Esempio n. 1
0
void hashCollectPV(Position* position, Move pv[]){
	HashData* hd;
	guint64 hData;
	guint index = 0;
	while(hashFind(&hd,position->key,&hData)){
		if(index < Max_Pv-1 && hashMove(hData) != Empty){
			pv[index] = hashMove(hData);
			moveDo(position,pv[index]);
			index++;
		}
		else break;
	}
	
	pv[index] = Empty;
	while(index>0){
		moveUndo(position);
		index--;
	}
}
Esempio n. 2
0
gint threadSearch(Position* position, gint alpha, gint beta, gint depth, gint hight, const gboolean nullMove, const gboolean nodePV){
	Moves moves;
	Move move, bestMove = Empty, hMove = Empty, pMove=Empty;
	gboolean extend=FALSE, endGamePhase;
	gint eval, tmpDepth, movesSearched = 0, pAlpha, pType;
	guint idleThreads;
	guint64 key = position->key, hData;
	HashData* hd;

	if(stopFlag == TRUE && !ponderSearch) return EVAL_DRAW;

	searchNodes++;

	/* Draw */
	if(positionRepeat(position) >= 1 || position->staticMoves >= 100) return EVAL_DRAW;

	/* End game */
	gint numberOfPieces = numberOfBits64(position->allPieces);
	if(numberOfPieces <= 5 && egbbIsLoaded()){
		tmpDepth = (2 * iterativeDepth) / 3;
		if((numberOfPieces <= 4 || hight <= tmpDepth) &&
			(hight >= tmpDepth || positionEvalEG(position))){
			if(egbbProbe(position, &eval)){
				if(eval < 0) return eval + hight * 40 + positionMaterial(position);
				if(eval > 0) return eval - hight * 40 + positionMaterial(position);
				return eval;
			}
		}
	}

	/* Mate distance pruning */
	eval = -EVAL_MATE + hight;
	if(eval > alpha){
		if(eval >= beta) return eval;
		alpha = eval;
	}

	eval = EVAL_MATE - hight;
	if(eval < beta){
		if(eval <= alpha) return eval;
		beta = eval;
	}

	/* Hash */
	if(hashFind(&hd,key,&hData)){
		hMove = hashMove(hData);
        if(!nodePV && (gint)hashDepth(hData) >= depth){
			if(hashFlag(hData) == EXACT) return hashEval(hData);
			else if(hashFlag(hData) == ALPHA && hashEval(hData) > alpha){
				bestMove = hashMove(hData);
				alpha = hashEval(hData);
                if(alpha >= beta) return alpha;
			}
			else if(hashFlag(hData) == BETA && hashEval(hData) < beta){
				beta = hashEval(hData);
				if(alpha >= beta) return beta;
			}
		}
	}

	/* Extension */	
	if(position->extend || (nodePV && passedPawnMove(position))){
		depth ++;
		extend = TRUE;
	}

	/* Horizon */
	if(depth < 1){
		eval = quiescent(position,alpha,beta,hight+1,TRUE);
		return eval;
	}

	if(position->phase <= 7 && numberOfPieces <= 10) endGamePhase = TRUE;
	else endGamePhase = FALSE;

	/* Null move pruning */
	if (!nodePV && nullMove && depth>2 && !extend && !endGamePhase){
		if(depth > 6) tmpDepth = depth - 4;
		else tmpDepth = depth - 3;
		moveDo(position,Null_Move);
		eval = -threadSearch(position,-beta,-beta+1,tmpDepth,hight+1,FALSE,FALSE);
		moveUndo(position);
		if(eval >= beta){
			hashWrite(hd,key,depth,eval,ALPHA,Empty);
			return eval;
		}
	}

	/* Internal Iterative Deepening */
	tmpDepth = depth/2;
	if(nodePV && hMove == Empty && depth > 3 && tmpDepth >= (gint)hashDepth(hData)){
		threadSearch(position,alpha, beta, tmpDepth, hight, FALSE,nodePV);
		if(hashFind2(hd,key,&hData)) hMove = hashMove(hData);
	}

	/* First move */
	moves.state = START;
	if(hMove != Empty){
		move = hMove;
		moveDo(position,move);
	}
	else move = nextMoveDo(position,&moves);
	
	if(move != Empty){
		eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE,nodePV);
		if(eval > alpha){
			if(eval >= beta){
				moveUndo(position);
				if(moves.state == STATIC) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth;
				hashWrite(hd,key,depth,eval,ALPHA,move);
				return eval;
			}
			alpha = eval;
			bestMove = move;
		}
		moveUndo(position);
		movesSearched ++;
	}

	/* Parallel search*/
	idleThreads = searchThreads;

	while(TRUE){
		if(idleThreads > 0){
			move = nextMoveDo(position,&moves);
			/* Last moves searched sequential */
			if(move == Empty){
				parallelStopFlag = TRUE;
				moves.size = moves.next = 0;
				while(idleThreads != searchThreads){
					parallelSearchResult(&pMove,&pAlpha,&pType);
					idleThreads++;
					moves.move[moves.size] = pMove;
					moves.size ++;
				}
				parallelStopFlag = FALSE;
				moves.toSort = moves.size;
				break;
			}
			/* History pruning */
			if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && 
				!extend && !position->extend){
				idleThreads--;
				parallelSearch(position, move, -(alpha+1), -alpha, depth-2, hight+1,TRUE,HP,FALSE);
				moveUndo(position);
				movesSearched ++;
			}
			else{ /* PVS */
				idleThreads--;
				parallelSearch(position, move, -(alpha+1), -alpha, depth-1, hight+1,TRUE,PVS,FALSE);
				moveUndo(position);
				movesSearched ++;
			}
		}
		else{
			eval = -parallelSearchResult(&pMove,&pAlpha,&pType);
			idleThreads++;
			pAlpha = -pAlpha - 1;
			if(pType == HP && eval > pAlpha){ /* HP */
				idleThreads--;
				moveDo(position,pMove);
				parallelSearch(position, pMove, -(pAlpha+1), -pAlpha, depth-1, hight+1,TRUE,PVS,FALSE);
				moveUndo(position);
				continue;
			}
			if(pType == PVS && eval > pAlpha && eval < beta){ /* PVS research */
				idleThreads--;
				moveDo(position,pMove);
				parallelSearch(position, pMove, -beta, -pAlpha, depth-1, hight+1,TRUE,RPVS,nodePV);
				moveUndo(position);
				continue;
			}
			if(eval > alpha){
				if(eval >= beta){
					parallelSearchStop(idleThreads);
					if(moveGetType(pMove) == Normal) history[moveGetFrom(pMove)][moveGetTo(pMove)] += 1<<depth;
					hashWrite(hd,key,depth,eval,ALPHA,pMove);
					return eval;
				}
				alpha = eval;
				bestMove = pMove;
			}
		}
	}

	/* Last moves searched sequential */
	move = nextMoveDo(position,&moves);
	while(move != Empty){
		/* History pruning */
		if(!nodePV && movesSearched >= HistoryFullDepthMoves && depth > HistoryReductionLimit && 
			!extend && !position->extend){
			eval = -threadSearch(position, -(alpha+1), -alpha, depth-2, hight+1, TRUE, FALSE);
		}
		else eval = alpha + 1;

		/* PVS */
		if(eval > alpha){
			eval = -threadSearch(position, -(alpha+1), -alpha, depth-1, hight+1, TRUE, FALSE);
			if(eval > alpha && eval < beta)
				eval = -threadSearch(position, -beta, -alpha, depth-1, hight+1, TRUE, nodePV);
		}
		moveUndo(position);
		if(eval > alpha){
			if(eval >= beta){
				if(moveGetType(pMove) == Normal) history[moveGetFrom(move)][moveGetTo(move)] += 1<<depth;
				hashWrite(hd,key,depth,eval,ALPHA,move);
				return eval;
			}
			alpha = eval;
			bestMove = move;
		}
		movesSearched ++;
		move = nextMoveDo(position,&moves);
	}

	/* Mate or pat */
	if(movesSearched == 0){
		if(position->inCheck == TRUE){
			eval = -EVAL_MATE+hight;
			hashWrite(hd,key,depth,eval,EXACT,Empty);
			return eval;
		}
		else{  
			hashWrite(hd,key,depth,EVAL_DRAW,EXACT,Empty);
			return EVAL_DRAW;
		}
	}

	/* hash is update */
	if(bestMove != Empty) hashWrite(hd,key,depth,alpha,EXACT,bestMove);
	else hashWrite(hd,key,depth,alpha,BETA,hMove);

	return alpha;
}
Esempio n. 3
0
gboolean moveDo(Position* position, const Move move){
	History* history = &position->history[position->ply];
	history->move = move;
	history->key = position->key;
	history->capture = position->capture;
	history->staticMoves = position->staticMoves;
	history->enPassant = position->enPassant;
	history->castle = position->castle;
	history->inCheck = position->inCheck;
	history->material[White] = position->material[White];
	history->material[Black] = position->material[Black];
	history->pvt[Opening] = position->pvt[Opening];
	history->pvt[Endgame] = position->pvt[Endgame];
	history->extend = position->extend;
	history->phase = position->phase;

	#ifndef G_DISABLE_ASSERT 
	if(move != Null_Move && position->type[moveGetFrom(move)]%2 != position->turn){
		positionPrint(position);
		g_printf("Wrong move (");
		movePrint(move);
		g_printf(")\n");
		g_error("!!\n");
	}
	#endif
	if(position->enPassant != 0){
		position->key ^= enPassantKey[file(position->enPassant)];
		position->enPassant = 0;
	}
	position->capture = Empty;
	position->extend = FALSE;
	position->staticMoves ++;

	switch(moveGetType(move)){
		case Normal: 	{ normalMoveDo(position, move); break;}
		case Capture:	{ captureMoveDo(position, move); break;}
		case En_Passant:{ enPassantMoveDo(position, move); break;}
		case Castle:	{
			if(!castleMoveDo(position,move)){
				position->enPassant = history->enPassant;
				position->capture = history->capture;
				position->extend = history->extend;
				position->staticMoves--;
				#ifndef G_DISABLE_ASSERT 
				positionIsOk(position);
				#endif
				return FALSE;
			}else{
				position->turn ^= 1; 
				position->key ^= turnKey;
				position->ply++;
				position->inCheck = positionIsInCheck(position); /* Speed up (rook only)*/
				if(position->inCheck) position->extend = TRUE;
				#ifndef G_DISABLE_ASSERT 
				positionIsOk(position);
				#endif
				return TRUE;
			}
		}
		case Promote_Queen:	{ promoteMoveDo(position,move,Queen); break;}
		case Promote_Rook: 	{ promoteMoveDo(position,move,Rook); break;}
		case Promote_Bishop:	{ promoteMoveDo(position,move,Bishop); break;}
		case Promote_Knight:	{ promoteMoveDo(position,move,Knight); break;}
		case Null_Move:	{
			position->turn ^= 1; 
			position->key ^= turnKey;
			position->ply++;
			position->staticMoves = 0;
			#ifndef G_DISABLE_ASSERT 
			positionIsOk(position);
			#endif
			return TRUE;
		}
		default: { g_error("Wrong move type!\n"); }
	};
	position->turn ^= 1; 
	position->key ^= turnKey;
	position->ply++;
	if(!positionGood(position)){
		moveUndo(position);
		return FALSE;
	}
	position->inCheck = positionIsInCheck(position); /* Speed up */
	if(position->inCheck) position->extend = TRUE;
	#ifndef G_DISABLE_ASSERT 
	positionIsOk(position);
	#endif
	return TRUE;
}