Skip to content

Commit d60d957

Browse files
committed
Implement Display trait for Game to format as FEN
1 parent 0ac8d81 commit d60d957

File tree

3 files changed

+105
-45
lines changed

3 files changed

+105
-45
lines changed

src/board.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,11 @@ impl Board {
10841084
pub fn checkers(&self) -> &BitBoard {
10851085
&self.checkers
10861086
}
1087+
1088+
pub fn get_psuedo_fen(&self) -> String {
1089+
let board_builder: BoardBuilder = self.into();
1090+
board_builder.get_psuedo_fen()
1091+
}
10871092
}
10881093

10891094
impl fmt::Display for Board {

src/board_builder.rs

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -264,83 +264,88 @@ impl BoardBuilder {
264264
self.en_passant = file;
265265
self
266266
}
267-
}
268-
269-
impl Index<Square> for BoardBuilder {
270-
type Output = Option<(Piece, Color)>;
271-
272-
fn index<'a>(&'a self, index: Square) -> &'a Self::Output {
273-
&self.pieces[index.to_index()]
274-
}
275-
}
276267

277-
impl IndexMut<Square> for BoardBuilder {
278-
fn index_mut<'a>(&'a mut self, index: Square) -> &'a mut Self::Output {
279-
&mut self.pieces[index.to_index()]
280-
}
281-
}
282-
283-
impl fmt::Display for BoardBuilder {
284-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
268+
pub fn get_psuedo_fen(&self) -> String {
269+
let mut psuedo_fen = String::new();
285270
let mut count = 0;
286271
for rank in ALL_RANKS.iter().rev() {
287272
for file in ALL_FILES.iter() {
288273
let square = Square::make_square(*rank, *file).to_index();
289274

290275
if self.pieces[square].is_some() && count != 0 {
291-
write!(f, "{}", count)?;
276+
psuedo_fen.push_str(count.to_string().as_str());
292277
count = 0;
293278
}
294279

295280
if let Some((piece, color)) = self.pieces[square] {
296-
write!(f, "{}", piece.to_string(color))?;
281+
psuedo_fen.push_str(piece.to_string(color).as_str());
297282
} else {
298283
count += 1;
299284
}
300285
}
301286

302287
if count != 0 {
303-
write!(f, "{}", count)?;
288+
psuedo_fen.push_str(count.to_string().as_str());
304289
}
305290

306291
if *rank != Rank::First {
307-
write!(f, "/")?;
292+
psuedo_fen.push_str("/");
308293
}
309294
count = 0;
310295
}
311296

312-
write!(f, " ")?;
297+
psuedo_fen.push_str(" ");
313298

314299
if self.side_to_move == Color::White {
315-
write!(f, "w ")?;
300+
psuedo_fen.push_str("w ");
316301
} else {
317-
write!(f, "b ")?;
302+
psuedo_fen.push_str("b ");
318303
}
319304

320-
write!(
321-
f,
322-
"{}",
323-
self.castle_rights[Color::White.to_index()].to_string(Color::White)
324-
)?;
325-
write!(
326-
f,
327-
"{}",
328-
self.castle_rights[Color::Black.to_index()].to_string(Color::Black)
329-
)?;
305+
psuedo_fen.push_str(
306+
self.castle_rights[Color::White.to_index()]
307+
.to_string(Color::White)
308+
.as_str(),
309+
);
310+
psuedo_fen.push_str(
311+
self.castle_rights[Color::Black.to_index()]
312+
.to_string(Color::Black)
313+
.as_str(),
314+
);
330315
if self.castle_rights[0] == CastleRights::NoRights
331316
&& self.castle_rights[1] == CastleRights::NoRights
332317
{
333-
write!(f, "-")?;
318+
psuedo_fen.push_str("-");
334319
}
335320

336-
write!(f, " ")?;
321+
psuedo_fen.push_str(" ");
337322
if let Some(sq) = self.en_passant_target {
338-
write!(f, "{}", sq)?;
323+
psuedo_fen.push_str(sq.to_string().as_str());
339324
} else {
340-
write!(f, "-")?;
325+
psuedo_fen.push_str("-");
341326
}
342327

343-
write!(f, " 0 1")
328+
psuedo_fen
329+
}
330+
}
331+
332+
impl Index<Square> for BoardBuilder {
333+
type Output = Option<(Piece, Color)>;
334+
335+
fn index<'a>(&'a self, index: Square) -> &'a Self::Output {
336+
&self.pieces[index.to_index()]
337+
}
338+
}
339+
340+
impl IndexMut<Square> for BoardBuilder {
341+
fn index_mut<'a>(&'a mut self, index: Square) -> &'a mut Self::Output {
342+
&mut self.pieces[index.to_index()]
343+
}
344+
}
345+
346+
impl fmt::Display for BoardBuilder {
347+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
348+
write!(f, "{} 0 1", self.get_psuedo_fen())
344349
}
345350
}
346351

src/game.rs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::color::Color;
44
use crate::error::Error;
55
use crate::movegen::MoveGen;
66
use crate::piece::Piece;
7+
use std::fmt;
78
use std::str::FromStr;
89

910
/// Contains all actions supported within the game
@@ -170,6 +171,48 @@ impl Game {
170171
copy
171172
}
172173

174+
fn get_full_move_counter(&self) -> usize {
175+
let mut half_moves = 2;
176+
for x in self.moves.iter() {
177+
match *x {
178+
Action::MakeMove(_) => {
179+
half_moves += 1;
180+
}
181+
_ => (),
182+
}
183+
}
184+
half_moves / 2
185+
}
186+
187+
fn get_half_move_clock(&self) -> usize {
188+
let mut reversible_moves = 0;
189+
let mut board = self.start_pos;
190+
for x in self.moves.iter() {
191+
match *x {
192+
Action::MakeMove(m) => {
193+
let white_castle_rights = board.castle_rights(Color::White);
194+
let black_castle_rights = board.castle_rights(Color::Black);
195+
if board.piece_on(m.get_source()) == Some(Piece::Pawn) {
196+
reversible_moves = 0;
197+
} else if board.piece_on(m.get_dest()).is_some() {
198+
reversible_moves = 0;
199+
} else {
200+
reversible_moves += 1;
201+
}
202+
board = board.make_move_new(m);
203+
204+
if board.castle_rights(Color::White) != white_castle_rights
205+
|| board.castle_rights(Color::Black) != black_castle_rights
206+
{
207+
reversible_moves = 0;
208+
}
209+
}
210+
_ => {}
211+
}
212+
}
213+
reversible_moves
214+
}
215+
173216
/// Determine if a player can legally declare a draw by 3-fold repetition or 50-move rule.
174217
///
175218
/// ```
@@ -205,7 +248,6 @@ impl Game {
205248
let mut legal_moves_per_turn: Vec<(u64, Vec<ChessMove>)> = vec![];
206249

207250
let mut board = self.start_pos;
208-
let mut reversible_moves = 0;
209251

210252
// Loop over each move, counting the reversible_moves for draw by 50 move rule,
211253
// and filling a list of legal_moves_per_turn list for 3-fold repitition
@@ -216,20 +258,16 @@ impl Game {
216258
let white_castle_rights = board.castle_rights(Color::White);
217259
let black_castle_rights = board.castle_rights(Color::Black);
218260
if board.piece_on(m.get_source()) == Some(Piece::Pawn) {
219-
reversible_moves = 0;
220261
legal_moves_per_turn.clear();
221262
} else if board.piece_on(m.get_dest()).is_some() {
222-
reversible_moves = 0;
223263
legal_moves_per_turn.clear();
224264
} else {
225-
reversible_moves += 1;
226265
}
227266
board = board.make_move_new(m);
228267

229268
if board.castle_rights(Color::White) != white_castle_rights
230269
|| board.castle_rights(Color::Black) != black_castle_rights
231270
{
232-
reversible_moves = 0;
233271
legal_moves_per_turn.clear();
234272
}
235273
legal_moves_per_turn
@@ -239,7 +277,7 @@ impl Game {
239277
}
240278
}
241279

242-
if reversible_moves >= 100 {
280+
if self.get_half_move_clock() >= 100 {
243281
return true;
244282
}
245283

@@ -427,6 +465,18 @@ impl FromStr for Game {
427465
}
428466
}
429467

468+
impl fmt::Display for Game {
469+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470+
write!(
471+
f,
472+
"{} {} {}",
473+
self.current_position().get_psuedo_fen(),
474+
self.get_half_move_clock(),
475+
self.get_full_move_counter()
476+
)
477+
}
478+
}
479+
430480
#[cfg(test)]
431481
pub fn fake_pgn_parser(moves: &str) -> Game {
432482
moves

0 commit comments

Comments
 (0)