gnome-chess/lib/chess-move.vala
Michael Catanzaro 9b41b9bef7 Show better move description for en passant captures
The current description is wrong since it says the captured piece was at
the current location of the capturing piece, but that's not true for en
passant captures.

Also, this might possibly help users realize that en passant is not a bug.
2018-04-24 11:48:07 -05:00

143 lines
4.2 KiB
Vala

/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2010-2016 Robert Ancell
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version. See http://www.gnu.org/copyleft/gpl.html the full text of the
* license.
*/
public class ChessMove : Object
{
public int number;
public ChessPiece piece;
public ChessPiece? promotion_piece;
public ChessPiece? castling_rook;
public ChessPiece? victim;
public int r0;
public int f0;
public int r1;
public int f1;
public bool ambiguous_rank;
public bool ambiguous_file;
public bool en_passant;
public CheckState check_state;
public string get_lan ()
{
if (castling_rook != null)
{
if (f1 > f0)
return "O-O";
else
return "O-O-O";
}
var builder = new StringBuilder ();
if (victim != null)
builder.append_printf ("%c%dx%c%d", 'a' + f0, r0 + 1, 'a' + f1, r1 + 1);
else
builder.append_printf ("%c%d-%c%d", 'a' + f0, r0 + 1, 'a' + f1, r1 + 1);
const char promotion_symbols[] = {' ', 'R', 'N', 'B', 'Q', 'K'};
if (promotion_piece != null)
builder.append_printf ("=%c", promotion_symbols[promotion_piece.type]);
switch (check_state)
{
case CheckState.CHECK:
builder.append_c ('+');
break;
case CheckState.CHECKMATE:
builder.append_c ('#');
break;
}
return builder.str;
}
public string get_san ()
{
const string piece_names[] = {"", "R", "N", "B", "Q", "K"};
return make_san ((string[]) piece_names);
}
public string get_fan ()
{
const string white_piece_names[] = {"", "", "", "", "", ""};
const string black_piece_names[] = {"", "", "", "", "", ""};
if (piece.color == Color.WHITE)
return make_san ((string[]) white_piece_names);
else
return make_san ((string[]) black_piece_names);
}
private string make_san (string[] piece_names)
{
if (castling_rook != null)
{
if (f1 > f0)
return "O-O";
else
return "O-O-O";
}
var builder = new StringBuilder ();
builder.append (piece_names[piece.type]);
if (ambiguous_file)
builder.append_printf ("%c", 'a' + f0);
if (ambiguous_rank)
builder.append_printf ("%d", r0 + 1);
if (victim != null)
builder.append ("x");
builder.append_printf ("%c%d", 'a' + f1, r1 + 1);
if (promotion_piece != null)
builder.append_printf ("=%s", piece_names[promotion_piece.type]);
switch (check_state)
{
case CheckState.CHECK:
builder.append_c ('+');
break;
case CheckState.CHECKMATE:
builder.append_c ('#');
break;
}
return builder.str;
}
/* Move suitable for a chess engine (CECP/UCI) */
public string get_engine ()
{
var builder = new StringBuilder ();
const char promotion_symbols[] = {' ', 'r', 'n', 'b', 'q', ' '};
if (promotion_piece != null)
builder.append_printf ("%c%d%c%d%c", 'a' + f0, r0 + 1, 'a' + f1, r1 + 1, promotion_symbols[promotion_piece.type]);
else
builder.append_printf ("%c%d%c%d", 'a' + f0, r0 + 1, 'a' + f1, r1 + 1);
return builder.str;
}
public ChessMove copy ()
{
var move = new ChessMove ();
move.number = number;
move.piece = piece;
move.promotion_piece = promotion_piece;
move.castling_rook = castling_rook;
move.victim = victim;
move.r0 = r0;
move.f0 = f0;
move.r1 = r1;
move.f1 = f1;
move.ambiguous_rank = ambiguous_rank;
move.ambiguous_file = ambiguous_file;
move.en_passant = en_passant;
move.check_state = check_state;
return move;
}
}