Newer
Older
Import / applications / Chess / AbstractChessMove.cpp
/*
 * =====================================================================================
 *
 *       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;
    }
}