This section describes the foundational value types used across the mjai-manue-go domain. These primitives define how tiles are encoded, how player positions (seats) are calculated, and how winds are managed.
The codebase employs a multi-tiered tile identification system to handle standard tiles, red-five variants, and unknown tiles (used in state masking).
Tiles are represented by a Tile struct containing an int8 ID internal/domain/game/tile/tile.go99-101 The system supports three levels of type counts:
?) internal/domain/game/tile/tile.go13-14The tile package provides static lookup tables for tile attributes based on their ID:
ManzuColor ('m'), PinzuColor ('p'), SouzuColor ('s'), HonorsColor ('t'), and UnknownColor ('?') internal/domain/game/tile/tile.go16-20NextForDora() uses a circular mapping (doraIndicatorToDora) to determine the effective dora tile from an indicator internal/domain/game/tile/tile.go90-200Title "Tile ID and Code Mapping"
Sources: internal/domain/game/tile/tile.go38-160
The Tiles type is a slice of Tile objects with helper methods for common mahjong operations internal/domain/game/tile/tiles.go16
tileSortKeyTable to ensure a standard hand order: Manzu -> Pinzu -> Souzu -> Honors. Red fives are sorted immediately after their black counterparts (e.g., 5m then 5mr) internal/domain/game/tile/tiles.go7-33Distinct() returns a sorted slice of unique tiles, with an optional filter to exclude specific tiles (like red fives) internal/domain/game/tile/tiles.go57-70HasSameSymbol() and CountSameSymbol() ignore the red-five status, comparing only the number and color internal/domain/game/tile/tile.goThe Seat struct represents a player's physical position at the table (0 to 3) internal/domain/game/seat/seat.go5-7
DistanceFrom(base) calculates the gap between two seats (0=Self, 1=Shimocha, 2=Toimen, 3=Kamicha) internal/domain/game/seat/seat.go34-36IsShimochaOf(target) specifically checks if the current seat is to the immediate left of the target internal/domain/game/seat/seat.go39-41Winds are represented as an int enum: East, South, West, North internal/domain/game/wind/wind.go7-14
Next() handles the wind progression during dealer rotations internal/domain/game/wind/wind.go46-59Title "Seat and Wind Domain Entities"
Sources: internal/domain/game/seat/seat.go
The system provides explicit methods to transition between red and black variants of tiles.
AddRed(): Converts 5m, 5p, or 5s to their red versions (IDs 34, 35, 36). Returns the original tile if no red version exists internal/domain/game/tile/tile.go202-213RemoveRed(): Converts red fives back to standard black tiles (IDs 4, 13, 22) internal/domain/game/tile/tile.go215-226Tile primitives are heavily used in the meld package to enforce mahjong rules during calls:
CountSameSymbol and limits red fives to one per meld internal/domain/game/round/player/meld/pon.go17-27ConcealedKan: Ensures four-of-a-kind and handles red five placement internal/domain/game/round/player/meld/concealed_kan.go14-31CalledKan: Validates four identical symbols including exactly one red five for numerical 5s internal/domain/game/round/player/meld/called_kan.go17-27PromotedKan: Validates the addition of a fourth tile to an existing Pon internal/domain/game/round/player/meld/promoted_kan.go23-33The SwapCallTiles() method in meld.Pon provides the tiles that are restricted for discard immediately after a call to prevent illegal swap calls (kuikae). For numerical 5s, it returns both the black and red variants internal/domain/game/round/player/meld/pon.go70-76
Sources: