Esempio n. 1
0
Move JanusBoard::moveFromSanString(const QString& str)
{
	/*
	 * accepts O-O and Kb1/Kb8/Ki1/Ki8 formats for castling
	 * Xboard uses O-O for B-file and Ki1/Ki8 for I-file castling
	 */
	if (str.startsWith("O-O-O"))
		return WesternBoard::moveFromSanString("O-O");
	if (str.startsWith("O-O"))
		return WesternBoard::moveFromSanString("O-O-O");

	if (!str.startsWith(pieceSymbol(King).toUpper()))
		return WesternBoard::moveFromSanString(str);  //main path

	if (hasCastlingRight(sideToMove(), KingSide))
	{
		Move castlingMove = WesternBoard::moveFromSanString("O-O");
		if (!castlingMove.isNull() && str == sanMoveString(castlingMove))
			return castlingMove;
	}
	if (hasCastlingRight(sideToMove(), QueenSide))
	{
		Move castlingMove = WesternBoard::moveFromSanString("O-O-O");
		if (!castlingMove.isNull() && str == sanMoveString(castlingMove))
			return castlingMove;
	}

	return WesternBoard::moveFromSanString(str); // normal king moves
}
Esempio n. 2
0
extern int parseUciMove(Board_t self, const char *line, int xMoves[maxMoves], int xlen, int *move)
{
        int ix = 0; // index into line
        int rawMove = 0;

        while (isspace(line[ix])) // Skip white space
                ix++;

        int castleLen;
        int nrOh = parseCastling(&line[ix], &castleLen);

        if (nrOh == 2) { // King-side castling
                int rank = (sideToMove(self) == white) ? rank1 : rank8;
                rawMove = move(square(fileE, rank), square(fileG, rank));
                ix += castleLen;
        } else if (nrOh == 3) { // Queen-side castling
                int rank = (sideToMove(self) == white) ? rank1 : rank8;
                rawMove = move(square(fileE, rank), square(fileC, rank));
                ix += castleLen;
        } else { // Regular move
                if ('a' > line[ix+0] || line[ix+0] > 'h'
                 || '1' > line[ix+1] || line[ix+1] > '8'
                 || 'a' > line[ix+2] || line[ix+2] > 'h'
                 || '1' > line[ix+3] || line[ix+3] > '8')
                        return 0;

                int fromFile = charToFile(line[ix++]);
                int fromRank = charToRank(line[ix++]);
                int toFile   = charToFile(line[ix++]);
                int toRank   = charToRank(line[ix++]);

                rawMove = move(square(fromFile, fromRank), square(toFile, toRank));

                if (line[ix] == 'q' || line[ix] == 'r'
                 || line[ix] == 'b' || line[ix] == 'n')
                        rawMove += promotionFlags[(int)line[ix++]];
        }

        if (!isspace(line[ix]) && line[ix] != '\0')
                return 0; // Reject garbage following the move

        // Find matching move from move list and verify its legality
        for (int i=0; i<xlen; i++) {
                int xMove = xMoves[i];
                if ((xMove & ~specialMoveFlag) == rawMove && isLegalMove(self, xMove)) {
                        *move = xMove;
                        return ix;
                }
        }
        return 0;
}
Esempio n. 3
0
void OukBoard::generateMovesForPiece(QVarLengthArray< Move >& moves,
					  int pieceType,
					  int square) const
{
	MakrukBoard::generateMovesForPiece(moves, pieceType, square);

	Side side = sideToMove();

	// Only consider King and Neang on their initial squares
	if ((pieceType != King || square != m_initialSquare[side][King])
	&&  (pieceType != Maiden || square != m_initialSquare[side][Maiden]))
		return;
	// Return if the piece has moved already
	if (m_moveCount[side].value((OukPieceType)pieceType, -1) != 0)
		return;
	// No special moves for King in check
	if (pieceType == King && inCheck(side))
		return;

	// Generate initial move option for King (leap of Horse)
	// and for Neang (forward two squares)
	int sign = (side == Side::White) ? 1 : -1;

	for (const auto& i: m_initialOffsets)
	{
		if (pieceType != i.type)
			continue;

		int target = square - i.offset * sign;
		const Piece& piece = pieceAt(target);

		if  (piece.isEmpty())
			moves.append(Move(square, target));
	}
}
Esempio n. 4
0
bool RacingKingsBoard::isLegalPosition()
{
	Side side = sideToMove();
	if (inCheck(side))
		return false;

	return WesternBoard::isLegalPosition();
}
Esempio n. 5
0
void CrazyhouseBoard::vUndoMove(const Move& move)
{
	int source = move.sourceSquare();
	int target = move.targetSquare();
	int prom = move.promotion();

	Move tmp(move);
	if (source != 0 && prom != Piece::NoPiece)
		tmp = Move(source, target, promotedPieceType(prom));

	WesternBoard::vUndoMove(tmp);

	int ctype = captureType(move);
	if (ctype != Piece::NoPiece)
		removeFromReserve(Piece(sideToMove(), reserveType(ctype)));
	else if (source == 0)
		addToReserve(Piece(sideToMove(), prom));
}
Esempio n. 6
0
Result LosersBoard::result()
{
	Side winner;
	QString str;

	// Checkmate/Stalemate
	if (!canMove())
	{
		winner = sideToMove();
		str = tr("%1 gets mated").arg(winner.toString());
		return Result(Result::Win, winner, str);
	}

	// Lost all pieces
	int pieceCount = 0;
	for (int i = 0; i < arraySize(); i++)
	{
		if (pieceAt(i).side() == sideToMove()
		&&  ++pieceCount > 1)
			break;
	}
	if (pieceCount <= 1)
	{
		winner = sideToMove();
		str = tr("%1 lost all pieces").arg(winner.toString());
		return Result(Result::Win, winner, str);
	}

	// 50 move rule
	if (reversibleMoveCount() >= 100)
	{
		str = tr("Draw by fifty moves rule");
		return Result(Result::Draw, Side::NoSide, str);
	}

	// 3-fold repetition
	if (repeatCount() >= 2)
	{
		str = tr("Draw by 3-fold repetition");
		return Result(Result::Draw, Side::NoSide, str);
	}

	return Result();
}
Esempio n. 7
0
Result HordeBoard::result()
{
	Side side = sideToMove();
	Side opp = side.opposite();
	if (!hasMaterial(side))
		return Result(Result::Win, opp,
			      tr("%1 wins").arg(opp.toString()));

	return StandardBoard::result();
}
Esempio n. 8
0
Result KarOukBoard::result()
{
	Side side = sideToMove();
	if (!inCheck(side))
		return OukBoard::result();

	Side opp = side.opposite();
	QString str = tr("%1 wins by giving check").arg(opp.toString());
	return Result(Result::Win, opp, str);
}
Esempio n. 9
0
Result RacingKingsBoard::result()
{
	QString str;
	bool blackFinished = finished(Side::Black);
	bool whiteFinished = finished(Side::White);

	// Finishing on eighth rank
	if (blackFinished && whiteFinished)
	{
		str = tr("Drawn race");
		return Result(Result::Draw, Side::NoSide, str);
	}

	if (blackFinished)
	{
		str = tr("Black wins the race");
		return Result(Result::Win, Side::Black, str);
	}

	Side side = sideToMove();
	bool mobile = canMove();

	// White finished but Black cannot finish or forfeited the chance
	if (whiteFinished
	&& ((mobile && !canFinish(Side::Black)) || side == Side::White))
	{
		str = tr("White wins the race");
		return Result(Result::Win, Side::White, str);
	}

	// Stalemate
	if (!mobile)
	{
		str = tr("Draw by stalemate");
		return Result(Result::Draw, Side::NoSide, str);
	}

	// 50 move rule
	if (reversibleMoveCount() >= 100)
	{
		str = tr("Draw by fifty moves rule");
		return Result(Result::Draw, Side::NoSide, str);
	}

	// 3-fold repetition
	if (repeatCount() >= 2)
	{
		str = tr("Draw by 3-fold repetition");
		return Result(Result::Draw, Side::NoSide, str);
	}

	return Result();
}
Esempio n. 10
0
void CrazyhouseBoard::vMakeMove(const Move& move, BoardTransition* transition)
{
	int source = move.sourceSquare();
	int target = move.targetSquare();
	int prom = move.promotion();

	Move tmp(move);
	if (source != 0 && prom != Piece::NoPiece)
		tmp = Move(source, target, promotedPieceType(prom));
	
	int ctype = captureType(move);
	if (ctype != Piece::NoPiece)
	{
		Piece reservePiece(sideToMove(), reserveType(ctype));
		addToReserve(reservePiece);
		if (transition != 0)
			transition->addReservePiece(reservePiece);
	}
	else if (source == 0)
		removeFromReserve(Piece(sideToMove(), prom));

	return WesternBoard::vMakeMove(tmp, transition);
}
Esempio n. 11
0
void OukBoard::updateCounter(Move m, int increment)
{
	Side side = sideToMove();
	int source = m.sourceSquare();
	int target= m.targetSquare();

	if (source == m_initialSquare[side][King]
	||  target == m_initialSquare[side][King])
		m_moveCount[side][King] += increment;

	if (source == m_initialSquare[side][Maiden]
	||  target == m_initialSquare[side][Maiden])
		m_moveCount[side][Maiden] += increment;
}
Esempio n. 12
0
void normalizeEnPassantStatus(Board_t self)
{
        int square = self->enPassantPawn;
        if (!square)
                return;

        int pawn = (sideToMove(self) == white) ? whitePawn : blackPawn;
        int step = (sideToMove(self) == white) ? stepN : stepS;

        if (file(square) != fileA && self->squares[square+stepW] == pawn) {
                int move = specialMove(square + stepW, square + step);
                if (isLegalMove(self, move))
                        return;
        }
        if (file(square) != fileH && self->squares[square+stepE] == pawn) {
                int move = specialMove(square + stepE, square + step);
                if (isLegalMove(self, move))
                        return;
        }

        self->hash ^= hashEnPassant(square);
        self->enPassantPawn = 0;
}
Esempio n. 13
0
int get_Heuristic (Board *board , int depth){

	if ( board == NULL ) {
		logChess(WARN, "The board is null.");
		return NULL_BOARD;
	}

	if ( depth < 0 ) {
		logChess(WARN, "The depth is not correct. Minor than 0.");
		return BAD_DEPTH;
	}

	if(evaluateOurCheck(board)!=KING_IN_CHECK)
	{

		Board tmpBoard;
		memcpy(&tmpBoard, board, sizeof(Board));

		int material = 		getTotalTableMaterial(&tmpBoard);

		int mineMaterial=	getMaterial(board,board->myColor);					 //Calculating mine material to evaluate the game phase
		int movements=		getCurrentMovement(depth);							 //Calculating number of movements to calculate game phase
		int phase	 =		getGamePhase(board,movements,mineMaterial); 		 //Calculating phase of the game to be used in position
		int position = 		getTotalPiecePositionValue(&tmpBoard,depth,phase);	// Calculating game phase according to the position

		int menaced  =		getMenacedValueTotal(tmpBoard.myColor,&tmpBoard);

		int side = 			sideToMove(depth);
		int evaluation = 	0;
		if ( phase == END) {
			evaluation=2*material+ 0.5*position+ 0.1*menaced;
		} else {
			evaluation=1.6*material + 0.9*position+ 0.2*menaced;
		}


		//printf("material:%d + position:%d + menaced:%d = evaluation:%d\n", material, position, menaced, evaluation); //ONLY FOR TEST

		return evaluation * side;
	}

	else 	//we are in check, it's not useful to check with the heuristic
	{
		return OUR_CHECK_VALUE;
	}
}
Esempio n. 14
0
// Helper to generate slider moves
static void generateSlides(Board_t self, int from, int dirs)
{
        dirs &= kingDirections[from];
        int dir = 0;
        do {
                dir = (dir - dirs) & dirs; // pick next
                int vector = kingStep[dir];
                int to = from;
                do {
                        to += vector;
                        if (self->squares[to] != empty) {
                                if (pieceColor(self->squares[to]) != sideToMove(self))
                                        pushMove(self, from, to);
                                break;
                        }
                        pushMove(self, from, to);
                } while (dir & kingDirections[to]);
        } while (dirs -= dir); // remove and go to next
}
Esempio n. 15
0
// Calculate Zobrist hash using Polyglot's definition
uint64_t hash(Board_t self)
{
        uint64_t key = 0;

        // Pieces
        for (int square=0; square<boardSize; square++)
                key ^= zobristPiece[self->squares[square]][square];

        // Castling
        key ^= hashCastleFlags(self->castleFlags);

        // En passant
        key ^= hashEnPassant(self->enPassantPawn);

        // Turn
        if (sideToMove(self) == white)
                key ^= zobristTurn[0];

        return key;
}
Esempio n. 16
0
Move CrazyhouseBoard::moveFromSanString(const QString& str)
{
	if (str.isEmpty())
		return Move();

	Piece piece(pieceFromSymbol(str.at(0)));
	if (piece.isValid())
	{
		piece.setSide(sideToMove());
		QVarLengthArray<int> squares;

		normalizePieces(piece, squares);
		Move move(WesternBoard::moveFromSanString(str));
		restorePieces(piece, squares);

		return move;
	}

	return WesternBoard::moveFromSanString(str);
}
Esempio n. 17
0
extern int setupBoard(Board_t self, const char *fen)
{
        int ix = 0;

        /*
         *  Squares
         */

        while (isspace(fen[ix])) ix++;

        int file = fileA, rank = rank8;
        int nrWhiteKings = 0, nrBlackKings = 0;
        memset(self->squares, empty, boardSize);
        self->materialKey = 0;
        while (rank != rank1 || file != fileH + fileStep) {
                int piece = empty;
                int count = 1;

                switch (fen[ix]) {
                case 'K': piece = whiteKing; nrWhiteKings++; break;
                case 'Q': piece = whiteQueen; break;
                case 'R': piece = whiteRook; break;
                case 'B': piece = whiteBishop; break;
                case 'N': piece = whiteKnight; break;
                case 'P': piece = whitePawn; break;
                case 'k': piece = blackKing; nrBlackKings++; break;
                case 'r': piece = blackRook; break;
                case 'q': piece = blackQueen; break;
                case 'b': piece = blackBishop; break;
                case 'n': piece = blackKnight; break;
                case 'p': piece = blackPawn; break;
                case '/': rank -= rankStep; file = fileA; ix++; continue;
                case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8':
                        count = fen[ix] - '0';
                        break;
                default:
                        return 0; // FEN error
                }
                int squareColor = squareColor(square(file,rank));
                self->materialKey += materialKeys[piece][squareColor];
                do {
                        self->squares[square(file,rank)] = piece;
                        file += fileStep;
                } while (--count && file != fileH + fileStep);
                ix++;
        }
        if (nrWhiteKings != 1 || nrBlackKings != 1) return 0;

        /*
         *  Side to move
         */

        self->plyNumber = 2 + (fen[ix+1] == 'b'); // 2 means full move number starts at 1
        //self->lastZeroing = self->plyNumber;
        ix += 2;

        /*
         *  Castling flags
         */

        while (isspace(fen[ix])) ix++;

        self->castleFlags = 0;
        for (;; ix++) {
                switch (fen[ix]) {
                case 'K': self->castleFlags |= castleFlagWhiteKside; continue;
                case 'Q': self->castleFlags |= castleFlagWhiteQside; continue;
                case 'k': self->castleFlags |= castleFlagBlackKside; continue;
                case 'q': self->castleFlags |= castleFlagBlackQside; continue;
                case '-': ix++; break;
                default: break;
                }
                break;
        }

        /*
         *  En passant square
         */

        while (isspace(fen[ix])) ix++;

        if ('a' <= fen[ix] && fen[ix] <= 'h') {
                file = charToFile(fen[ix]);
                ix++;

                rank = (sideToMove(self) == white) ? rank5 : rank4;
                if (isdigit(fen[ix])) ix++; // ignore what it says

                self->enPassantPawn = square(file, rank);
        } else {
                self->enPassantPawn = 0;
                if (fen[ix] == '-')
                        ix++;
        }

        // Eat move number and halfmove clock. TODO: process this properly
        while (isspace(fen[ix])) ix++;
        while (isdigit(fen[ix])) ix++;
        while (isspace(fen[ix])) ix++;
        while (isdigit(fen[ix])) ix++;

        self->sideInfoPlyNumber = -1; // side info is invalid now

        // Reset the undo stack
        self->undoStack.len = 0;

        // Initialize hash and its history
        self->hash = hash(self);
        self->hashHistory.len = 0;

        self->pawnKingHash = pawnKingHash(self);
        self->pkHashHistory.len = 0;

        normalizeEnPassantStatus(self); // Only safe after update of hash

        self->eloDiff = 0;

        return ix;
}
Esempio n. 18
0
/*
 *  Pseudo-legal move generator
 */
