コード例 #1
0
ファイル: tt.c プロジェクト: DanielWhite94/robocide
void ttWrite(const Pos *pos, Depth ply, Depth depth, Move move, Score score, Bound bound) {
	// Sanity checks.
	assert(depthIsValid(ply));
	assert(depthIsValid(depth));
	assert(moveIsValid(move) || move==MoveNone);
	assert(scoreIsValid(score));
	assert(bound!=BoundNone);

	uint64_t key=posGetKey(pos);

	// Grab cluster.
	HTableKey hTableKey=ttHTableKeyFromPos(pos);
	TTCluster *cluster=htableGrab(tt, hTableKey);

	// Find entry to overwrite.
	TTEntry *entry, *replace=cluster->entries;
	unsigned int i, replaceScore=0; // Worst possible score.
	for(i=0,entry=cluster->entries;i<ttClusterSize;++i,++entry) {
		// If we find an exact match, simply reuse this entry.
		// We can also be certain that if this entry is unused, we will not find an
		// exact match in a later entry (otherwise said later entry would have
		// instead been written to this unused entry).
		if (ttEntryMatch(pos, entry) || ttEntryUnused(entry)) {
			// Set key (in case entry was previously unused).
			entry->keyUpper=(key>>48);

			// Update entry date (to reset age to 0).
			entry->date=searchGetDate();

			// Update move if we have one and it is from a deeper search (or no move already stored).
			if (!moveIsValid(entry->move) || (moveIsValid(move) && depth>=entry->depth))
				entry->move=move;

			// Update score, depth and bound if search was at least as deep as the entry depth.
			if (depth>=entry->depth) {
				entry->score=ttScoreIn(score, ply);
				entry->depth=depth;
				entry->bound=bound;
			}

			htableRelease(tt, hTableKey);
			return;
		}

		// Otherwise check if entry is better to use than replace.
		unsigned int entryScore=ttEntryFitness(searchDateToAge(entry->date), entry->depth, entry->bound==BoundExact);
		if (entryScore>replaceScore) {
			replace=entry;
			replaceScore=entryScore;
		}
	}
コード例 #2
0
ファイル: pos.c プロジェクト: 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));
}
コード例 #3
0
ファイル: pos.c プロジェクト: 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;
}
コード例 #4
0
ファイル: pos.c プロジェクト: 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;
}
コード例 #5
0
ファイル: moves.c プロジェクト: raimarHD/lcec
void movesRewind(Moves *moves, Move ttMove) {
	moves->stage=MovesStageTT;
	moves->next=moves->list;
	moves->ttMove=((moveIsValid(ttMove) && (posMoveGetType(moves->pos, ttMove)&moves->allowed)) ? ttMove : MoveInvalid);
}
コード例 #6
0
ファイル: move.c プロジェクト: DanielWhite94/robocide
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);
}
コード例 #7
0
ファイル: move.c プロジェクト: DanielWhite94/robocide
Colour moveGetColour(Move move) {
	assert(moveIsValid(move));
	return pieceGetColour(moveGetToPiece(move));
}
コード例 #8
0
ファイル: move.c プロジェクト: DanielWhite94/robocide
PieceType moveGetToPieceType(Move move) {
	assert(moveIsValid(move));
	return pieceGetType(moveGetToPiece(move));
}
コード例 #9
0
ファイル: move.c プロジェクト: DanielWhite94/robocide
Piece moveGetToPiece(Move move) {
	assert(moveIsValid(move));
	return move>>MoveShiftToPiece;
}