Exemplo n.º 1
0
Arquivo: pos.c Projeto: raimarHD/lcec
bool posIsXSTMInCheck(const Pos *pos) {
	Move move=pos->data->lastMove; // We need to know if last move was castling.
	return (posIsSqAttackedByColour(pos, posGetKingSq(pos, colourSwap(pos->stm)), pos->stm) ||
	        (moveIsCastling(move) &&
	         (posIsSqAttackedByColour(pos, moveGetFromSq(move), pos->stm) ||
		      posIsSqAttackedByColour(pos, (moveGetToSq(move)+moveGetFromSq(move))/2, pos->stm))));
}
Exemplo n.º 2
0
Arquivo: pos.c Projeto: raimarHD/lcec
MoveType posMoveGetType(const Pos *pos, Move move){
	// Standard capture?
	Sq toSq=moveGetToSq(move);
	Piece capPiece=posGetPieceOnSq(pos, toSq);
	if (capPiece!=PieceNone)
		return MoveTypeCapture;

	// Promotion?
	Sq fromSq=moveGetFromSq(move);
	Piece fromPiece=posGetPieceOnSq(pos, fromSq);
	Piece toPiece=moveGetToPiece(move);
	if (fromPiece!=toPiece)
		return MoveTypeCapture;

	// En-passent capture?
	assert(capPiece==PieceNone);
	if (pieceGetType(fromPiece)==PieceTypePawn && sqFile(fromSq)!=sqFile(toSq))
		return MoveTypeCapture;

	// Otherwise must be quiet.
	return MoveTypeQuiet;
}
Exemplo n.º 3
0
Arquivo: pos.c Projeto: raimarHD/lcec
void posUndoMove(Pos *pos) {
	Move move=pos->data->lastMove;
	assert(moveIsValid(move) || move==MoveNone);

	// Update generic fields.
	pos->stm=colourSwap(pos->stm);
	pos->fullMoveNumber-=(pos->stm==ColourBlack);

	if (move!=MoveNone) {
		Sq fromSq=moveGetFromSq(move);
		Sq toSq=moveGetToSq(move);
		Piece toPiece=moveGetToPiece(move);

		// Move piece back.
		if (toPiece!=pos->data->movePiece) {
			assert(pieceGetType(pos->data->movePiece)==PieceTypePawn);
			posPieceMoveChange(pos, toSq, fromSq, pos->data->movePiece);
		} else
			posPieceMove(pos, toSq, fromSq);

		// Replace any captured piece.
		if (pos->data->capPiece!=PieceNone)
			posPieceAdd(pos, pos->data->capPiece, pos->data->capSq);

		// If castling replace the rook.
		if (pieceGetType(toPiece)==PieceTypeKing) {
			if (toSq==fromSq+2)
				posPieceMove(pos, toSq-1, toSq+1); // Kingside.
			else if (toSq==fromSq-2)
				posPieceMove(pos, toSq+1, toSq-2); // Queenside.
		}
	}

	// Discard data.
	--pos->data;

	assert(posIsConsistent(pos));
}
Exemplo n.º 4
0
Arquivo: pos.c Projeto: raimarHD/lcec
bool posMoveIsPromotion(const Pos *pos, Move move) {
	Piece fromPiece=posGetPieceOnSq(pos, moveGetFromSq(move));
	bool result=(fromPiece!=moveGetToPiece(move));
	assert(!result || pieceGetType(fromPiece)==PieceTypePawn);
	return result;
}
Exemplo n.º 5
0
Arquivo: pos.c Projeto: raimarHD/lcec
bool posCanMakeMove(const Pos *pos, Move move) {
	// Sanity checks and special case.
	assert(moveIsValid(move) || move==MoveNone);
	if (move==MoveNone)
		return true;

	// Use local variables to simulate having made the move.
	Colour stm=moveGetColour(move);
	assert(stm==posGetSTM(pos));
	Colour xstm=colourSwap(stm);
	BB occ=posGetBBAll(pos);
	BB opp=posGetBBColour(pos, xstm);
	Sq fromSq=moveGetFromSq(move);
	Sq toSq=moveGetToSq(move);
	BB fromBB=bbSq(fromSq);
	BB toBB=bbSq(toSq);
	Sq kingSq=posGetKingSq(pos, stm);

	if (fromSq==kingSq)
		kingSq=toSq; // King move.
	occ&=~fromBB; // Move piece.
	occ|=toBB;
	opp&=~toBB; // Potentially capture opp piece (so it cannot attack us later).
	if (moveGetToPieceType(move)==PieceTypePawn && sqFile(fromSq)!=sqFile(toSq) && posGetPieceOnSq(pos, toSq)==PieceNone) {
		// En-passent capture.
		assert(pos->data->epSq==toSq);
		occ^=bbSq(toSq^8);
		opp^=bbSq(toSq^8);
	}

	// Make a list of squares we need to ensure are unattacked.
	BB checkSquares=bbSq(kingSq);
	if (moveIsCastling(move))
		checkSquares|=fromBB|bbSq((toSq+fromSq)/2);

	// Test for attacks to any of checkSquares.
	// Pawns are done setwise.
	BB oppPawns=(posGetBBPiece(pos, pieceMake(PieceTypePawn, xstm)) & opp);
	if (bbForwardOne(bbWingify(oppPawns), xstm) & checkSquares)
		return false;
	// Pieces are checked for each square in checkSquares (which usually only has a single bit set anyway).
	while(checkSquares) {
		Sq sq=bbScanReset(&checkSquares);

		// Knights.
		if (attacksKnight(sq) & opp & posGetBBPiece(pos, pieceMake(PieceTypeKnight, xstm)))
			return false;

		// Bishops and diagonal queen moves.
		if (attacksBishop(sq, occ) & opp &
		    (posGetBBPiece(pos, pieceMake(PieceTypeBishopL, xstm)) |
		     posGetBBPiece(pos, pieceMake(PieceTypeBishopD, xstm)) |
		     posGetBBPiece(pos, pieceMake(PieceTypeQueen, xstm))))
			return false;

		// Rooks and orthogonal queen moves.
		if (attacksRook(sq, occ) & opp &
		    (posGetBBPiece(pos, pieceMake(PieceTypeRook, xstm)) |
		     posGetBBPiece(pos, pieceMake(PieceTypeQueen, xstm))))
			return false;

		// King.
		if (attacksKing(sq) & opp & posGetBBPiece(pos, pieceMake(PieceTypeKing, xstm)))
			return false;
	}

	return true;
}
Exemplo n.º 6
0
Arquivo: pos.c Projeto: raimarHD/lcec
bool posMakeMove(Pos *pos, Move move) {
	assert(moveIsValid(move) || move==MoveNone);
# ifndef NDEBUG
	bool canMakeMoveResult=posCanMakeMove(pos, move);
# endif

	// Use next data entry.
	if (pos->data+1>=pos->dataEnd) {
		// We need more space.
		size_t size=2*(pos->dataEnd-pos->dataStart);
		PosData *ptr=realloc(pos->dataStart, size*sizeof(PosData));
		if (ptr==NULL)
			return false;
		unsigned int dataOffset=pos->data-pos->dataStart;
		pos->dataStart=ptr;
		pos->dataEnd=ptr+size;
		pos->data=ptr+dataOffset;
	}
	++pos->data;

	// Update generic fields.
	Sq fromSq=moveGetFromSq(move);
	Sq toSq=moveGetToSq(move);
	pos->data->lastMove=move;
	pos->data->halfMoveNumber=(pos->data-1)->halfMoveNumber+1;
	pos->data->epSq=SqInvalid;
	pos->data->key=(pos->data-1)->key^posKeySTM^posKeyEP[(pos->data-1)->epSq];
	pos->data->cast=(pos->data-1)->cast;
	pos->data->movePiece=PieceNone;
	pos->data->capPiece=posGetPieceOnSq(pos, toSq);
	pos->data->capSq=toSq;
	pos->fullMoveNumber+=(pos->stm==ColourBlack); // Inc after black's move.
	pos->stm=colourSwap(pos->stm);

	if (move!=MoveNone) {
		Piece fromPiece=posGetPieceOnSq(pos, fromSq);
		pos->data->movePiece=fromPiece;

		// Update castling rights
		pos->data->cast&=posCastlingUpdate[fromSq] & posCastlingUpdate[toSq];

		switch(pieceGetType(fromPiece)) {
			case PieceTypePawn: {
				// Pawns are complicated so deserve a special case.

				// En-passent capture?
				bool isEP=(sqFile(fromSq)!=sqFile(toSq) && pos->data->capPiece==PieceNone);
				if (isEP) {
					pos->data->capSq^=8;
					pos->data->capPiece=pieceMake(PieceTypePawn, pos->stm);
					assert(posGetPieceOnSq(pos, pos->data->capSq)==pos->data->capPiece);
				}

				// Capture?
				if (pos->data->capPiece!=PieceNone)
					// Remove piece.
					posPieceRemove(pos, pos->data->capSq);

				// Move the pawn, potentially promoting.
				Piece toPiece=moveGetToPiece(move);
				if (toPiece!=fromPiece)
					posPieceMoveChange(pos, fromSq, toSq, toPiece);
				else
					posPieceMove(pos, fromSq, toSq);

				// Pawn moves reset 50 move counter.
				pos->data->halfMoveNumber=0;

				// If double pawn move check set EP capture square (for next move).
				if (abs(sqRank(toSq)-sqRank(fromSq))==2) {
					Sq epSq=toSq^8;
					if (posIsEPCap(pos, epSq))
						pos->data->epSq=epSq;
				}
			} break;
			case PieceTypeKing:
				// Castling.
				if (sqFile(toSq)==sqFile(fromSq)+2)
					posPieceMove(pos, toSq+1, toSq-1); // Kingside.
				else if (sqFile(toSq)==sqFile(fromSq)-2)
					posPieceMove(pos, toSq-2, toSq+1); // Queenside.

				// Fall through to move king.
			default:
				// Capture?
				if (pos->data->capPiece!=PieceNone) {
					// Remove piece.
					posPieceRemove(pos, toSq);

					// Captures reset 50 move counter.
					pos->data->halfMoveNumber=0;
				}

				// Move non-pawn piece (i.e. no promotion to worry about).
				posPieceMove(pos, fromSq, toSq);
			break;
		}

		// Does move leave STM in check?
		if (posIsXSTMInCheck(pos)) {
			posUndoMove(pos);
			assert(!canMakeMoveResult);
			return false;
		}

		// Update key.
		pos->data->key^=posKeyCastling[pos->data->cast^(pos->data-1)->cast]^posKeyEP[pos->data->epSq];
	}

	assert(posIsConsistent(pos));
	assert(canMakeMoveResult);

	return true;
}
Exemplo n.º 7
0
bool moveIsDP(Move move) {
	assert(moveIsValid(move));
	int toRank=sqRank(moveGetToSqRaw(move));
	int fromRank=sqRank(moveGetFromSq(move));
	return (moveGetToPieceType(move)==PieceTypePawn && abs(toRank-fromRank)==2);
}
Exemplo n.º 8
0
bool moveIsValid(Move move) {
	return (moveGetFromSq(move)!=moveGetToSqRaw(move));
}