From a1f01d4a2b1ce2a167b7fec1506f3970bf13ea79 Mon Sep 17 00:00:00 2001 From: Lizzy Hunt Date: Mon, 13 Mar 2023 14:13:11 -0600 Subject: Move history (#18) * store move history * Add previous game viewer --- lib/chessh/ssh/client/game/previous_game.ex | 121 ++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 lib/chessh/ssh/client/game/previous_game.ex (limited to 'lib/chessh/ssh/client/game/previous_game.ex') diff --git a/lib/chessh/ssh/client/game/previous_game.ex b/lib/chessh/ssh/client/game/previous_game.ex new file mode 100644 index 0000000..38172fd --- /dev/null +++ b/lib/chessh/ssh/client/game/previous_game.ex @@ -0,0 +1,121 @@ +defmodule Chessh.SSH.Client.PreviousGame do + @start_fen "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" + + alias Chessh.{Game, Utils} + alias Chessh.SSH.Client.Game.Renderer + alias IO.ANSI + + require Logger + + defmodule State do + defstruct move_fens: %{}, + move_idx: 0, + binbo_pid: nil, + game: %Game{}, + client_pid: nil, + flipped: false + end + + use Chessh.SSH.Client.Screen + + def init([ + %State{ + client_pid: client_pid, + game: %Game{ + game_moves: game_moves + } + } = state + ]) do + {:ok, binbo_pid} = :binbo.new_server() + :binbo.new_game(binbo_pid, @start_fen) + + {move_fens, _moves} = + game_moves + |> String.trim() + |> String.split(" ") + |> Enum.reduce({%{"0" => @start_fen}, 1}, fn move, {move_idx_fen_map, curr_turn} -> + {:ok, _status} = :binbo.move(binbo_pid, move) + {:ok, fen} = :binbo.get_fen(binbo_pid) + + {Map.put(move_idx_fen_map, "#{curr_turn}", fen), curr_turn + 1} + end) + + new_state = %State{ + state + | binbo_pid: binbo_pid, + move_fens: move_fens + } + + send(client_pid, {:send_to_ssh, Utils.clear_codes()}) + render(new_state) + + {:ok, new_state} + end + + def input( + _width, + _height, + action, + %State{ + move_idx: move_idx, + flipped: flipped, + game: %Game{ + moves: num_moves + } + } = state + ) do + new_move_idx = + case action do + :left -> + Utils.wrap_around(move_idx, -1, num_moves) + + :right -> + Utils.wrap_around(move_idx, 1, num_moves) + + _ -> + move_idx + end + + new_state = %State{ + state + | move_idx: new_move_idx, + flipped: if(action == "f", do: !flipped, else: flipped) + } + + render(new_state) + new_state + end + + def render( + %State{ + flipped: flipped, + client_pid: client_pid, + move_fens: move_fens, + move_idx: move_idx, + game: %Game{id: game_id, moves: total_moves} + } = state + ) do + {:ok, fen} = Map.fetch(move_fens, "#{move_idx}") + + lines = + ["Game #{game_id} | Move #{move_idx} / #{total_moves}"] ++ + Renderer.draw_board(fen, flipped) ++ + ["<- previous | next ->"] + + send( + client_pid, + {:send_to_ssh, + [ANSI.home()] ++ + Enum.map( + Enum.zip(1..length(lines), lines), + fn {i, line} -> + [ANSI.cursor(i, 0), ANSI.clear_line(), line] + end + )} + ) + + state + end + + def render(_width, _height, %State{} = state), do: render(state) +end -- cgit v1.2.3-70-g09d2