Example #1
0
int quiescent(app_t *app, cnodeptr_t parent, int alpha, int beta)
{
	int i, score = -MATE;
	node_t node;
	int delta = 200;

	init_node(&node);

	assert(app);

	app->search.nodes++;

	/* max depth */
	if (app->game.board->ply > (SEARCH_MAXDEPTH - 1)) {
		return evaluate(app->game.board);
	}

	/* draws */
	if (repetitions(app) || (app->game.board->half >= 100)) {
		return 0;
	}

	score = evaluate(app->game.board);

	if (score >= beta) return beta;
	/* delta pruning based on a material value of delta (this should be disabled
	   in the endgame) */
	/* The idea here is that, even if our score can improve alpha, it doesn't
	   improve it by a significant amount, so don't bother searching these nodes */
	if (score < (alpha - delta)) return alpha;
	if (score > alpha) alpha = score;


	/* generate moves (with separate captures) */
	generate_moves(app->game.board, &node.ml, &node.cl);

	for (i = 0; i < node.cl.count; i++) {
		/* get the next move ordered */
		next_move(i, &node.cl);

		if (!(do_move(app->game.board, &app->game.undo, node.cl.moves[i])))
			continue;

		score = -quiescent(app, &node, -beta, -alpha);

		node.made++;
		undo_move(app->game.board, &app->game.undo);

		if (score > alpha) {
			if (score >= beta) {
				return beta;
			}

			/* update alpha */
			alpha = score;
		}
	}

	return alpha;
}
Example #2
0
/**
 * Use mpmcqs to allow stealing directly from a victim, without waiting for a
 * response.
 */
static pony_actor_t* steal(scheduler_t* sched, pony_actor_t* prev)
{
  send_msg(0, SCHED_BLOCK, 0);
  uint64_t tsc = ponyint_cpu_tick();
  pony_actor_t* actor;

  while(true)
  {
    scheduler_t* victim = choose_victim(sched);

    if(victim == NULL)
      actor = (pony_actor_t*)ponyint_mpmcq_pop(&inject);
    else
      actor = pop_global(victim);

    if(actor != NULL)
    {
      DTRACE3(WORK_STEAL_SUCCESSFUL, (uintptr_t)sched, (uintptr_t)victim, (uintptr_t)actor);
      break;
    }

    uint64_t tsc2 = ponyint_cpu_tick();

    if(quiescent(sched, tsc, tsc2))
    {
      DTRACE2(WORK_STEAL_FAILURE, (uintptr_t)sched, (uintptr_t)victim);
      return NULL;
    }

    // If we have been passed an actor (implicitly, the cycle detector), and
    // enough time has elapsed without stealing or quiescing, return the actor
    // we were passed (allowing the cycle detector to run).
    if((prev != NULL) && ((tsc2 - tsc) > 10000000000))
    {
      actor = prev;
      break;
    }
  }

  send_msg(0, SCHED_UNBLOCK, 0);
  return actor;
}
Example #3
0
/**
 * Use mpmcqs to allow stealing directly from a victim, without waiting for a
 * response.
 */
