Spreading Poison

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
JustNatan
Posts: 34
Joined: September 17th, 2020, 6:07 pm

Spreading Poison

Post by JustNatan »

Hey,
for a very specific scenario I want to have poison spreading.

Code: Select all

Forall units.status_poisoned
	poison_nearby_friendly_units
I tried to do this by using wml:
https://forums.wesnoth.org/viewtopic.php?t=48985
https://wiki.wesnoth.org/FilterWML
https://wiki.wesnoth.org/FilterWML/Exam ... use_Filter

Code: Select all

[event]
    name="side turn"
    first_time_only=no
    #this filter works; I've tested it with other commands
    [filter]
      side=$side_number
      [filter_wml]
        [status]
          poisoned=yes
        [/status]
      [/filter_wml]
    [/filter]
    
    #doesnt work properly; I think because of the filter
    [modify_unit]
      [filter]
      # Finds teammates with with the advancing unit next to them.
        side=$unit.side
        [filter_adjacent]
          id=$unit.id
        [/filter_adjacent]
      [/filter]
      hitpoints=1
    [/modify_unit]
[/event]
Any ideas (yea it would be better to define a custom status, but that looks very unhandy so I take a cheap solution and then just limit the scenario to only few poisoning units)
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Spreading Poison

Post by Helmet »

I've not done anything similar to what you're trying to do, but it looks to me like your code is trying to poison a side, instead of units. You may need to store, poison, and unstore all the adjacent units in the targeted side. You might investigate that idea while waiting for an experienced coder to pipe in.
JustNatan
Posts: 34
Joined: September 17th, 2020, 6:07 pm

Re: Spreading Poison

Post by JustNatan »

Hey @Helmet I am not really sure about this since in the topic above someone describes the part I use up there as "working" (first link in initial post). The grabbing of all poisoned units works fine, but I think what doesnt work is that "all poisoned units" is a set/sum/aggregate or however wesnoth may call it of units instead of a single unit and instead of automatically applying the effect to all units it fails to do anything meaningful (since unit.id is unclear).

If I would write this in another language I would try something like:

Code: Select all

adjacentUnits = []

foreach unit in AllUnits
	if unit.isPoisoned
		adjacentUnits.add(unit)
		
foreach unit in adjacentUnits
	unit.setPoisoned = true
This is of course very simple pseudo-code but I think one can understand what I mean ;)

If you don't know how to do it, don't worry thanks for your help anyway!
vghetto
Posts: 357
Joined: November 2nd, 2019, 5:12 pm

Re: Spreading Poison

Post by vghetto »

Hi,

I don't think side turn events take filters.

This might be what you're after, or close to it.

Code: Select all

[event]
        name="side turn"
        first_time_only=no

        [modify_unit]
                [filter]
                        side=$side_number
                        [not]
                                status=poisoned
                        [/not]
                        [filter_adjacent]
                                status=poisoned
                                [filter_side]
                                        [allied_with]
                                                side=$side_number
                                        [/allied_with]
                                [/filter_side]
                        [/filter_adjacent]
                [/filter]

                # Apply poisoned effect
                [effect]
                        apply_to=status
                        add=poisoned
                [/effect]
        [/modify_unit]
[/event]
I didn't test this, let us know if it works.

Edit:
The filter_side tag can be further simplified with is_enemy=no instead filter_side and allied_with
Last edited by vghetto on December 9th, 2020, 10:03 pm, edited 1 time in total.
User avatar
WhiteWolf
Forum Moderator
Posts: 739
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Spreading Poison

Post by WhiteWolf »

Just because you specifically said "this filter works" in your first post, I must comment: that filter doesn't do anything. It's a side turn event, that doesn't take a unit filter. Btw, even the side=$side_number doesn't really make sense. Stored event variables are not available at filter level, because they are created at the time when they are first accessed in the event. (For that, the event must start executing).

