Ludii Forum
(forEach Group) - 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: (forEach Group) (/showthread.php?tid=219)



(forEach Group) - Michael - 10-27-2020

This question is meant to replace the one asked here. I'm having issues with the new ludeme (forEach Group). I have made a simpler version of what I'm trying to do which should illustrate my issue a bit better.

In the attached game the score is calculated when a pass is followed by a pass. A player's score is supposed to be the sum of the value of of each of that player's groups, and the value of a group is the square of the number of stones in it. So a size 1 group has value 1, a size 2 group has the value 4, and so on (|3|=>9, |4|=>16, |5|=>25 …). If I have 2 groups of size 5, my score should be (+ (* 5 5) (* 5 5)). If I had understood the new ludeme correctly, the formula should be

Code:
(define "CalculateScore"
    (forEach Group Orthogonal if:true
        (and
            (addScore P1
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                )
            )
            (addScore P2
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                )
            )
        )
    )
)
But this does not give the expected result. I expected that this code would go through each group and add to the relevant player's score the square of the number of that player's stones in that group (so 0 is added for each group that belongs to the other player).

I'm wondering what it is I am misunderstanding.


RE: (forEach Group) - Eric Piette - 10-28-2020

Hi Michael,

In the condition of your group you have "if:true" Consequently the empty sites, the sites occupied by P1 and the sites occupied by P2 all in the same group.

To do what you expect you need to call two times (forEach Group ...) in an (and ...) for each player.

Something like that should work in the last release version (1.1.0) released tomorrow.


Quote:(define "CalculateScore"
    (and
        (forEach Group Orthogonal if:(= (who at:(to)) P1)
            (addScore P1
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                )
            )
           
        )
        (forEach Group Orthogonal if:(= (who at:(to)) P2)
            (addScore P2
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                )
            )
        )
    )
)


In the version you are using now (8 or 9), you have to handle the (from) too (was in these versions the first site found in each group, but that's pointless, no need in the next version), so for the condition something like 


Code:
(or
   (= (who at:(from)) P1)
   (= (who at:(to)) P1)
)


Regards,
Eric


RE: (forEach Group) - Michael - 10-28-2020

Thank you, Eric!

Still, this does not give the expected result:
Code:
(define "CalculateScore"
    (and
        (forEach Group Orthogonal
            if:(or
                    (= (who at:(from)) P1)
                    (= (who at:(to)) P1)
                )
            (addScore P1
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P1))
                    )
                )
            )
        )
        (forEach Group Orthogonal
            if:(or
                    (= (who at:(from)) P2)
                    (= (who at:(to)) P2)
                )
            (addScore P2
                (*
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                    (count Sites
                        in:(intersection (sites) (sites Occupied by:P2))
                    )
                )
            )
        )
    )
)
(I'm guessing I don't need to take the intersection with sites occupied by the player when using the if-parameter correctly, but I have left it in place.)

In the attached .lud, white has a 3-group and a 2-group, while black has two 2-groups. If both players pass white should win with 13 [9+4] points over black's 8 [4+4] points. What happens, though, is that white gets 25 and black 16. I don't get it. What am I doing wrong?


RE: (forEach Group) - Eric Piette - 10-29-2020

Hi,

OK I checked you can not used the


Code:
(or
  (= (who at:(from)) P1)
  (= (who at:(to)) P1)
)


in your version because the (from) condition is always true when it reaches a site satisfying the condition (only the (to) changes). But if you use in the version I put at the beginning with the version 1.1.0 (release during the day), that works at you expect.

Sorry for the suggestion with the version 8 or 9, my mistake ;)

And yes, the intersection with the occupied sites is now useless.

My working version of this define is:

Code:
(define "CalculateScore"
    (and
        (forEach Group Orthogonal
            if:(= (who at:(to)) P1)
            (addScore P1
                (*
                    (count Sites
                        in:(sites)
                    )
                    (count Sites
                        in:(sites)
                    )
                )
            )
        )
        (forEach Group Orthogonal
            if:(= (who at:(to)) P2)
            (addScore P2
                (*
                    (count Sites
                        in:(sites)
                    )
                    (count Sites
                        in:(sites)
                    )
                )
            )
        )
    )
)


Regards,
Eric