/*
* =====================================================================================
*
* Filename: AbstractChessMove.cpp
*
* Description:
*
* Version: 1.0
* Created: 28/02/2011 10:46:22
* Revision: none
* Compiler: gcc
*
* Author: John Ryland (jryland), jryland@xiaofrog.com
* Company: InvertedLogic
*
* =====================================================================================
*/
#include <AbstractChessMove.h>
#include <QString>
#include <QDebug>
AbstractChessMove::AbstractChessMove(AbstractChessBoard *board, QString notation, bool whitesMove)
{
queenSideCastle = false;
kingSideCastle = false;
captureMove = false;
notationStr = notation;
int len = notation.length();
if ( len < 2 ) {
qDebug() << "Invalid move: " << notation;
return;
}
movedToRow = -1;
movedToColumn = -1;
movedFromRow = -1;
movedFromColumn = -1;
switch ( notation.toLatin1().data()[len - 1] ) {
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8':
movedToRow = notation.toLatin1().data()[len - 1] - '1';
switch ( notation.toLatin1().data()[len - 2] ) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
movedToColumn = notation.toLatin1().data()[len - 2] - 'a';
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H':
movedToColumn = notation.toLatin1().data()[len - 2] - 'A';
qDebug() << "Warning: column notation should use lower case in move " << notation;
break;
default:
qDebug() << "Invalid move: " << notation;
return;
}
break;
case '0': case 'O': case 'o':
typeMoving = King;
notation = notation.toLower();
if ( notation == "o-o-o" ) {
queenSideCastle = true;
qDebug() << " Queen Side Castle";
if ( whitesMove ) {
movedToRow = 0;
movedToColumn = 1;
} else {
movedToRow = 7;
movedToColumn = 1;
}
} else if ( notation == "o-o" ) {
kingSideCastle = true;
qDebug() << " King Side Castle";
if ( whitesMove ) {
movedToRow = 0;
movedToColumn = 6;
} else {
movedToRow = 7;
movedToColumn = 6;
}
} else {
qDebug() << "Invalid move: " << notation;
return;
}
movedFromColumn = 4;
movedFromRow = movedToRow;
return;
default:
qDebug() << "Invalid move: " << notation;
return;
}
if ( len == 2 ) {
typeMoving = Pawn;
movedFromColumn = movedToColumn;
if ( whitesMove ) {
if ( board->at( movedToRow - 1, movedFromColumn ).type == Pawn ) {
movedFromRow = movedToRow - 1;
} else {
movedFromRow = movedToRow - 2;
}
} else {
if ( board->at( movedToRow + 1, movedFromColumn ).type == Pawn ) {
movedFromRow = movedToRow + 1;
} else {
movedFromRow = movedToRow + 2;
}
}
return;
}
if ( notation.toLatin1().data()[len - 3] == 'x' || notation.toLatin1().data()[len - 3] == 'X' ) {
captureMove = true;
if ( len == 3 ) {
typeMoving = Pawn;
if ( whitesMove ) {
movedFromRow = movedToRow - 1;
} else {
movedFromRow = movedToRow + 1;
}
ChessBoardPieceDescription p = board->at( movedFromRow, movedToColumn - 1 );
if ( p.type == Pawn && p.side != whitesMove ) {
movedFromColumn = movedToColumn - 1;
} else {
movedFromColumn = movedToColumn + 1;
}
qDebug() << "Warning - notation should explicitly show the column the pawn captured from: " << notation;
return;
}
len--;
}
if ( len != 3 ) {
qDebug() << "Invalid move: " << notation;
return;
}
switch ( notation.toLatin1().data()[0] )
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'A':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
typeMoving = Pawn;
if ( !captureMove ) {
qDebug() << "Warning - appears to be error in notation: " << notation;
return;
} else {
if ( whitesMove ) {
movedFromRow = movedToRow - 1;
} else {
movedFromRow = movedToRow + 1;
}
ChessBoardPieceDescription p = board->at( movedFromRow, movedToColumn - 1 );
if ( p.type == Pawn && p.side != whitesMove ) {
movedFromColumn = movedToColumn - 1;
} else {
movedFromColumn = movedToColumn + 1;
}
}
break;
case 'R':
case 'r':
typeMoving = Rook;
foreach (AbstractChessPiece *piece, board->pieces) {
int c = piece->position.rank;
int d = piece->position.file;
int e = movedToRow;
int f = movedToColumn;
if ( c > e ) {
int g = e;
e = c;
c = g;
}
if ( d > f ) {
int g = f;
f = d;
d = g;
}
if ( (c == e || d == f) && piece->type == Rook && piece->color != whitesMove ) {
bool found = false;
if ( c == e ) {
for (int i = d + 1; i < f - 1; i++) {
if (board->at( movedToRow, i ).type != None )
found = true;
}
} else {
for (int i = c + 1; i < e - 1; i++) {
if (board->at( i, movedToColumn ).type != None )
found = true;
}
}
if ( !found ) {
movedFromRow = piece->position.rank;
movedFromColumn = piece->position.file;
return;
}
}
}
break;
case 'N':
case 'n':
typeMoving = Knight;
foreach (AbstractChessPiece *piece, board->pieces) {
int c = piece->position.rank - movedToRow;
int d = piece->position.file - movedToColumn;
if (c < 0)
c = -c;
if (d < 0)
d = -d;
if (c > d) {
int f = c;
c = d;
d = f;
}
if ( piece->type == Knight && piece->color != whitesMove ) {
qDebug() << "c: " << c << " d: " << d;
if ( c == 1 && d == 2 ) {
movedFromRow = piece->position.rank;
movedFromColumn = piece->position.file;
return;
}
}
}
break;
case 'B':
typeMoving = Bishop;
foreach (AbstractChessPiece *piece, board->pieces) {
//int g = (piece->position.rank + piece->position.file) % 2;
//int h = (movedToRow + movedToColumn) % 2;
int c = piece->position.rank - movedToRow;
int d = piece->position.file - movedToColumn;
if (c < 0)
c = -c;
if (d < 0)
d = -d;
if ( c == d && piece->type == Bishop && piece->color != whitesMove ) {
movedFromRow = piece->position.rank;
movedFromColumn = piece->position.file;
return;
}
}
break;
case 'K':
case 'k':
typeMoving = King;
foreach (AbstractChessPiece *piece, board->pieces) {
if ( piece->type == King && piece->color != whitesMove ) {
movedFromRow = piece->position.rank;
movedFromColumn = piece->position.file;
return;
}
}
break;
case 'Q':
case 'q':
{
typeMoving = Queen;
int queenCount = 0;
foreach (AbstractChessPiece *piece, board->pieces) {
if ( piece->type == Queen && piece->color != whitesMove ) {
movedFromRow = piece->position.rank;
movedFromColumn = piece->position.file;
queenCount++;
}
}
if (queenCount == 1)
return;
if (queenCount >= 1) {
// XXX Need to verify move carefully
}
}
break;
default:
qDebug() << "Invalid move: " << notation;
break;
}
}