Exemplo n.º 1
0
BitBaseResultFull bitbaseComputeStaticResult(Sq pawnSq, Sq wKingSq, Colour stm, Sq bKingSq) {
	// Sanity checks.
	assert(sqIsValid(pawnSq) && sqFile(pawnSq)<=FileD);
	assert(sqIsValid(wKingSq));
	assert(colourIsValid(stm));
	assert(sqIsValid(bKingSq));

	// Init.
	BB wKingAtks=attacksKing(wKingSq);
	BB bKingAtks=attacksKing(bKingSq);
	BB pawnAtks=attacksPawn(pawnSq, ColourWhite);
	BB wKingBB=bbSq(wKingSq);
	BB bKingBB=bbSq(bKingSq);
	BB pawnBB=bbSq(pawnSq);
	BB occ=(pawnBB | wKingBB | bKingBB);

	// If any pieces occupy the same square, or the side not on move is in check, invalid position.
	if (pawnSq==wKingSq || pawnSq==bKingSq || wKingSq==bKingSq || // Pieces overlap.
	    sqRank(pawnSq)==Rank1 || // Pawn on rank 1.
	    (wKingAtks & bKingBB)!=BBNone || // Kings are adjacent.
	    (stm==ColourWhite && (pawnAtks & bKingBB)!=BBNone)) // White to move, black king attacked by pawn.
		return BitBaseResultFullInvalid;

	// If pawn can promote without capture, win.
	if (sqRank(pawnSq)==Rank7 && stm==ColourWhite) {
		Sq promoSq=sqNorth(pawnSq,1);
		if (promoSq!=wKingSq && promoSq!=bKingSq && // Promotion square empty.
		    ((bbSq(promoSq) & bKingAtks)==BBNone || (bbSq(promoSq) & wKingAtks)!=BBNone)) // Promotion square is safe.
			return BitBaseResultFullWin;
	}

	// If black can capture pawn, draw.
	bool pawnAttacked=((bKingAtks & pawnBB)!=BBNone);
	bool pawnDefended=((wKingAtks & pawnBB)!=BBNone);
	if (stm==ColourBlack && pawnAttacked && !pawnDefended)
	    return BitBaseResultFullDraw;

	// If 'pawn' is on 8th rank, win (we have already shown that it cannot be captured).
	if (sqRank(pawnSq)==Rank8)
		return BitBaseResultFullWin;

	// If no moves available for stm, draw (stalemate).
	if (stm==ColourWhite) {
		BB safe=~(bKingAtks | occ);
		if ((wKingAtks & safe)==BBNone && // No king moves.
		    (sqNorth(pawnSq,1)==wKingSq || sqNorth(pawnSq,1)==bKingSq)) // No pawn moves.
			return BitBaseResultFullDraw;
	} else {
		BB safe=~(wKingAtks | pawnAtks | occ); // We already check if black can capture pawn, hence assume defended.
		if ((bKingAtks & safe)==BBNone)
			return BitBaseResultFullDraw;
	}

	// Unable to statically evaluate the position.
	return BitBaseResultFullUnknown;
}
Exemplo n.º 2
0
Arquivo: pos.c Projeto: raimarHD/lcec
void posDraw(const Pos *pos) {
	// Header.
	uciWrite("Position:\n");

	// Board with pieces.
	int file, rank;
	for(rank=Rank8;rank>=Rank1;--rank) {
		uciWrite("%i|", (rank+8)-Rank8);
		for(file=FileA;file<=FileH;++file)
			uciWrite(" %c", pieceToChar(posGetPieceOnSq(pos, sqMake(file,rank))));
		uciWrite("\n");
	}
	uciWrite("   ----------------\n");
	uciWrite("  ");
	for(file=FileA;file<=FileH;++file)
		uciWrite(" %c", (file+'a')-FileA);
	uciWrite("\n");

	// Other information.
	uciWrite("STM: %s\n", colourToStr(posGetSTM(pos)));
	uciWrite("Castling rights: %s\n", posCastRightsToStr(posGetCastRights(pos)));
	if (pos->data->epSq!=SqInvalid)
		uciWrite("EP-sq: %c%c\n", fileToChar(sqFile(pos->data->epSq)), rankToChar(sqRank(pos->data->epSq)));
	else
		uciWrite("EP-sq: -\n");
	uciWrite("Half move number: %u\n", pos->data->halfMoveNumber);
	uciWrite("Full move number: %u\n", pos->fullMoveNumber);
	uciWrite("Base hash key: %016"PRIxKey"\n", posGetKey(pos));
	uciWrite("Pawn hash key: %016"PRIxKey"\n", posGetPawnKey(pos));
	uciWrite("Material hash key: %016"PRIxKey"\n", posGetMatKey(pos));
}
Exemplo n.º 3
0
BitBaseResult bitbaseProbeRaw(Sq pawnSq, Sq wKingSq, Sq bKingSq, Colour stm) {
	// Sanity checks.
	assert(sqIsValid(pawnSq));
	assert(sqIsValid(wKingSq));
	assert(sqIsValid(bKingSq));
	assert(colourIsValid(stm));

	// Adjust so pawn is in left half of board (on files A, B, C or D).
	File pawnFile=sqFile(pawnSq);
	Rank pawnRank=sqRank(pawnSq);
	if (pawnFile>FileD) {
		pawnFile=fileMirror(pawnFile);
		wKingSq=sqMirror(wKingSq);
		bKingSq=sqMirror(bKingSq);
	}

	// Probe.
	unsigned int index=bitbaseIndex(pawnFile, pawnRank, wKingSq, stm);
	return (bitbase[index]>>bKingSq)&1;
}
Exemplo n.º 4
0
BitBaseResultFull bitbaseComputeDynamicResult(const BitBaseResultFull *array, Sq pawnSq, Sq wKingSq, Colour stm, Sq bKingSq) {
	// Sanity checks.
	assert(sqIsValid(pawnSq) && sqFile(pawnSq)<=FileD && sqRank(pawnSq)>=Rank2 && sqRank(pawnSq)<=Rank7);
	assert(sqIsValid(wKingSq));
	assert(colourIsValid(stm));
	assert(sqIsValid(bKingSq));

	// If white to move and any children are wins, win. If white to move and
	// all children are draws, draw.
	// If black to move and any children are draws, draw. If black to move
	// and all children are wins, win.
	File pawnFile=sqFile(pawnSq);
	Rank pawnRank=sqRank(pawnSq);
	Colour xstm=colourSwap(stm);
	if (stm==ColourWhite) {
		bool allDraws=true;

		// King moves.
		BB set=attacksKing(wKingSq);
		while(set) {
			unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank, bbScanReset(&set), xstm, bKingSq);
			switch(array[newIndex]) {
				case BitBaseResultFullInvalid: break; // Invalid move.
				case BitBaseResultFullUnknown: allDraws=false; break;
				case BitBaseResultFullDraw: break;
				case BitBaseResultFullWin: return BitBaseResultFullWin; break;
			}
		}

		// Standard pawn move forward.
		// We do not need to test for moving to 8th rank or into either of the kings as such positions will be marked already.
		unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank+1, wKingSq, xstm, bKingSq);
		bool singlePushOk=true;
		switch(array[newIndex]) {
			case BitBaseResultFullInvalid: singlePushOk=false; break; // Invalid move.
			case BitBaseResultFullUnknown: allDraws=false; break;
			case BitBaseResultFullDraw: break;
			case BitBaseResultFullWin: return BitBaseResultFullWin; break;
		}

		// Double pawn move.
		// Again we do not need to check for moving into either of the kings.
		if (pawnRank==Rank2 && singlePushOk) {
			unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank+2, wKingSq, xstm, bKingSq);
			switch(array[newIndex]) {
				case BitBaseResultFullInvalid: break; // Invalid move.
				case BitBaseResultFullUnknown: allDraws=false; break;
				case BitBaseResultFullDraw: break;
				case BitBaseResultFullWin: return BitBaseResultFullWin; break;
			}
		}

		return (allDraws ? BitBaseResultFullDraw : BitBaseResultFullUnknown);
	} else {
		// King moves.
		bool allWins=true;
		BB set=attacksKing(bKingSq);
		while(set) {
			unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, xstm, bbScanReset(&set));
			switch(array[newIndex]) {
				case BitBaseResultFullInvalid: break; // Invalid move.
				case BitBaseResultFullUnknown: allWins=false; break;
				case BitBaseResultFullDraw: return BitBaseResultFullDraw; break;
				case BitBaseResultFullWin: break;
			}
		}

		return (allWins ? BitBaseResultFullWin : BitBaseResultFullUnknown);
	}

	assert(false);
	return BitBaseResultFullInvalid;
}
Exemplo n.º 5
0
Arquivo: pos.c Projeto: raimarHD/lcec
bool posLegalMoveExists(const Pos *pos, MoveType type) {
	Colour stm=posGetSTM(pos);
	BB occ=posGetBBAll(pos);
	BB opp=posGetBBColour(pos, colourSwap(stm));
	BB allowed=BBNone; // Squares pieces can move to.
	if (type & MoveTypeQuiet) allowed|=~occ;
	if (type & MoveTypeCapture) allowed|=opp;

	// Pieces (ordered for speed).
	if (posLegalMoveExistsPiece(pos, PieceTypeKing, allowed) ||
	    posLegalMoveExistsPiece(pos, PieceTypeKnight, allowed) ||
	    posLegalMoveExistsPiece(pos, PieceTypeQueen, allowed) ||
	    posLegalMoveExistsPiece(pos, PieceTypeRook, allowed) ||
	    posLegalMoveExistsPiece(pos, PieceTypeBishopL, allowed) ||
	    posLegalMoveExistsPiece(pos, PieceTypeBishopD, allowed))
		goto success;

	// Pawns.
	Piece piece=pieceMake(PieceTypePawn, stm);
	BB pawns=posGetBBPiece(pos, piece);
	BB forwardPawns=(bbForwardOne(pawns, stm) & ~occ);
	int delta;
	BB set;

	if (type & MoveTypeQuiet) {
		// Pawns - standard move forward.
		delta=(stm==ColourWhite ? 8 : -8);
		set=(forwardPawns & ~(stm==ColourWhite ? bbRank(Rank8) : bbRank(Rank1)));
		while(set) {
			Sq toSq=bbScanReset(&set);
			Sq fromSq=toSq-delta;
			Move move=moveMake(fromSq, toSq, piece);
			if (posCanMakeMove(pos, move))
				goto success;
		}

		// Pawns - double first move.
		delta=(stm==ColourWhite ? 16 : -16);
		set=(bbForwardOne(forwardPawns, stm) & ~occ);
		set&=(stm==ColourWhite ? bbRank(Rank4) : bbRank(Rank5));
		while(set) {
			Sq toSq=bbScanReset(&set);
			Sq fromSq=toSq-delta;
			Move move=moveMake(fromSq, toSq, piece);
			if (posCanMakeMove(pos, move))
				goto success;
		}
	}

	if (type & MoveTypeCapture) {
		// Pawns - west captures.
		delta=(stm==ColourWhite ? 7 : -9);
		set=(bbWestOne(forwardPawns) & opp);
		while(set) {
			Sq toSq=bbScanReset(&set);
			Sq fromSq=toSq-delta;
			Piece toPiece=((sqRank(toSq)==Rank1 || sqRank(toSq)==Rank8) ? pieceMake(PieceTypeQueen, stm) : piece);
			Move move=moveMake(fromSq, toSq, toPiece);
			if (posCanMakeMove(pos, move))
				goto success;
		}

		// Pawns - east captures.
		delta=(stm==ColourWhite ? 9 : -7);
		set=(bbEastOne(forwardPawns) & opp);
		while(set) {
			Sq toSq=bbScanReset(&set);
			Sq fromSq=toSq-delta;
			Piece toPiece=((sqRank(toSq)==Rank1 || sqRank(toSq)==Rank8) ? pieceMake(PieceTypeQueen, stm) : piece);
			Move move=moveMake(fromSq, toSq, toPiece);
			if (posCanMakeMove(pos, move))
				goto success;
		}

		// Pawns - en-passent captures.
		if (pos->data->epSq!=SqInvalid) {
			Sq toSq=pos->data->epSq, fromSq;

			// Left capture.
			if (sqFile(pos->data->epSq)!=FileH && posGetPieceOnSq(pos, fromSq=sqEastOne(sqBackwardOne(toSq, stm)))==piece) {
				Move move=moveMake(fromSq, toSq, piece);
				if (posCanMakeMove(pos, move))
					goto success;
			}

			// Right capture.
			if (sqFile(pos->data->epSq)!=FileA && posGetPieceOnSq(pos, fromSq=sqWestOne(sqBackwardOne(toSq, stm)))==piece) {
				Move move=moveMake(fromSq, toSq, piece);
				if (posCanMakeMove(pos, move))
					goto success;
			}
		}
	}

	// No moves available.
	assert(posGenLegalMove(pos, type)==MoveInvalid);
	return false;

	// At least one move available.
	success:
	assert(posGenLegalMove(pos, type)!=MoveInvalid);
	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);
}