static pony_actor_t* steal(scheduler_t* sched, pony_actor_t* prev)
{
  send_msg(0, SCHED_BLOCK, 0);
  uint64_t tsc = ponyint_cpu_tick();
  pony_actor_t* actor;

  while(true)
  {
    scheduler_t* victim = choose_victim(sched);

    if(victim == NULL)
      victim = sched;

    actor = pop_global(victim);

    if(actor != NULL)
      break;

    uint64_t tsc2 = ponyint_cpu_tick();

    if(quiescent(sched, tsc, tsc2))
      return NULL;

    // If we have been passed an actor (implicitly, the cycle detector), and
    // enough time has elapsed without stealing or quiescing, return the actor
    // we were passed (allowing the cycle detector to run).
    if((prev != NULL) && ((tsc2 - tsc) > 10000000000))
    {
      actor = prev;
      break;
    }
  }

  send_msg(0, SCHED_UNBLOCK, 0);
  return actor;
}
Example #4
0
int alpha_beta(app_t *app, cnodeptr_t parent, int alpha, int beta, int depth)
{
	int palpha = alpha;
	int i, score = -MATE, highest = -MATE;
	node_t node;
	move_t cutoff = 0;
	piece_t p;

	init_node(&node);

	assert(app);

	app->search.nodes++;
	node.depth = depth;

	/* max depth */
	if (app->game.board->ply > (SEARCH_MAXDEPTH - 1)) {
		/* return evaluate(app->board); */
		return quiescent(app, parent, alpha, beta);
	}

	/* recursive base */
	if (depth == 0) {
		return evaluate(app->game.board);
	}

	/* draws */
	if (repetitions(app) || (app->game.board->half >= 100)) {
		return 0;
	}

	/* if we are checked, set the nodes checked flag */
	if (check(app->game.board, app->game.board->side)) {
		node.flags |= NODE_CHECK;
		/* extend our search by 1 depth if we are in check */
		/* NOTES: we may want to NOT extend our search here if the parent
		   is in check, because the means we already extended once */
		depth++;
	}

	/* TODO:
	     - NULL moves
	     - Late-move reduction
	     - Tactical extensions (pins & forks -> depth++)
	 */

	/* probe our table */
	if (probe_hash(&app->hash, app->game.board, &cutoff, &score, depth, alpha, beta) == TRUE) {
		app->hash.cut++;
		return score;
	}

	/* generate moves */
	generate_moves(app->game.board, &node.ml, &node.ml);

	/* reset score */
	score = -MATE;

	/* try to match our hash hit move */
	if (cutoff != 0) {
		for (i = 0; i < node.ml.count; i++) {
			if (node.ml.moves[i] == cutoff) {
				node.ml.scores[i] = 20000;
				break;
			}
		}
	}

	/* search negamax */
	for (i = 0; i < node.ml.count; i++) {
		/* get the next move ordered */
		next_move(i, &node.ml);

		if (!(do_move(app->game.board, &app->game.undo, node.ml.moves[i])))
			continue;

		score = -alpha_beta(app, &node, -beta, -alpha, depth - 1);

		node.made++;
		undo_move(app->game.board, &app->game.undo);

		/* score whatever is best so far */
		if (score > highest) {
			node.best = node.ml.moves[i];
			highest = score;

			/* update alpha */
			if (score > alpha) {
				if (score >= beta) {

					/* non-captures causing beta cutoffs (killers) */
					if (!is_capture(node.ml.moves[i])) {
						app->game.board->killers[1][app->game.board->ply] =
							app->game.board->killers[0][app->game.board->ply];
						app->game.board->killers[0][app->game.board->ply] = node.ml.moves[i];
					}

					/* store this beta in our transposition table */
					store_hash(&app->hash, app->game.board, node.best, beta, HASH_BETA, depth);

					return beta;
				}

				/* update alpha */
				alpha = score;

				/* update our history */
				if (!is_capture(node.best)) {
					p = app->game.board->pos.squares[move_from(node.best)];
					app->game.board->history[piece_color(p)][piece_type(p)][move_to(node.best)] += depth;
				}
			}
		}
	}

	/* check for checkmate or stalemate */
	if (!node.made) {
		if (node.flags & NODE_CHECK) {
			return -MATE + app->game.board->ply;
		} else {
			return 0;
		}
	}

	if (alpha != palpha) {
		/* store this as an exact, since we beat alpha */
		store_hash(&app->hash, app->game.board, node.best, highest, HASH_EXACT, depth);
	} else {
		/* store the current alpha */
		store_hash(&app->hash, app->game.board, node.best, alpha, HASH_ALPHA, depth);
	}

	return alpha;
}
Example #5
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;
}