summaryrefslogtreecommitdiff
path: root/lib/chessh/ssh/client/game/previous_game.ex
diff options
context:
space:
mode:
authorLizzy Hunt <elizabeth.hunt@simponic.xyz>2023-03-13 14:13:11 -0600
committerGitHub <noreply@github.com>2023-03-13 14:13:11 -0600
commita1f01d4a2b1ce2a167b7fec1506f3970bf13ea79 (patch)
tree3eb1a991569da428a77155b6e6bb601d00c3eb98 /lib/chessh/ssh/client/game/previous_game.ex
parent3cb88323c22e72f36d82ae5ada384311123eae67 (diff)
downloadchessh-a1f01d4a2b1ce2a167b7fec1506f3970bf13ea79.tar.gz
chessh-a1f01d4a2b1ce2a167b7fec1506f3970bf13ea79.zip
Move history (#18)
* store move history * Add previous game viewer
Diffstat (limited to 'lib/chessh/ssh/client/game/previous_game.ex')
-rw-r--r--lib/chessh/ssh/client/game/previous_game.ex121
1 files changed, 121 insertions, 0 deletions
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