summaryrefslogtreecommitdiff
path: root/lib/chessh/ssh/client/board/board.ex
diff options
context:
space:
mode:
authorSimponic <loganhunt@simponic.xyz>2023-01-11 19:14:47 -0700
committerSimponic <loganhunt@simponic.xyz>2023-01-11 19:14:47 -0700
commitaa2ff6e1374e8a6a546aa04ee3430d1152c58553 (patch)
treec4e340f072a1da4c9a64c23bb7b1b474fdc0f058 /lib/chessh/ssh/client/board/board.ex
parent628c6d95a32ba0dea67ab046a480ddfca7432c9b (diff)
downloadchessh-aa2ff6e1374e8a6a546aa04ee3430d1152c58553.tar.gz
chessh-aa2ff6e1374e8a6a546aa04ee3430d1152c58553.zip
Checkpoint
Diffstat (limited to 'lib/chessh/ssh/client/board/board.ex')
-rw-r--r--lib/chessh/ssh/client/board/board.ex113
1 files changed, 113 insertions, 0 deletions
diff --git a/lib/chessh/ssh/client/board/board.ex b/lib/chessh/ssh/client/board/board.ex
new file mode 100644
index 0000000..600917f
--- /dev/null
+++ b/lib/chessh/ssh/client/board/board.ex
@@ -0,0 +1,113 @@
+defmodule Chessh.SSH.Client.Board do
+ alias IO.ANSI
+ require Logger
+
+ @chess_board_height 8
+ @chess_board_width 8
+ @tile_width 7
+ @tile_height 4
+
+ @dark_piece_color ANSI.magenta()
+ @light_piece_color ANSI.red()
+ @from_select_background ANSI.green_background()
+ @to_select_background ANSI.blue_background()
+
+ defmodule State do
+ defstruct cursor: %{x: 0, y: 0},
+ highlighted: %{},
+ move_from: nil,
+ game_id: nil,
+ client_pid: nil
+ end
+
+ use Chessh.SSH.Client.Screen
+
+ def init([%State{game_id: game_id} = state | _]) do
+ :syn.add_node_to_scopes([:games])
+ :ok = :syn.join(:games, {:game, game_id}, self())
+
+ {:ok, state}
+ end
+
+ def handle_info({:attempted_move, move}, %State{client_pid: client_pid} = state) do
+ send(client_pid, {:send_to_ssh, ["hello, world!"]})
+ {:noreply, state}
+ end
+
+ def input(
+ width,
+ height,
+ action,
+ %State{
+ move_from: move_from,
+ game_id: game_id,
+ cursor: %{x: cursor_x, y: cursor_y} = cursor,
+ client_pid: client_pid
+ } = state
+ ) do
+ new_cursor =
+ case action do
+ :left -> %{y: cursor_y, x: cursor_x - 1}
+ :right -> %{y: cursor_y, x: cursor_x + 1}
+ :down -> %{y: cursor_y + 1, x: cursor_x}
+ :up -> %{y: cursor_y - 1, x: cursor_x}
+ _ -> cursor
+ end
+
+ {new_move_from, move_to} =
+ if action == :return do
+ coords = {new_cursor.y, new_cursor.x}
+
+ case move_from do
+ nil -> {coords, nil}
+ _ -> {nil, coords}
+ end
+ else
+ {move_from, nil}
+ end
+
+ if move_from && move_to do
+ attempted_move = "#{to_chess_coord(move_from)}#{to_chess_coord(move_to)}"
+ :syn.publish(:games, {:game, game_id}, {:new_move, attempted_move})
+ end
+
+ new_state = %State{
+ state
+ | cursor: new_cursor,
+ move_from: new_move_from,
+ highlighted: %{
+ new_move_from => @from_select_background,
+ {new_cursor.y, new_cursor.x} => @to_select_background
+ }
+ }
+
+ send(client_pid, {:send_to_ssh, render_state(width, height, new_state)})
+ new_state
+ end
+
+ def render(width, height, %State{client_pid: client_pid} = state) do
+ send(client_pid, {:send_to_ssh, render_state(width, height, state)})
+ state
+ end
+
+ defp render_state(width, height, %State{} = _state) do
+ [ANSI.clear(), "#{width}#{height}"]
+ end
+
+ defp to_chess_coord({y, x})
+ when x >= 0 and x < @chess_board_width and y >= 0 and y < @chess_board_height do
+ "#{List.to_string([?a + x])}#{y + 1}"
+ end
+
+ defp piece_type(char) do
+ case String.capitalize(char) do
+ "P" -> "pawn"
+ "N" -> "knight"
+ "R" -> "rook"
+ "B" -> "bishop"
+ "K" -> "king"
+ "Q" -> "queen"
+ _ -> nil
+ end
+ end
+end