A tool for testing starfish
at main 4.4 kB view raw
1import gleam/http 2import gleam/http/request 3import gleam/httpc 4import gleam/int 5import gleam/io 6import gleam/list 7import gleam/string 8import simplifile as file 9import starfish.{type Move} 10 11type ToMove { 12 UpdatedToMove 13 OriginalToMove 14} 15 16const fen_file = "silversuite.fen" 17 18pub fn main() -> Nil { 19 io.println("Loading games from file...") 20 21 let assert Ok(games) = 22 fen_file 23 |> file.read 24 as "Failed to read game file" 25 26 let games = 27 games 28 |> string.split("\n") 29 // Use `#` for comments in the file 30 |> list.filter(fn(game) { game != "" && !string.starts_with(game, "#") }) 31 32 io.println("Loaded games.") 33 34 let outcomes = list.index_map(games, run_game) |> list.flatten 35 36 let #(wins, draws, losses) = 37 list.fold(outcomes, #(0, 0, 0), fn(tuple, outcome) { 38 let #(wins, draws, losses) = tuple 39 case outcome { 40 Updated -> #(wins + 1, draws, losses) 41 Draw(_) -> #(wins, draws + 1, losses) 42 Original -> #(wins, draws, losses + 1) 43 } 44 }) 45 46 io.println( 47 "Updated version won " 48 <> int.to_string(wins) 49 <> " times.\nThe bots drew " 50 <> int.to_string(draws) 51 <> " times.\nOriginal version won " 52 <> int.to_string(losses) 53 <> " times.", 54 ) 55 56 Nil 57} 58 59type Outcome { 60 Updated 61 Original 62 Draw(starfish.DrawReason) 63} 64 65fn run_game(fen: String, i: Int) -> List(Outcome) { 66 let assert Ok(game) = starfish.try_from_fen(fen) 67 as "Failed to parse fen string" 68 69 io.println("Running match " <> int.to_string(i + 1) <> ", position " <> fen) 70 71 update_fen(fen) 72 73 let first_outcome = run_game_loop(game, UpdatedToMove, UpdatedPlaysWhite) 74 75 io.println("Finished first game of match, " <> print_outcome(first_outcome)) 76 77 io.println("Running again with reversed colours...") 78 79 update_fen(fen) 80 81 let second_outcome = run_game_loop(game, OriginalToMove, UpdatedPlaysBlack) 82 83 io.println("Finished second game of match, " <> print_outcome(second_outcome)) 84 85 [first_outcome, second_outcome] 86} 87 88fn print_outcome(outcome: Outcome) -> String { 89 case outcome { 90 Original -> "original version won." 91 Updated -> "updated version won." 92 Draw(starfish.FiftyMoves) -> "fifty quiet moves occurred" 93 Draw(starfish.InsufficientMaterial) -> "there was insufficient material" 94 Draw(starfish.Stalemate) -> "it was stalemate" 95 Draw(starfish.ThreefoldRepetition) -> "the position was repeated 3 times" 96 } 97} 98 99type Configuration { 100 UpdatedPlaysWhite 101 UpdatedPlaysBlack 102} 103 104fn run_game_loop( 105 game: starfish.Game, 106 to_move: ToMove, 107 configuration: Configuration, 108) -> Outcome { 109 case starfish.state(game), configuration { 110 starfish.Draw(reason), _ -> Draw(reason) 111 starfish.BlackWin, UpdatedPlaysBlack | starfish.WhiteWin, UpdatedPlaysWhite -> 112 Updated 113 starfish.BlackWin, UpdatedPlaysWhite | starfish.WhiteWin, UpdatedPlaysBlack -> 114 Original 115 starfish.Continue, _ -> { 116 let best_move = get_best_move(game, to_move) 117 118 let to_move = case to_move { 119 OriginalToMove -> UpdatedToMove 120 UpdatedToMove -> OriginalToMove 121 } 122 123 run_game_loop( 124 starfish.apply_move(game, best_move), 125 to_move, 126 configuration, 127 ) 128 } 129 } 130} 131 132fn update_fen(fen: String) -> Nil { 133 let assert Ok(original_req) = request.to(original_url <> "/fen") 134 135 let assert Ok(response) = 136 httpc.send( 137 original_req |> request.set_body(fen) |> request.set_method(http.Post), 138 ) 139 assert response.status == 200 140 141 let assert Ok(updated_req) = request.to(updated_url <> "/fen") 142 143 let assert Ok(response) = 144 httpc.send( 145 updated_req |> request.set_body(fen) |> request.set_method(http.Post), 146 ) 147 assert response.status == 200 148 149 Nil 150} 151 152const updated_url = "http://0.0.0.0:8000" 153 154const original_url = "http://0.0.0.0:8001" 155 156fn get_best_move(game: starfish.Game, to_move: ToMove) -> Move { 157 let #(url, opposing_url) = case to_move { 158 UpdatedToMove -> #(updated_url, original_url) 159 OriginalToMove -> #(original_url, updated_url) 160 } 161 162 let assert Ok(request) = request.to(url <> "/get_move") 163 let assert Ok(response) = httpc.send(request) 164 assert response.status == 200 165 166 let assert Ok(move) = starfish.parse_move(response.body, game) 167 168 let assert Ok(request) = request.to(opposing_url <> "/move") 169 let assert Ok(response) = 170 httpc.send( 171 request 172 |> request.set_body(response.body) 173 |> request.set_method(http.Post), 174 ) 175 assert response.status == 200 176 177 move 178}