Beispiel #1
0
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));
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
PieceType moveGetToPieceType(Move move) {
	assert(moveIsValid(move));
	return pieceGetType(moveGetToPiece(move));
}