// Scoring options (define "Scoring" // group scores plus the sum of pairwise players scores, excluding consideration of tied groups (cascade scoring) when scoring pairs. (if (all Passed) (do (forEach Player (remember Value "Scores" #1) ) next:(do (forEach Player (if ("Tied4FirstPlace" #1) (and (remember Value "Tied" (player)) (set Score Player #1) ) (set Score Player #1) ) ) next:(do (forEach Value (values Remembered "Tied") (forEach (players All if:(is In (player) (values Remembered "Tied"))) (addScore (player (player)) ) // can be "CascadeWins" "CascadeLoses" "StoneCount" "GroupCount" ) ) next:(forget Value "Scores" All (then (forget Value "Tied" All) ) ) ) ) ) (forEach Player (set Score Player #1)) ) ) (define "CascadeWins" (max 0 (- ("LargerGroup" (player) (value)) ("LargerGroup" (value) (player))))) (define "CascadeLoses" (max 0 (- ("LargerGroup" (value) (player)) ("LargerGroup" (player) (value))))) (define "LargerGroup" (max 0 (max (difference (sizes Group "ScoreConnection" of:#1) (sizes Group "ScoreConnection" of:#2) ) ) ) ) (define "Tied4FirstPlace" (= (#1) (max (difference (values Remembered "Scores") #1 // This is causing a non-fatal null pointer exception at compilation ) ) ) ) (define "GroupCount" (max 0 (max (sizes Group "ScoreConnection" of:#1))) ) (define "StoneCount" // change to score Most pieces placed (count Sites in:(sites Occupied by:Player)) // (forEach (sites Occupied) if:(= (who at:(site)) #1))) ) //---------------------------- (define "LessQtyAroundSiteThanAnother" (> (max 0 (count Pieces of:#1 in:(sites Around (site) "ConnectionDirection"))) (max 0 (count Pieces of:(mover) in:(sites Around (site) "ConnectionDirection"))) ) ) (define "Anemone" (or { (move Pass) (move Claim (to (sites Empty))) (forEach Site (difference (difference (sites Board) (sites Empty)) (sites Occupied by:Mover) ) (if ("LessQtyAroundSiteThanAnother" (who at:(site))) (move Remove (site) (then (claim (to (last To))) ) ) ) ) } (then ) ) ) //----------------------------------------------- // Main routine (game "Windflowers" (players ) (equipment { "BoardUsed" (piece "Ball" Each) }) (rules (start (set Score Each 0) ) (play "Anemone" ) (end (if (all Passed) (byScore) ) ) ) ) //------------------------------------------------- // Defines for Options (define "ScoreConnection" ) (define "ConnectionDirection" ) (define "BoardUsed" ) (define "HexLimp" (board (hex Limping (- 1)) use:Cell)) (define "Hex2Limp" (board (hex (- 1) (+ 1)) use:Cell)) (define "HexCell" (board (hex Hexagon ) use:Cell)) (define "TriSquare" (board (tiling T33434 (- 2)) use:Vertex)) (define "SquareGrid" (board (square ) use:Cell)) (define "SquareDiagonal" (board (square (- (* 2 ) 2)) use:Vertex)) //----------------------------------------- // Options // Notes: Opponent scoring on odd square diagonal grid leads to 1st player win by diagonals only. (option "Board Size" args:{ } { (item "3 (20 moves)" <3> <1.30> "Order 3 board") (item "4 (45 moves)" <4> <1.20> "Order 4 board")* (item "5 (75 moves)" <5> <1.15> "Order 5 board") } ) (option "Board Grid" args:{ } { (item "Hex Double Limping" <"Hex2Limp"> <"Disc"> "Hex N+1 / N-1 Grid") (item "TriSquare 7 direction majorities" <"TriSquare"> <"Disc"> "Triangle-Square N-2: Capture-compare all 7 adjacent directions. Scoring - groups connect only in the 5 edge-edge directions.")** (item "Square 8 direction majorities" <"SquareDiagonal"> <"Square-alt1"> "Square Grid 2N-2: Capture-compare all 8 adjacent directions. Scoring - groups connect only in the 4 edge-edge directions.") } ) (option "Scoring" args:{} { (item "Stone count" <("Scoring" ("StoneCount" (player)))> "Score a point for each stone placed.")*** (item "Largest group" <("Scoring" ("GroupCount" (player)))> "Score a point for each piece in your largest group") } ) (option "Tie Breaker" args:{} { (item "Cascading wins" <("CascadeWins")> "While ignoring paired groups of equal size, if your group is larger, augment your score by the difference between your largest group and the largest group for every tied opponent.") (item "Cascading loses" <("CascadeLoses")> "While ignoring paired groups of equal size, if your largest group is SMALLER, augment your score by the difference between your largest group and the largest group for every tied opponent.")*** } ) (option "Players" args:{} { (item "2" <2> "2 players")* (item "3" <3> "3 players") (item "4" <4> "4 players") } ) //--------------------------------------------- (define "ColourBackground" (colour 136 175 96)) //meadow (colour 146 175 86)) // tawny: (colour 175 146 86)) (metadata (info { (description "Windflowers is a finite, 2-4 player, place-or-capture, connectivity game. It is playable on a wide variety of grid and connectivity types. It is still experimental, as the best scoring and tiebreaker combination needs to be resolved. Also, more investigation is needed concerning the degree that king making will be a problem for the multiplayer version. Placement is to empty sites: Capture is by replacing an opponent's stone during placement if that opponent owns more of the surrounding stones than the moving player does. On boards with diagonals, diagonal connections are included in the count to determine if a piece can be captured, but are not used for determining scoring groups discussed below. Passing is allowed, and the game ends when all players have passed consecutively. The board typically is full at this point, but there might be capture options still available that are disadvantageous to take. Scoring has 2 options: Either scoring for stones placed, or for the largest group. Tie breakers scoring is needed to reduce the frequency of ties. multi-player cascade group scoring: Between those tied for winner, each pair of players is considered separately and the difference in size of their largest groups (after excluding all pairs of equal-size groups) is awarded to the owner of the larger group for cascade scoring (or to the owner of the smaller group for underdog scoring.) Underdog tie breaking is currently preferred. In 2-player games, the last player to place is the final tie-breaker. Finiteness: Each individual placement/capture is obviously finite as eventually one of the players with the smallest number of surrounding pieces will have placed there. Proof is needed that, as a whole, cycling is impossible, but this is what is experienced practically, even with multiple players. If every thing is equal, the last to play wins. Thus, on even boards, the first player is obligated to break mirror play to win. ---------------------- The previous version had the goal of least number of groups. This goal was flawed, allowing the simple strategy of always passing to force a win.") (rules "Choose between two versions: -- Place the most stones, or -- Form the largest group. Ties are broken by relying on a cascading comparison of largest groups; - With a standard choice of breaking the tie in favor of the underdog. The board starts empty. Players take turns in sequence. Passing is allowed. The game ends when all players have passed in succession. On a turn, the mover either: 1: Places a stone on an empty site, - or - 2: Replaces an opponent's stone with their own, ---- But replacing a stone is only allowed when there are more stones around that site of the captured stone's color than there are of the mover's own color. Note: On boards with diagonals, diagonally adjacent stones are part of the count used to allow or disallow capture. At the end of the game, players count all their stones, or count the stones in their largest group, depending on the goal. Which stones belong to a given group are determined by orthogonal connections. In the case of a tie between the leading players, each pair of those players compares the size of their largest remaining group after any tied pairs have been removed. This difference is added to the score of the player with the larger group in that pairing - (or to the score of other player in that pairing, in the case of underdog tie-breaking) The winner of the game is decided by these amended scores. Ties may still remain. Also ties between non-leading players are not resolved.") (id "1549") (version "1.3.12") (classification "experimental") (author "Dale W. Walton") (credit "Dale W. Walton") (date "25-05-2021") } ) (graphics { (player Colour P1 (colour 120 36 0)) (player Colour P2 (colour Cream)) (player Colour P3 (colour BabyBlue)) (player Colour P4 (colour Gold)) (piece Scale "Ball" 0.92) (piece Background "Ball" image:"Disc" fillColour:(colour 0 0 0 140) edgeColour:(colour 0 0 0 0)) (board Colour Phase0 "ColourBackground") (board StyleThickness InnerEdges 0.4) (board StyleThickness OuterEdges 0.6) (board StyleThickness InnerVertices 0.45) (board StyleThickness OuterVertices 0.45) (board Colour InnerVertices (colour Grey)) (board Colour OuterVertices (colour Grey)) (board Colour InnerEdges (colour Black)) (board Colour OuterEdges (colour Black)) (show Edges Diagonal (colour DarkGrey)) (board Background image: fillColour:"ColourBackground" edgeColour:(colour 180 180 180 80) scale:) } ) (ai "Windflowers_ai" ) )