1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
defmodule Chessh.SSH.Client.Board do
require Logger
alias Chessh.Utils
alias Chessh.SSH.Client.Board.Renderer
defmodule State do
defstruct cursor: %{x: 7, y: 7},
highlighted: %{},
move_from: nil,
game_id: nil,
client_pid: nil,
binbo_pid: nil,
width: 0,
height: 0
# flipped: false
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())
:binbo.start()
{:ok, binbo_pid} = :binbo.new_server()
:binbo.new_game(binbo_pid)
{:ok, %State{state | binbo_pid: binbo_pid}}
end
def handle_info({:new_move, move}, %State{binbo_pid: binbo_pid, client_pid: client_pid} = state) do
case :binbo.move(binbo_pid, move) do
{:ok, :continue} ->
send(client_pid, {:send_to_ssh, render_state(state)})
_ ->
nil
end
{: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
# flipped: flipped
} = state
) do
new_cursor =
case action do
:left -> %{y: cursor_y, x: Utils.wrap_around(cursor_x, -1, Renderer.chess_board_width())}
:right -> %{y: cursor_y, x: Utils.wrap_around(cursor_x, 1, Renderer.chess_board_width())}
:down -> %{y: Utils.wrap_around(cursor_y, 1, Renderer.chess_board_height()), x: cursor_x}
:up -> %{y: Utils.wrap_around(cursor_y, -1, Renderer.chess_board_height()), 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
# TODO: Check move here, then publish new move, subscribers get from DB instead
if move_from && move_to do
attempted_move = "#{Renderer.to_chess_coord(move_from)}#{Renderer.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_cursor.y, new_cursor.x} => Renderer.to_select_background(),
new_move_from => Renderer.from_select_background()
},
width: width,
height: height
# flipped: if(action == "f", do: !flipped, else: flipped)
}
send(client_pid, {:send_to_ssh, render_state(new_state)})
new_state
end
def render(width, height, %State{client_pid: client_pid} = state) do
send(client_pid, {:send_to_ssh, render_state(state)})
%State{state | width: width, height: height}
end
defp render_state(
%State{
binbo_pid: binbo_pid
} = state
) do
{:ok, fen} = :binbo.get_fen(binbo_pid)
Renderer.render_board_state(fen, state)
end
end
|