Ludii Forum
(do next:(if)) - Printable Version

+- Ludii Forum (https://ludii.games/forums)
+-- Forum: Questions (https://ludii.games/forums/forumdisplay.php?fid=13)
+--- Forum: About the Ludii Grammar (https://ludii.games/forums/forumdisplay.php?fid=15)
+--- Thread: (do next:(if)) (/showthread.php?tid=1188)



(do next:(if)) - Michael - 08-26-2022

Consider a ludeme with this shape:
Code:
(do
    ("Something")
    next:(if
        ("Condition")
        ("Consequence")
    )
)

If ("Condition") evaluates to False, ("Something") is not called. 


My question is: Is this how it has always worked?

I seem to remember it working differently. More like this (but without an explicit pass in the move notation):
Code:
(do
    ("Something")
    next:(if
        ("Condition")
        ("Consequence")
        (pass)
    )
)
In this case, ("Something") is called no matter what ("Condition") evaluates to.


RE: (do next:(if)) - Eric Piette - 08-26-2022

Hi,

Yes, that's working exactly like you said.
The next "Moves" has to return something for the "do" to be applied.

Regards,
Eric


RE: (do next:(if)) - Michael - 08-26-2022

What is the idiomatic Ludii-way of doing what the following does, then?
Code:
(do
    ("Something")
    next:(if
        ("Condition")
        ("Consequence")
        (pass)
    )
)

Is that it?
The reason I wonder is that I find it strange that there isn't a ludeme for "first do this, if possible, then do this, if possible (regardless of whether the first thing happened or not)". It's such a natural way of composing ludemes, but neither (and) nor (do next:) work like this.. Maybe the new (seq {})?


RE: (do next:(if)) - Tester001 - 08-28-2022

As far as I understand it the 'and' ludeme has two functions so far: the natural logic one, and the functionality to enclose a list of ludemes.
I guess the new (seq{}) was introduced to clarify this ambiguity. 
And maybe in some future version the and-ludeme will be used for the logic part only.

In the game I submitted recently I used the (do next:(if)) construction, too.
But only because it did what I wanted it to do when nothing else i tried worked.
Actually I tried to simplify it later but didn't find anything better (there always were issues regarding decision & non-decision moves..),
So I'm also interested in what would be a more idiomatic way of doing this.


RE: (do next:(if)) - dale walton - 08-29-2022

Does every move X ludeme handle consequences the same way? i.e.  if there is a conditional apply in X where some action Y is taken if condition Z is true, is Move X handled the same way when Z is false for all X, Y, and Z? e.g. (forEach) has a NoMovesYet parameter..., but do some combinations default to executing the move without the condition, or is it consistently not executed?

How about for (and) ?

My understanding of (seq) is that it is a shortcut for concatenating move ... then ... move ... then ... move... constructions - which can make it easier to construct defines, but still enforces dependency. I don't know if this is correct. It could be helpful to have an "(ifPossible" <move> <then>)  ludeme to use within a consequence chain. - I perhaps could use (priority {1 argument} (then ...)) for this purpose, or if not at least: (priority (1 argument (then (or {the others}))) (or {the others}) but that is not what priority is intended for I think.
-- I understand the intent of the language is to encourage script designs that can be parallelized as much as possible when compiled, but some games do need this kind of option.


RE: (do next:(if)) - Eric Piette - 08-29-2022

Hi,

The ludeme (seq ...) is slightly different. It applies each move one by one, yes, but each move will use the new state created by the previous move applied in the sequence. I will add this clarification in the documentation.

The (and ...) ludeme is used to apply the full list of moves generated by a Moves ludeme before the next one. Without to take in account the modification of the state in between.

A (then ...) ludeme (so a consequence Moves) will use a temporary state after applying the move decided by the player to compute the ludemes and then applying them. The most important to remember with a consequence move is the use of the ludeme (last ...) to have a reference to the `from' and `to' location just used by the player. Other variables can also be used, of course.

The (do ...) ludeme can be used in different ways. With a next:, it will apply the do Moves only if the next Moves computed is not empty. With a ifAfterwards: I will apply a move only if the condition defined is true after applying the move.

It is true, that it would be possible to apply a (seq ...) ludeme no taking in account the state reached by each move. However, this can be obtained in doing what you said with just adding a pass move (always reached) in the (do ....) moves.
If you have an example of a situation in a game that you think this can be done with this. Let me know to think about it :)

Eric


RE: (do next:(if)) - dale walton - 08-30-2022

Thanks for the response, it is very helpful.

RE:The ludeme (seq ...) is slightly different. It applies each move one by one, yes, but each move will use the new state created by the previous move applied in the sequence. I will add this clarification in the documentation.

What happens if a move in the (seq) arguments cannot be applied and/or has no result (no effect on the game state)?

A flow chart of how the language handles such non-results and false conditions when multiple consequences are to be made in parallel, in sequence, if-possible-in-sequence, if-possible-and-parallel, and how this flow recurses, would help in us diagnosing when a bug is likely in our own script (and where) or when the behavior doesn't match the intended paradigm of the language, and is a language bug.


RE: (do next:(if)) - Eric Piette - 08-30-2022

For (seq ...), each move generated in each Moves ludeme is applied one after the other. So if a Moves is not generated any moves, the sequence will stop there.


RE: (do next:(if)) - Michael - 08-31-2022

Thank you, Eric! This is very helpful.

It seems to me that a generic way of aggregating a number of ludemes so that the first is called if possible, then the second is called if possible no matter whether the previous was called, and so on … is this:

Code:
(seq {
    (or
        ("NondecisionA")
        (pass)
    )
    (or
        ("NondecisionB")
        (pass)
    )
    (or
        ("NondecisionA")
        (pass)
    )
})


Even if these nondecisions are conditional, the next one in the list will be called whether the last one was or not.


Does this look like idiomatic Ludii code to you?

No, wait.. That will call (pass) even if the nondesicion is called. So I guess it has to be
Code:
(seq {
    (priority
        ("NondecisionA")
        (pass)
    )
    (priority
        ("NondecisionB")
        (pass)
    )
    (priority
        ("NondecisionA")
        (pass)
    )
})



RE: (do next:(if)) - Eric Piette - 08-31-2022

Hi,

I never tried myself, but that sounds correct.
The easiest is to try with a simple example to be sure this does what you expected :)

Eric