(define "IsCircleAt" (or (= (what at:#1) (id "Disc" P1)) (= (what at:#1) (id "Disc" P2))))
(define "IsCrossAt"  (or (= (what at:#1) (id "Cross" P1))  (= (what at:#1) (id "Cross" P2))))

(define "CircleConnects"
    (and {
        ("IsCircleAt" (last To))
        (> (count Sites in:(intersection
                (sites Group at:(last To) if:("IsCircleAt" (to)))
                (sites Side NE)
            )) 0)
        (> (count Sites in:(intersection
                (sites Group at:(last To) if:("IsCircleAt" (to)))
                (sites Side SW)
            )) 0)
    })
)

(define "CrossConnects"
    (and {
        ("IsCrossAt" (last To))
        (> (count Sites in:(intersection
                (sites Group at:(last To) if:("IsCrossAt" (to)))
                (sites Side NW)
            )) 0)
        (> (count Sites in:(intersection
                (sites Group at:(last To) if:("IsCrossAt" (to)))
                (sites Side SE)
            )) 0)
    })
)

//-----------------------------------------------------------------------------

(game "DualHex"
    (players 2)

    (equipment {
        (board (hex Diamond <Board>))
        (piece "Disc" P1) (piece "Cross" P1)
        (piece "Disc" P2) (piece "Cross" P2)
        (regions P1 { (sites Side NE) (sites Side SW) })
        (regions P2 { (sites Side NW) (sites Side SE) })
    })

    (rules
        (start {})

        (play
            (if (= 1 (var "TurnStep"))
                (or {
                    (if (!= (what at:(last To)) (id "Disc" P1))
                        (move Add (piece (id "Disc" P1)) (to (sites Empty))))
                    (if (!= (what at:(last To)) (id "Cross" P1))
                        (move Add (piece (id "Cross" P1)) (to (sites Empty))))
                    (if (!= (what at:(last To)) (id "Disc" P2))
                        (move Add (piece (id "Disc" P2)) (to (sites Empty))))
                    (if (!= (what at:(last To)) (id "Cross" P2))
                        (move Add (piece (id "Cross" P2)) (to (sites Empty))))
                }
                (then (set Var "TurnStep" 0)))
                (if (= 0 (count Moves))
                    (or {
                        (move Add (piece (id "Cross" P1)) (to (sites Empty)))
                        (move Add (piece (id "Disc" P2)) (to (sites Empty)))
                    })
                    (or {
                        (move Add (piece (id "Disc" P1)) (to (sites Empty)))
                        (move Add (piece (id "Cross" P1)) (to (sites Empty)))
                        (move Add (piece (id "Disc" P2)) (to (sites Empty)))
                        (move Add (piece (id "Cross" P2)) (to (sites Empty)))
                    }
                    (then (and { (set Var "TurnStep" 1) (moveAgain) })))
                )
            )
        )

        (end {
            (if (and (= (mover) 1) (or (is Connected P1) "CircleConnects")) (result P1 Win))
            (if (and (= (mover) 2) (or (is Connected P2) "CrossConnects")) (result P2 Win))
            (if (is Connected P1) (result P1 Win))
            (if (is Connected P2) (result P2 Win))
            (if "CircleConnects" (result P1 Win))
            (if "CrossConnects" (result P2 Win))
        })
    )
)

//-----------------------------------------------------------------------------

(option "Board Size" <Board> args:{ <size> } {
    (item "7"  <7>  "A 7-per-side board (49 points).")
    (item "9"  <9>  "A 9-per-side board (81 points).")***
    (item "11" <11> "An 11-per-side board (121 points), the traditional Hex size.")
    (item "13" <13> "A 13-per-side board (169 points).")
})

//-----------------------------------------------------------------------------

(metadata
    (info
        {
            (description "DualHex is a Hex variant by Kashio Fujii, 2026. Each player has two piece shapes (Circle and Cross) as well as a colour; connecting your own colour's sides wins, and so does connecting the same sides with your shape, regardless of whose colour the pieces are.")
            (rules "
COMPONENTS
* A diamond-shaped Hex board, any size.
* Four piece types: White Disc, White Cross, Black Disc, Black Cross.

SETUP
The board starts empty.

HOW TO PLAY
White's very first move of the game is a single stone only -- either a White Cross or a Black Disc. After that, each turn you freely choose any two of the four piece types, not necessarily your own colour, and place one of each on two different empty cells. No placing the same type twice in one turn.

ENDING THE GAME
White wins by connecting its two sides with White stones, or with Disc-shaped stones of either colour. Black wins on its own two sides with Black stones, or with Cross-shaped stones of either colour. Checked after every single stone, so a turn can end the game on its first stone.

Since you're free to place either colour, one stone can occasionally complete both players' conditions at once (e.g. a Black Disc finishing Black's colour connection and White's shape connection together) -- whoever's turn it was wins.

No draws: colour alone splits the whole board into two, so the Hex theorem guarantees a winner by colour. Shape does exactly the same thing independently, since every stone is also either a Disc or a Cross. Either axis on its own already rules out a draw.

No pie rule is intended.
")
            (id "dualhex")
            (version "0.1")
            (classification "board/space/connection")
            (author "Kashio Fujii")
            (credit "Kashio Fujii")
            (date "2026")
        }
    )

    (graphics {
        (player Colour P1 (colour White))
        (player Colour P2 (colour VeryDarkGrey))
        (piece Scale 0.9)
        (board Style ConnectiveGoal)
    })
)
