// Parry (define "SameTurn" (is Prev Mover)) (define "SitePowerPlayerAt" (- (* 2 (count Pieces of:#1 in:(sites Around #2 includeSelf:True))) (count Pieces All in:(sites Around #2 includeSelf:True)) )) (define "PlacementSites" // any neutral. (forEach (sites Empty) if:(< 0 ("SitePowerPlayerAt" (mover) (site))) )) (define "SitesUncontrolledEmpty" (difference (sites Empty) (sites (results from:(difference (sites Board) (sites Empty)) to:(sites Around (from) if:(and (is Empty (to)) (< 0 ("SitePowerPlayerAt" (who at:(from)) (to))) )) (to) )))) (define "SiteUntontrolledOccupiedBy" (difference (sites Occupied by:(player #1)) (sites (results from:(difference (sites Occupied by:All) (sites Occupied by:(player #1))) to:(sites Around (from) if:(and (= #1 (who at:(to))) (< 0 ("SitePowerPlayerAt" (who at:(from)) (to))) )) (to) )))) (define "PlayerTerritory" (forEach (sites Board) if:(or (< 0 ("SitePowerPlayerAt" #1 (site))) (and { // (< 0 ("SitePowerPlayerAt" #1 (site))) // optimization - after removing some options this no longer optimises - instead it causes a logic error... (= #1 (who at:(site))) // helps optimize (is In (site) ("SiteUntontrolledOccupiedBy" #1)) // heavy processing on small number of cases } )))) (define "SetScores" (forEach Player (set Score (player (player)) (max 0 (size Array (array ("PlayerTerritory" (player)))) )))) (define "MoveAddPriority" (priority // { (move Add (to (#1) (apply (set Var "PlacedPiece" (to))) )) (move Add (to (#2) (apply (set Var "PlacedPiece" (to))) )) // } (then (set Value Mover (max 0 (- ("SitePowerPlayerAt" (mover) (last To)) 1)) // -1 because of the includeSelf in the power at Site. (then (if (>= 0 (value Player Mover)) ("SetScores") (and ("SetScores") (moveAgain) ))))))) (define "MoveUntilDone" (or (move Pass (then ("SetScores")) ) (do (set Value Mover (- (value Player Mover) 1)) next:(forEach Piece (move Step (from if:(!= (from) (var "PlacedPiece"))) (to if:(is Empty (to))) (then (if (>= 0 (value Player Mover)) ("SetScores") (moveAgain) ))))))) //--------------------------------------- // Main routine //--------------------------------------- (game "Parry" (players ) (equipment { (board use:Vertex) (piece "Ball" Each) } ) (rules (meta (no Repeat PositionalInTurn)) // Positional)) (start { (set Score Each 1) //(max (array (sites Board)))) } ) (play (if "SameTurn" ("MoveUntilDone") ("MoveAddPriority" "PlacementSites" "SitesUncontrolledEmpty" // fairly rare, but heavy. ))) (end { (if (and { "EndCondition" (= 2 ) (= (score P1) (score P2)) (= (id P1) (what at:(var "PlacedPiece"))) } ) (result P1 Win) ) (if (and { "EndCondition" (= 2 ) (= (score P1) (score P2)) (!= (id P1) (what at:(var "PlacedPiece"))) } ) (result P2 Win) ) (if "EndCondition" (byScore) ) } ) ) ) (define "EndCondition" (or (no Moves Next) (all Passed) )) //--------------------------------------- (option "Number of players" args:{