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
116
117
118
119
120
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
|