tangled
alpha
login
or
join now
gearsco.de
/
starfish
2
fork
atom
A chess library for Gleam
2
fork
atom
overview
issues
pulls
pipelines
Generate promotion moves
gearsco.de
6 months ago
077a142b
8e7b0128
+35
-3
2 changed files
expand all
collapse all
unified
split
src
starfish
internal
board.gleam
move.gleam
+2
src/starfish/internal/board.gleam
···
23
23
King
24
24
}
25
25
26
26
+
pub const pawn_promotions = [Bishop, Knight, Rook, Queen]
27
27
+
26
28
pub type Colour {
27
29
White
28
30
Black
+33
-3
src/starfish/internal/move.gleam
···
90
90
position: Int,
91
91
moves: List(Move(Legal)),
92
92
) -> List(Move(Legal)) {
93
93
-
let #(forward, left, right) = case game.to_move {
94
94
-
board.Black -> #(direction.down, direction.down_left, direction.down_right)
95
95
-
board.White -> #(direction.up, direction.up_left, direction.up_right)
93
93
+
let #(forward, left, right, promotion_rank) = case game.to_move {
94
94
+
board.Black -> #(
95
95
+
direction.down,
96
96
+
direction.down_left,
97
97
+
direction.down_right,
98
98
+
0,
99
99
+
)
100
100
+
board.White -> #(direction.up, direction.up_left, direction.up_right, 7)
96
101
}
97
102
98
103
let forward_one = direction.in_direction(position, forward)
104
104
+
// If moving forward on square is a promotion, then captured are also
105
105
+
// promotions, because they must move to the same rank. A double-move can
106
106
+
// never be a promotion because a pawn cannot double move from a position that
107
107
+
// ends on the promotion rank.
108
108
+
let is_promotion = board.rank(forward_one) == promotion_rank
109
109
+
99
110
let moves = case iv.get(game.board, forward_one) {
100
111
Ok(board.Empty) -> {
101
112
let moves = case
102
113
can_move(position, forward_one, game.attack_information)
103
114
{
104
115
False -> moves
116
116
+
True if is_promotion ->
117
117
+
add_promotions(position, forward_one, moves, board.pawn_promotions)
105
118
True -> [Move(from: position, to: forward_one), ..moves]
106
119
}
107
120
···
130
143
Ok(board.Occupied(colour:, ..)) if colour != game.to_move ->
131
144
case can_move(position, new_position, game.attack_information) {
132
145
False -> moves
146
146
+
True if is_promotion ->
147
147
+
add_promotions(position, new_position, moves, board.pawn_promotions)
133
148
True -> [Capture(from: position, to: new_position), ..moves]
134
149
}
135
150
Ok(board.Empty) if game.en_passant_square == Some(new_position) ->
···
145
160
Ok(board.Occupied(colour:, ..)) if colour != game.to_move ->
146
161
case can_move(position, new_position, game.attack_information) {
147
162
False -> moves
163
163
+
True if is_promotion ->
164
164
+
add_promotions(position, new_position, moves, board.pawn_promotions)
148
165
True -> [Capture(from: position, to: new_position), ..moves]
149
166
}
150
167
Ok(board.Empty) if game.en_passant_square == Some(new_position) ->
···
153
170
True -> [EnPassant(from: position, to: new_position), ..moves]
154
171
}
155
172
Ok(board.Empty) | Ok(board.Occupied(_, _)) | Error(_) -> moves
173
173
+
}
174
174
+
}
175
175
+
176
176
+
fn add_promotions(
177
177
+
from: Int,
178
178
+
to: Int,
179
179
+
moves: List(Move(Legal)),
180
180
+
pieces: List(board.Piece),
181
181
+
) -> List(Move(Legal)) {
182
182
+
case pieces {
183
183
+
[] -> moves
184
184
+
[piece, ..pieces] ->
185
185
+
add_promotions(from, to, [Promotion(from:, to:, piece:), ..moves], pieces)
156
186
}
157
187
}
158
188