···11+import gleam/bool
12import gleam/result
33+import starfish/internal/board
24import starfish/internal/game
35import starfish/internal/move
46···175177 FiftyMoves
176178}
177179180180+/// Returns the current game state: A win, draw or neither.
178181pub fn state(game: Game) -> GameState {
179179- todo
182182+ // TODO: Check for insufficient material and threefold repetition
183183+ use <- bool.guard(game.half_moves >= 50, Draw(FiftyMoves))
184184+ use <- bool.guard(move.any_legal(game), Continue)
185185+ use <- bool.guard(!game.attack_information.in_check, Draw(Stalemate))
186186+ case game.to_move {
187187+ board.Black -> WhiteWin
188188+ board.White -> BlackWin
189189+ }
180190}
+15
src/starfish/internal/move.gleam
···3333 }
3434}
35353636+/// Checks whether any legal moves are possible without calculating every legal
3737+/// move beforehand.
3838+pub fn any_legal(game: Game) -> Bool {
3939+ use any, square, position <- iv.index_fold(game.board, False)
4040+ // If we've found legal moves already, we already know that there are some,
4141+ // so no need to check for more.
4242+ use <- bool.guard(any, any)
4343+4444+ case square {
4545+ board.Occupied(piece:, colour:) if colour == game.to_move ->
4646+ moves_for_piece(game, position, piece, []) != []
4747+ board.Occupied(_, _) | board.Empty -> any
4848+ }
4949+}
5050+3651fn move_is_valid_with_pins(
3752 from: Int,
3853 to: Int,