Actually, I think your pseude-code is also wrong. You search for poisoned units, then add them to a list of some kind, and then just poison the poisoned ones again. (Works in Gwent probably :D :D )
The trick is to search for the adjacent units, and that's the trick here too, but it's not very difficult thanks to the [filter_adjacent] tag. Do this in your event:

Code: Select all

[store_unit]
    [filter]
        [filter_adjacent]
           status=poisoned # yes, the [filter_wml] way works too but it's slower.
        [/filter_adjacent]
    [/filter]
    variable=spread_poison
[/store_unit]


{FOREACH spread_poison i}
    {MODIFY_UNIT id=$spread_poison[$i] status.poisoned yes}
{NEXT i}
{CLEAR_VARIABLE spread_poison}
You should probably use the more robust [foreach] tag instead of the old {FOREACH} macro (I'm just someone who refuses to go on and always uses the old syntax). If might also be a better idea to use a [modify_unit][effect] to apply the poison instead of directly editing the status with {MODIFY_UNIT}.

EDIT: vghetto's code in the earlier post is better than mine, it works on the same principle, but it's more concise.
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
JustNatan
Posts: 34
Joined: September 17th, 2020, 6:07 pm

Re: Spreading Poison

Post by JustNatan »

First thank you @vghetto! Your solution works like a charm (with and without edit; even though the edit is nicer of course)

I would like to explain your code back to you, so I can make sure that I understand it right in order to enable me to do similar stuff on my own in the future...

Code: Select all

On every side turn
modify all units where side=currentSide
unit is not poisoned
and there is an adjacent unit
and that unit is poisoned and not_enemy
and modify it with the effect: add poison to status
is that right more or less? Is there a major advantage of filtering by going through not poisoned units? Is it just simpler in WML?

@WhiteWolf
Ye, you right ^^ that pseudo-code was garbage! Tbh I didn't gave it much thought, because I think my problem wasn't a structural one, but just me being new to WML. (I could argue though that I never defined add, but let's be honest :P )

You claim that my filter up there doesn't do much which is right in it's context, but the context is given by the first link in the initial post. I just tested the filter in a different structure:

Code: Select all

  [event]
      name="side turn"
      first_time_only=no
      [modify_unit]
          [filter]
              side=$side_number
              [filter_wml]
                  [status]
                      poisoned=yes
                  [/status]
              [/filter_wml]
          [/filter]
      side=$unit.side
      [/modify_unit]
  [/event]
  
This one ;) where it works.

I could've been more precise saying that I only know that the filter works; not if it is in the right place.

I am still very new to WML so I mostly work with what I find online tinkering around, seeing what works and what doesn't.

Thanks for all your help (to all of you)!
vghetto
Posts: 357
Joined: November 2nd, 2019, 5:12 pm

Re: Spreading Poison

Post by vghetto »

JustNatan wrote: December 9th, 2020, 10:36 pm is that right more or less? Is there a major advantage of filtering by going through not poisoned units? Is it just simpler in WML?
Yes, you got it. I excluded the already poisoned to reduce the iteration size. It might not matter much in terms of performance.
User avatar
Ravana
Forum Moderator
Posts: 2482
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Spreading Poison

Post by Ravana »

JustNatan wrote: December 9th, 2020, 8:04 pm If I would write this in another language I would try something like:

Code: Select all

adjacentUnits = []

foreach unit in AllUnits
	if unit.isPoisoned
		adjacentUnits.add(unit)
		
foreach unit in adjacentUnits
	unit.setPoisoned = true
If you are familiar with that kind of languages, it might be suitable to implement some logic with Lua. https://wiki.wesnoth.org/LuaWML
JustNatan
Posts: 34
Joined: September 17th, 2020, 6:07 pm

Re: Spreading Poison

Post by JustNatan »

Hey,
@Ravana
maybe this is an option. I haven't done much with lua yet, but I might give it a go :)

I feel more and more like wesnoth is either very badly documented or I am very stupid...

I tried to switch 'name="side turn"' to 'name="turn end"'. Both set the variable side_number to the current side (turn end before switching) so I thought this would move my poison spreading effect to end of turn. But now nothing happens.

I feel like Wesnoth doesn't give a lot of feedback; or do I have to activate a debug_mode or something like that?

Full code:

Code: Select all

[event]
    name="turn end"
    first_time_only=no

    [modify_unit]
            [filter]
                    side=$side_number
                    [not]
                            status=poisoned
                    [/not]
                    [filter_adjacent]
                            status=poisoned
                            is_enemy=no
                    [/filter_adjacent]
            [/filter]

            # Apply poisoned effect
            [effect]
                    apply_to=status
                    add=poisoned
            [/effect]
    [/modify_unit]
[/event]
User avatar
lhybrideur
Posts: 174
Joined: July 9th, 2019, 1:46 pm

Re: Spreading Poison

Post by lhybrideur »

Maybe $side_number is initialized in side turn and not in turn end
User avatar
WhiteWolf
Forum Moderator
Posts: 739
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Spreading Poison

Post by WhiteWolf »

turn end fires once at the end of the whole turn, when the last side passes. You probably didn't get to that point in your test, that's why you didn't see anything at all. You want side turn end for this application ;)

$side_turn, (and all prestored event variables as far as I know), are initialized when they are first accessed in the respective event. So that's not a problem.

Wesnoth's documentation is here: https://wiki.wesnoth.org/Referencewml
There's a list of all the tags in the right pane, whenever in doubt of how something works, just check it - it's got all keys and their behaviour explained. (The number and quality of examples could indeed be improved though.)

To be honest, the easiest way to debug stuff is the equivalent of printf("does it get to this pont?"):

Code: Select all

[message]
    speaker=narrator
    message= _ "Game, tell me if we got to this point in the code or not."
[/message]
Works every time. Also see this topic for tips on debugging WML.
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Spreading Poison

Post by Helmet »

JustNatan wrote: December 11th, 2020, 10:42 am I feel more and more like wesnoth is either very badly documented or I am very stupid...
It took me a while to learn how to use the WML Wiki. The information presented is concise, literal, deficient in examples, and presupposes that you understand a lot about about WML and have memorized the acronyms and definitions for terms. However, once you get to a certain point in your self-education with WML, the Wiki becomes very helpful. It is almost never wrong about anything. I can't count the number of times I went back to the Wiki after solving a problem, thinking the Wiki misled me, only to discover that I had not read a passage carefully enough.

I think a lot of people collect their own code examples in a file, as a supplement to the Wiki.
Shiki
Developer
Posts: 317
Joined: July 13th, 2015, 9:53 pm
Location: Germany

Re: Spreading Poison

Post by Shiki »

Helmet wrote: […]
I've had this thought for a while in mind … I think what is missing is a new landing page in the wiki for people who are new here, which tells where to start. Maybe you guys want to write one? You're new enough to know what is missing.

What I feel what is missing:
- telling people how to use their computer: Installing an editor, getting syntax highlighting, installing python, opening a terminal, how to start wesnoth with the `-d` flag.
- A hint about how to debug: the existence of `:ínspect` for example.
- Explaining the difference between the preprocessor and WML. It's not a big deal, but unless one know this, a lot of things remain unclear later on. It's not the first thing one needs to know though …
- The difference between code which is just data and code which is code … or in other words, explaining events. (Someone did that pretty good in one of the threads here recently)

Personally, I made some notes over the last year to come up with a how to get into Lua page.
Try out the dark board theme.
JustNatan
Posts: 34
Joined: September 17th, 2020, 6:07 pm

Re: Spreading Poison

Post by JustNatan »

WhiteWolf wrote: December 11th, 2020, 11:53 am turn end fires once at the end of the whole turn, when the last side passes. You probably didn't get to that point in your test, that's why you didn't see anything at all. You want side turn end for this application ;)
I just tried again (the old version), because I was really sure that I got to the point where the last side passes and again it didn't work. I assume that "last side passes" means: The last side passes and the turn counter is incremented.
Your version on the other hand works; but I don't know why the "turn end" doesn't. It doesn't make a lot of a difference to me tbh I am fine with both solutions; and probably "side turn end" is fairer.
WhiteWolf wrote: December 11th, 2020, 11:53 am Wesnoth's documentation is here: https://wiki.wesnoth.org/Referencewml
There's a list of all the tags in the right pane, whenever in doubt of how something works, just check it - it's got all keys and their behaviour explained. (The number and quality of examples could indeed be improved though.)
This actually helped a little, not because I've never seen the wml pages of wesnoth, but because it shows some kind of structure I haven't seen before.
Helmet wrote: December 11th, 2020, 1:50 pm It took me a while to learn how to use the WML Wiki. The information presented is concise, literal, deficient in examples, and presupposes that you understand a lot about about WML and have memorized the acronyms and definitions for terms.
But this is not enough to constitute a good documentation. But I guess I have to lower my expectations since it's a non-commercial project after all :) (examples for good documentation: Documentation of supercollider (the linking system in the supercollider IDE is great), bootstrap https://getbootstrap.com/docs/4.1/getti ... roduction/ documentation or spring boot probably as well https://docs.spring.io/spring-boot/docs ... tmlsingle/. You can also name stuff like hoogle https://hoogle.haskell.org/ there are a lot of examples)
Shiki wrote: December 11th, 2020, 4:27 pm What I feel what is missing:
- telling people how to use their computer: Installing an editor, getting syntax highlighting, installing python, opening a terminal, how to start wesnoth with the `-d` flag.
- A hint about how to debug: the existence of `:ínspect` for example.
- Explaining the difference between the preprocessor and WML. It's not a big deal, but unless one know this, a lot of things remain unclear later on. It's not the first thing one needs to know though …
- The difference between code which is just data and code which is code … or in other words, explaining events. (Someone did that pretty good in one of the threads here recently)
For me it's
-One example for every piece of code. (by having one page/tag(I am not sure how it's called in wesnoth))
-More explicit explanations and better structure (by having one page/tag(I am not sure how it's called in wesnoth))
-A Guide for everything
-Common mistake list
-Best practice routines
-Q&A of most common questions

But also: If a filter cannot be interpreted by wesnoth, just throw an error!

Tbh my syntax highlighting is prob. not the best I use Visual Studio Code with WML 1.07 by Aaron Winter.
What do you need python for when coding for wesnoth (I don't know much about wesnoth's internal structure)?

--
Anyway, probably it's just me feeling bad about having to ask you guys so many questions cause I can't figure it out on my own for some reason ;)
User avatar
WhiteWolf
Forum Moderator
Posts: 739
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Spreading Poison

Post by WhiteWolf »

JustNatan wrote: December 11th, 2020, 5:02 pm I assume that "last side passes" means: The last side passes and the turn counter is incremented.
That's correct, turn end fires just before the turn counter is incremented. Maybe it didn't work because the last side didn't have any poisoned units? Keep in mind that the code still has $side_number in it, which at "turn end" equals to the last side, and the code only runs for that one.
But also: If a filter cannot be interpreted by wesnoth, just throw an error!
If you run wesnoth in a terminal on linux, there's logs in it. It's also outputted to some log.txt on windows (I don't know where, someone will need to clarify the exact location). Those logs do contain these types of warnings. But there is no way for Wesnoth to tell you problems with stuff that is not syntactically wrong. No programming language compiler can do that.
Tbh my syntax highlighting is prob. not the best I use Visual Studio Code with WML 1.07 by Aaron Winter.
What do you need python for when coding for wesnoth (I don't know much about wesnoth's internal structure)?
There's a collection of syntax highlighters that people use for various editors in this topic.
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
Post Reply