github.com/gorgonia/agogo@v0.1.1/game/state.go (about) 1 package game 2 3 import ( 4 "fmt" 5 ) 6 7 type Colour int32 8 9 const ( 10 None Colour = iota 11 Black 12 White 13 ) 14 15 func (cl Colour) Format(s fmt.State, c rune) { 16 switch c { 17 case 'v': // used in debug 18 switch cl { 19 case None: 20 fmt.Fprint(s, "None") 21 case Black: 22 fmt.Fprint(s, "Black") 23 case White: 24 fmt.Fprint(s, "White") 25 } 26 case 's': // used in board games 27 switch cl { 28 case None: 29 fmt.Fprint(s, "·") 30 case Black: 31 fmt.Fprint(s, "X") 32 case White: 33 fmt.Fprint(s, "O") 34 } 35 } 36 } 37 38 // Player represents a player. It's also a colour. 39 type Player Colour 40 41 func (p Player) Format(s fmt.State, c rune) { 42 switch c { 43 case 'v': // used in debug 44 switch Colour(p) { 45 case None: 46 fmt.Fprint(s, "None") 47 case Black: 48 fmt.Fprint(s, "Black") 49 case White: 50 fmt.Fprint(s, "White") 51 } 52 case 's': // used in board games 53 switch Colour(p) { 54 case None: 55 fmt.Fprint(s, "·") 56 case Black: 57 fmt.Fprint(s, "X") 58 case White: 59 fmt.Fprint(s, "O") 60 } 61 } 62 } 63 64 // PlayerMove is a tuple indicating the player and the move to be made. 65 // 66 // For now, the move is a Single. The original implementation took a Coordinate 67 type PlayerMove struct { 68 Player 69 Single 70 } 71 72 // Eq returns true if both are equal 73 func (p PlayerMove) Eq(other PlayerMove) bool { 74 return p.Player == other.Player && p.Single == other.Single 75 } 76 77 func (p PlayerMove) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%v@%d", p.Player, p.Single) } 78 79 // Coordinate is a representation of coordinates. This is typically a move 80 type Coordinate interface { 81 IsResignation() bool 82 IsPass() bool 83 } 84 85 // Coord represents a (row, col) coordinate. 86 // Given we're unlikely to actually have a board size of 255x255 or greater, 87 // a pair of bytes is sufficient to represent the coordinates 88 // 89 // The Coord uses a standard computer cartesian coordinates 90 // - (0, 0) represents the top left 91 // - (18, 18) represents the bottom right of a 19x19 board 92 // - (255, 255) represents a "pass" move 93 // - (254, 254) represents a "resign" move 94 type Coord struct { 95 X, Y int16 96 } 97 98 func (c Coord) Add(other Coord) struct{ X, Y int16 } { 99 return Coord{c.X + other.X, c.Y + other.Y} 100 } 101 102 func (c Coord) Eq(other Coord) bool { return c.X == other.X && c.Y == other.Y } 103 104 // IsResignation returns true when the coordinate represents a "resignation" move 105 func (c Coord) IsResignation() bool { return c.X == 254 && c.Y == 254 } 106 107 // IsPass returns true when the coordinate represents a "pass" move 108 func (c Coord) IsPass() bool { return c.X == 255 && c.Y == 255 } 109 110 // Single represents a coordinate as a single 8-bit number, utilized in a rowmajor fashion. 111 // - 0 represents the top left 112 // - 18 represents the top right 113 // - 19 represents (1, 0) 114 // - -1 represents the "pass" move 115 // - -2 represents the "resignation" move 116 type Single int32 117 118 // IsResignation returns true when the coordinate represents a "resignation" move 119 func (c Single) IsResignation() bool { return c == -2 } 120 121 // IsPass returns true when the coordinate represents a "pass" move 122 func (c Single) IsPass() bool { return c == -1 } 123 124 // State is any game that implements these and are able to report back 125 type State interface { 126 // These methods represent the game state 127 BoardSize() (int, int) // returns the board size 128 Board() []Colour // returns the board state 129 ActionSpace() int // returns the number of permissible actions 130 Hash() Zobrist // returns the hash of the board 131 ToMove() Player // returns the next player to move (terminology is a bit confusing - this means the current player) 132 Passes() int // returns number of passes that have been made 133 MoveNumber() int // returns count of moves so far that led to this point. 134 LastMove() PlayerMove // returns the last move that was made 135 Handicap() int // returns a handicap (i.e. allow N moves) 136 137 // Meta-game stuff 138 Score(p Player) float32 // score of the given player 139 AdditionalScore() float32 // additional tie breaking scores (like komi etc) 140 Ended() (ended bool, winner Player) // has the game ended? if yes, then who's the winner? 141 142 // interactions 143 SetToMove(Player) // set the next player to move 144 Check(m PlayerMove) bool // check if the placement is legal 145 Apply(m PlayerMove) State // should return a GameState. The required side effect is the NextToMove has to change. 146 Reset() // reset state 147 148 // For MCTS 149 Historical(i int) []Colour // returns the board state from history 150 UndoLastMove() 151 Fwd() 152 153 // generics 154 Eq(other State) bool 155 Clone() State 156 } 157 158 // KomiSetter is any State that can set a Komi score. 159 // 160 // The komi score may be acquired from the State via AdditionalScore() 161 type KomiSetter interface { 162 State 163 SetKomi(komi float64) error 164 } 165 166 // Zobrist is a type representing a "zobrist" hash. 167 // The word "Zobrist" is put in quotes because only Go and chess uses zobrist hashing. 168 // Other games have different hashes of the boards (because only Go and Chess have subtractive boards) 169 type Zobrist uint32 170 171 type MetaState interface { 172 Name() string // name of the game 173 Epoch() int 174 GameNumber() int 175 Score(a Player) float64 176 State() State 177 } 178 179 type CoordConverter interface { 180 Ltoi(Coord) Single 181 Itol(Single) Coord 182 }