Ludii Forum
Troubleshooting promotion in shogi games - Printable Version

+- Ludii Forum (https://ludii.games/forums)
+-- Forum: Problems (https://ludii.games/forums/forumdisplay.php?fid=5)
+--- Forum: Grammar Problems (https://ludii.games/forums/forumdisplay.php?fid=24)
+--- Thread: Troubleshooting promotion in shogi games (/showthread.php?tid=384)



Troubleshooting promotion in shogi games - castle - 01-23-2021

I'm building 'Tori shogi' to learn Ludii grammar (obviously heavily recycling Ludii's shogi implementation). For some reason, I can't get the game the game to follow promotion rules (e.g. restricting how many pawns are allowed in a column). As far as I can tell, I'm using the same rule structure as the original shogi so I must be missing something pretty obvious.

Full file:
Code:
// todo: triple pawn issue, icons, rule audit, mapping, QA, history, submission
// Methods pulled/modified from official 'Shogi' and 'Taikyoku shogi'


(define "CapturePiece"
    (apply
        (if (is Enemy (who at:(to)))
            (add
                (piece (mapEntry "Captured" (what at:(to))))
                (to (mapEntry "Where" (what at:(to))))
            )
        )
    )
)

(define "NextCannotMove"
    (not (can Move (do (forEach Piece Next) ifAfterwards:(not ("IsInCheck" "lion" Next))) ))
)

// broken
(define "OnePawnPerColumn"
    (=
        (count Sites in:(sites Occupied by:Mover container:"Board" component:"duck"))
        (count Sites in:(difference (sites Occupied by:Mover container:"Board" component:"duck") (sites Column (column of:(to)))))
    )
)

//ditching
(define "PlaceSwallow"
    (do
        (move
            (from (sites Occupied by:Mover container:"Hand" component:"duck"))
            (to (difference (sites Empty) (sites Mover "LastRank"))
                //if:"TwoSwallowPerColumn"
            )
        )
        ifAfterwards:(not (and ("IsInCheck" "lion" Next) ("NextCannotMove")))
    )
)

(define "InPromotionZone"
    (is In #1 (sites Mover "Promotion"))   
)

(define "InLastRank"
    (is In #1 (sites Mover "LastRank"))   
)

(define "InTwoFurthestRank"
    (is In #1 (sites Mover "TwoFurthestRank"))   
)

(define "Promote"
    (move Promote (last To) (piece (mapEntry "Promoted" (what at:(last To)))))   
)

(define "CanPromote"
    (then
        (if
            (or ("InPromotionZone" (last To)) ("InPromotionZone" (last From)))
            (moveAgain)
        )
    )
)

(define "SlideMove"
    (move
        Slide
        #1
        (to if:(is Enemy (who at:(to))) "CapturePiece")
        #2
    )      
)

// This version allows you to define limits; needed for 'Eagle'
(define "SlideMoveAlt"
    (move
        Slide
        #1
        #2
        (to if:(is Enemy (who at:(to)))
        "CapturePiece")
        #3
    )
)

(define "StepMove"
    (move
        Step
        #1
        (to if:(or (is Empty (to)) (is Enemy (who at:(to)))) "CapturePiece")
        #2
    )      
)

(define "HopMove"
    (move
        Hop
        #1
        (between
            if:true
        )
        (to
            if:(or (is Empty (to)) (is Enemy (who at:(to))))
            (apply (if (is Enemy (who at:(to))) (remove (to))))
        )
        #2
    )
)

//------------------------------------------------------------------------------


(game "Tori shogi" 
    (players {(player N) (player S)}) 
   
    (equipment {
        (board (square 7))

        // Phoenix - King
        (piece "lion" Each ("StepMove"))
       
        // Swallow - Pawn
        // (piece "duck" Each ("StepMove" (directions {Forward}) "CanPromote"))
        (piece "duck" Each
            ("StepMove"
                Forward
                (then
                    (if ("InPromotionZone" (last To))
                        (if ("InLastRank" (last To))
                            ("Promote")
                            (moveAgain)
                        )
                    )
                )
            )
        )

        // Goose (promoted Swallow)
        (piece "goose" Each ("HopMove" (directions {FL FR Backward})))

        // Falcon
        (piece "fox" Each ("StepMove" (directions {BL Leftward FL Forward FR Rightward BL}) "CanPromote"))

        // Eagle (promoted Falcon)
        (piece "wolf" Each
            (or {
                ("StepMove" (directions {Leftward Forward Rightward}))
                ("SlideMove" (directions {FL FR Backward}))
                ("SlideMoveAlt" (directions {BL BR}) (between (max 2)))
            })
        )

        // Crane
        (piece "snake" Each ("StepMove" (directions {BL FL Forward FR BL Backward})))

        // Pheasant
        (piece "jaguar" Each
            (or
                ("StepMove" (directions {BL BR}))
                ("HopMove" (directions {Forward}))
            )
        )

        // Quail, right
        (piece "hex" Each
            (or
                ("StepMove" (directions {BL}))
                ("SlideMove" (directions {Forward BR}))
            )
        )

        // Quail, left
        (piece "hexE" Each
            (or
                ("StepMove" (directions {BR}))
                ("SlideMove" (directions {Forward BL}))
            )
        )


        (regions "LastRankP1" P1 (sites Top))
        (regions "LastRankP2" P2 (sites Bottom))
        (regions "TwoFurthestRankP1" P1 (expand (sites Top)))
        (regions "TwoFurthestRankP2" P2 (expand (sites Bottom)))
        (regions "Promotion" P1 (expand (sites Top) steps:1))
        (regions "Promotion" P2 (expand (sites Bottom) steps:1))

        (map "Where" {
            (pair (id "duck" P1) (handSite P2))
            (pair (id "duck" P2) (handSite P1))
            (pair (id "goose" P1) (handSite P2))
            (pair (id "goose" P2) (handSite P1))            
            (pair (id "fox" P1) (handSite P2 1))
            (pair (id "fox" P2) (handSite P1 1))
            (pair (id "wolf" P1) (handSite P2 1))
            (pair (id "wold" P2) (handSite P1 1))
            (pair (id "snake" P1) (handSite P2 2))
            (pair (id "snake" P2) (handSite P1 2))
            (pair (id "jaguar" P1) (handSite P2 3))
            (pair (id "jaguar" P2) (handSite P1 3))
            (pair (id "hex" P1) (handSite P2 4))
            (pair (id "hex" P2) (handSite P1 4))
            (pair (id "hexE" P1) (handSite P2 5))
            (pair (id "hexE" P2) (handSite P1 5))
        })

        (map "Captured" {
            (pair (id "duck" P1) (id "duck" P2))
            (pair (id "duck" P2) (id "duck" P1))
            (pair (id "goose" P1) (id "duck" P2))
            (pair (id "goose" P2) (id "duck" P1))
            (pair (id "fox" P1) (id "fox" P2))
            (pair (id "fox" P2) (id "fox" P1))
            (pair (id "wolf" P1) (id "fox" P2))
            (pair (id "wolf" P2) (id "fox" P1))
            (pair (id "snake" P1) (id "snake" P2))
            (pair (id "snake" P2) (id "snake" P1))
            (pair (id "jaguar" P1) (id "jaguar" P2))
            (pair (id "jaguar" P2) (id "jaguar" P1))            
            (pair (id "hex" P1) (id "hex" P2))
            (pair (id "hex" P2) (id "hex" P1))
            (pair (id "hexE" P1) (id "hexE" P2))
            (pair (id "hexE" P2) (id "hexE" P1))
        })

        (map "Promoted" {
            (pair (id "duck" P1) (id "goose" P1))
            (pair (id "duck" P2) (id "goose" P2))
            (pair (id "fox" P1) (id "wolf" P1))
            (pair (id "fox" P2) (id "wolf" P2))
        })

        (hand Each size:7)
       
    })

    (rules

        (start {
            (place "fox1" coord:"D2")
            (place "hexE1" coord:"A1")
            (place "jaguar1" {"B1" "F1"})
            (place "snake1" {"C1" "E1"})
            (place "lion1" coord:"D1")
            (place "hex1" coord:"G1")
            (place "duck1" {"E4" "A3" "B3" "C3" "D3" "E3" "F3" "G3"})

            (place "fox2" coord:"D6")
            (place "hexE2" coord:"G7")
            (place "jaguar2" {"B7" "F7"})
            (place "snake2" {"C7" "E7"})
            (place "lion2" coord:"D7")
            (place "hex2" coord:"A7")
            (place "duck2" {"C4" "A5" "B5" "C5" "D5" "E5" "F5" "G5"})
        })
       
        (play
            (if ("SameTurn")
                (or
                    ("Promote")
                    (move Pass)
                )
                (do
                    (or {
                        (move
                            (from (sites Occupied by:Mover container:"Hand" components:{"duck" "fox" "snake" "jaguar" "hex" "hexE"}))
                            (to (sites Empty))
                        )
                        (do
                            (move
                                (from (sites Occupied by:Mover container:"Hand" component:"duck" ))
                                (to (difference (sites Empty) (sites Mover "Promotion") )
                                    if:"OnePawnPerColumn"
                                )
                            )
                            ifAfterwards:(not (and ("IsInCheck" "lion" Next) ("NextCannotMove")))
                        )
                        (forEach Piece)
                    })
                    ifAfterwards:(not ("IsInCheck" "lion" Mover))
                )
            )
        )

        (end
           {
            (if (and
                    ("IsInCheck" "lion" Next)
                    ("NextCannotMove")
                )
                (result Mover Win)
            )
            (if (no Moves Next) (result Mover Win))
            }
        )
   
    )
)

(metadata
   
    (info
        {
        (description "Tori shogi ...")
        (aliases {"Tori-Shogi"})
        (rules "Pieces move as follows: Pheonix(1): moves one space in any direction ... Sparrow(9): moves one space forward. Pieces are promoted when reaching the opposite last two rows of the board. Pieces are captured when an opponent's piece moves to the space it occupies. Captured pieces are held and can re-enter the game under the control of the capturing player as their turn. The goal is to capture the other player's Pheonix.")
        (source "NAMES YEAR: PAGES.")
        (version "1.1.12")
        (classification "board/war/shogi")
        (credit "James Gimbi")
        (origin  "This game was played in COUNTRY, around YEAR.")
        }
    )

    (graphics {
        (player Colour P1 (colour White))
        (player Colour P2 (colour White))
        (board Style Shogi)
        (piece Reflect P2 vertical:true horizontal:true)
        (piece Colour "goose" strokeColour:(colour Red))
        (piece Colour "wolf" strokeColour:(colour Red))
        (piece ExtendName P2 piece:"lion" "1")
    })

)


Any ideas what I might be missing?

Edit: swapped link for in-line code block


RE: Troubleshooting promotion in shogi games - Eric Piette - 01-26-2021

Hi,

Can you be more précised about exactly what you try to do but does not work (the best would be to send us a trial finishing by the incorrect move and what you expect it to do) and send us the full rules of that game (because I do not know it).

Regards,
Eric


RE: Troubleshooting promotion in shogi games - castle - 01-31-2021

Happy to, Eric. I am using the rules from wikipedia (https://en.wikipedia.org/wiki/Tori_shogi)

Off the bat, I got my wires crossed in my original post. I meant to ask about drops; not promotion. Sorry for the goof.

Like shogi, tori shogi restricts certain drops. For example, in shogi you cannot drop a pawn on a file that already has a pawn. Tori shogi has a similar rule ("A swallow [pawn] cannot be dropped into the same file (vertical column) as two other unpromoted swallows controlled by the same player.") So, the following move should not be allowed:

Code:
1. (Move E4-E5)
2. (Move D6-C6)
3. (Move 49/0-E4)

I hadn't worked through the logic for that rule, but the standard shogi rule (two pawns) is in my code doesn't appear to work either.

Full tori shogi drop rules here: https://en.wikipedia.org/wiki/Tori_shogi#Drops


RE: Troubleshooting promotion in shogi games - Eric Piette - 02-01-2021

Hi,

That's just because in that:

Code:
(move
      (from (sites Occupied by:Mover container:"Hand" components:{"Duck" "Fox" "Snake" "Jaguar" "Hex" "HexE"}))
      (to (sites Empty))
)


You are also including the "Duck", if you just remove it, that should work with the shogi rule (one pawn per column).

Of course you will have to update the define "OnePawnPerColumn" to the rule of your game (2 pawns per column I think).

Regards,
Eric