extern int generateMoves(Board_t self, int moveList[maxMoves])
{
        int side = sideToMove(self);
        updateSideInfo(self);

        self->movePtr = moveList;

        for (int from=0; from<boardSize; from++) {
                int piece = self->squares[from];
                if (piece == empty || pieceColor(piece) != sideToMove(self))
                        continue;

                /*
                 *  Generate moves for this piece
                 */
                int to;
                switch (piece) {
                        int dir, dirs;

                case whiteKing: case blackKing:
                        dirs = kingDirections[from];
                        dir = 0;
                        do {
                                dir = (dir - dirs) & dirs; // pick next
                                to = from + kingStep[dir];
                                if (self->squares[to] == empty
                                 || pieceColor(self->squares[to]) != sideToMove(self))
                                        if (self->sides[other(side)].attacks[to] == 0)
                                                pushMove(self, from, to);
                        } while (dirs -= dir); // remove and go to next
                        break;

                case whiteQueen: case blackQueen:
                        generateSlides(self, from, dirsQueen);
                        break;

                case whiteRook: case blackRook:
                        generateSlides(self, from, dirsRook);
                        break;

                case whiteBishop: case blackBishop:
                        generateSlides(self, from, dirsBishop);
                        break;

                case whiteKnight: case blackKnight:
                        dirs = knightDirections[from];
                        dir = 0;
                        do {
                                dir = (dir - dirs) & dirs; // pick next
                                to = from + knightJump[dir];
                                if (self->squares[to] == empty
                                 || pieceColor(self->squares[to]) != sideToMove(self))
                                        pushMove(self, from, to);
                        } while (dirs -= dir); // remove and go to next
                        break;

                case whitePawn:
                        if (file(from) != fileH) {
                                to = from + stepNE;
                                if (self->squares[to] != empty
                                 && pieceColor(self->squares[to]) == black)
                                        pushPawnMove(self, from, to);
                        }
                        if (file(from) != fileA) {
                                to = from + stepNW;
                                if (self->squares[to] != empty
                                 && pieceColor(self->squares[to]) == black)
                                        pushPawnMove(self, from, to);
                        }
                        to = from + stepN;
                        if (self->squares[to] != empty)
                                break;

                        pushPawnMove(self, from, to);
                        if (rank(from) == rank2) {
                                to += stepN;
                                if (self->squares[to] == empty) {
                                        pushMove(self, from, to);
                                        if (self->sides[black].attacks[to+stepS])
                                                self->movePtr[-1] |= specialMoveFlag;
                                }
                        }
                        break;

                case blackPawn:
                        if (file(from) != fileH) {
                                to = from + stepSE;
                                if (self->squares[to] != empty
                                 && pieceColor(self->squares[to]) == white)
                                        pushPawnMove(self, from, to);
                        }
                        if (file(from) != fileA) {
                                to = from + stepSW;
                                if (self->squares[to] != empty
                                 && pieceColor(self->squares[to]) == white)
                                        pushPawnMove(self, from, to);
                        }
                        to = from + stepS;
                        if (self->squares[to] != empty)
                                break;

                        pushPawnMove(self, from, to);
                        if (rank(from) == rank7) {
                                to += stepS;
                                if (self->squares[to] == empty) {
                                        pushMove(self, from, to);
                                        if (self->sides[white].attacks[to+stepN])
                                                self->movePtr[-1] |= specialMoveFlag;
                                }
                        }
                        break;
                }
        }

        /*
         *  Generate castling moves
         */
        if (self->castleFlags && !isInCheck(self)) {
                static const int flags[2][2] = {
                        { castleFlagWhiteKside, castleFlagWhiteQside },
                        { castleFlagBlackKside, castleFlagBlackQside }
                };

                int side = sideToMove(self);
                int sq = self->sides[side].king;

                if ((self->castleFlags & flags[side][0])
                 && self->squares[sq+stepE] == empty
                 && self->squares[sq+2*stepE] == empty
                 && self->sides[other(side)].attacks[sq+stepE] == 0
                 && self->sides[other(side)].attacks[sq+2*stepE] == 0)
                        pushSpecialMove(self, sq, sq + 2*stepE);

                if ((self->castleFlags & flags[side][1])
                 && self->squares[sq+stepW] == empty
                 && self->squares[sq+2*stepW] == empty
                 && self->squares[sq+3*stepW] == empty
                 && self->sides[other(side)].attacks[sq+stepW] == 0
                 && self->sides[other(side)].attacks[sq+2*stepW] == 0)
                        pushSpecialMove(self, sq, sq + 2*stepW);
        }

        /*
         *  Generate en passant captures
         */
        if (self->enPassantPawn) {
                static const int steps[] = { stepN, stepS };
                static const int pawns[] = { whitePawn, blackPawn };

                int step = steps[sideToMove(self)];
                int pawn = pawns[sideToMove(self)];
                int ep = self->enPassantPawn;

                if (file(ep) != fileA && self->squares[ep+stepW] == pawn)
                        pushSpecialMove(self, ep + stepW, ep + step);

                if (file(ep) != fileH && self->squares[ep+stepE] == pawn)
                        pushSpecialMove(self, ep + stepE, ep + step);
        }

        return self->movePtr - moveList; // nrMoves
}
Esempio n. 19
0
int isInCheck(Board_t self)
{
        updateSideInfo(self);
        int side = sideToMove(self);
        return self->sides[other(side)].attacks[self->sides[side].king] != 0;
}
Esempio n. 20
0
extern void boardToFen(Board_t self, char *fen)
{
        /*
         *  Squares
         */
        for (int rank=rank8; rank!=rank1-rankStep; rank-=rankStep) {
                int emptySquares = 0;
                for (int file=fileA; file!=fileH+fileStep; file+=fileStep) {
                        int square = square(file, rank);
                        int piece = self->squares[square];

                        if (piece != empty) {
                                if (emptySquares > 0) *fen++ = '0' + emptySquares;
                                *fen++ = pieceToChar[piece];
                                emptySquares = 0;
                        } else
                                emptySquares++;
                }
                if (emptySquares > 0) *fen++ = '0' + emptySquares;
                if (rank != rank1) *fen++ = '/';
        }

        /*
         *  Side to move
         */
        *fen++ = ' ';
        *fen++ = (sideToMove(self) == white) ? 'w' : 'b';

        /*
         *  Castling flags
         */
        *fen++ = ' ';
        if (self->castleFlags) {
                if (self->castleFlags & castleFlagWhiteKside) *fen++ = 'K';
                if (self->castleFlags & castleFlagWhiteQside) *fen++ = 'Q';
                if (self->castleFlags & castleFlagBlackKside) *fen++ = 'k';
                if (self->castleFlags & castleFlagBlackQside) *fen++ = 'q';
        } else
                *fen++ = '-';

        /*
         *  En-passant square
         */
        *fen++ = ' ';
        normalizeEnPassantStatus(self);
        if (self->enPassantPawn) {
                *fen++ = fileToChar(file(self->enPassantPawn));
                *fen++ = rankToChar((sideToMove(self) == white) ? rank6 : rank3);
        } else
                *fen++ = '-';

        /*
         *  Move number (TODO)
         */

        /*
         *  Halfmove clock (TODO)
         */

        *fen = '\0';
}