Example #1
0
	int AlphaBeta  (const uint64_t P, const uint64_t O, uint64_t& NodeCounter, int alpha, int beta)
	{
		const uint64_t empties = Empties(P, O);
		if (empties == 4)
			return AlphaBeta_4(P, O, NodeCounter, alpha, beta);

		uint64_t flipped;
		uint64_t BitBoardPossible = PossibleMoves(P, O);
		unsigned long Move;
		int score = -64;
		NodeCounter++;

		if (!BitBoardPossible){
			if (HasMoves(O, P))
				return -AlphaBeta(O, P, NodeCounter, -beta, -alpha);
			else //Game is over
				return BIND(EvalGameOver(P, empties), alpha, beta);
		}

		while (BitBoardPossible)
		{
			Move = BitScanLSB(BitBoardPossible);
			RemoveLSB(BitBoardPossible);
			flipped = flip(P, O, Move);
			score = -AlphaBeta(O ^ flipped, P ^ (1ULL << Move) ^ flipped, NodeCounter, -beta, -alpha);
			if (score >= beta) return beta;
			if (score > alpha) alpha = score;
		}

		return alpha;
	}
Example #2
0
void MakeMove(void)
{
    int X,Y, bestX, bestY, d, nosol;

    if (timelimit1 == 0){
        if (debug) fprintf(stderr, "alphabeta depthlimit = %d\n", depthlimit);
        (void) AlphaBeta(gamestate, depthlimit, -10000000, 10000000, me, &X,
                &Y);
        if (debug) fprintf(stderr, "returned X = %d  Y = %d\n", X, Y);
    }
    else {
        currenttime = clock();						//get current time
        deadline = currenttime + timelimit1 * (CLOCKS_PER_SEC / 1000);
        //calculate by when we need to make a move
        d = 1;

        if (debug)
            fprintf(stderr, "timelimit1 = %d  currenttime = %lu deadline = %lu\n", timelimit1, currenttime, deadline);

        nosol = TRUE;
        while (currenttime < deadline){
            d = d + 1;
            if (debug) fprintf(stderr, "interation depth = %d\n", d);
            (void) AlphaBeta(gamestate, d, -10000000, 10000000, me, &bestX,
                    &bestY);
            if (currenttime < deadline)
            {
                //storing the best possible move in the time given
                X = bestX;
                Y = bestY;
                nosol = FALSE;
                if (debug) fprintf(stderr, "saving move (%d , %d)\n", X, Y);
            }
        }
        if (nosol) error("timelimit too small to find a move\n");
        if (debug) fprintf(stderr, "end of iteration at currentime = %lu\n",
                currenttime);
    }

    if (X>=0) {
        Update(gamestate, me, X, Y);
        printf("%d %d\n", X, Y);
        fflush(stdout);
    } else {
        printf("pass\n");
        fflush(stdout);
    }
    if (debug) printboard(gamestate, me, ++turn, X, Y);
}
Example #3
0
void ComputerThink(void)
{
    short best;
    nodecount = 0;
    best = AlphaBeta(-INFINITY, INFINITY, MAX_PLY);
    //printf("%ld\n",nodecount);
}
/* Search game tree by alpha-beta algorith */
short AlphaBeta(short alpha, short beta, short depth)
{
    short i, value, best;

    if (!depth) return Eval();

    Gen();
    best = -INFINITY;

    for (i=gen_begin[ply]; i<gen_end[ply] && best<beta; i++)
    {
        if (best > alpha) alpha = best;

        if (MakeMove(gen_dat[i].m)) value = 1000-ply;
        else value = -AlphaBeta(-beta, -alpha, depth-1);
        UnMakeMove();

        if (value > best)
        {
            best = value; if (!ply) newmove = gen_dat[i].m;
        }
    }

    return best;
}
Example #5
0
int AlphaBeta(board state, int depth, int alpha, int beta, int player, int *
        bestX, int * bestY)	//AlphaBeta
{
    int X,Y, numacts, i, value;
    int Xacts[64], Yacts[64];	//maximum of 64 (actually 60) possible moves
    board child;

    if (timelimit1){
        currenttime = clock();
        if (deadline < currenttime) return 0;
    }

    if (CutoffTest(state, depth)) return Evaluate(state);
    numacts = Actions(state, player, Xacts, Yacts);

    if (player == 1){//the MAX player (us)
        for (i=0; i<numacts; i++) {
            Result(state, child, player, Xacts[i], Yacts[i]);
            value = AlphaBeta(child, depth-1, alpha, beta, -player, &X, &Y);
            if (timelimit1 && deadline < currenttime) return 0;
            //checking if we've reached the timelimit if applicable
            if (value > alpha) {
                alpha = value;
                *bestX = Xacts[i]; *bestY = Yacts[i];
            }
            if (beta <= alpha)//beta cut-off
                break;
        }
        return alpha;
    } else {
        for (i=0; i<numacts; i++) {
            Result(state, child, player, Xacts[i], Yacts[i]);
            value = AlphaBeta(child, depth-1, alpha, beta, -player, &X, &Y);
            if (timelimit1 && deadline < currenttime) return 0;
            //checking if we've reached the time limit if applicable
            if (value < beta) {
                beta = value;
                *bestX = Xacts[i]; *bestY = Yacts[i];
            }
            if (beta <= alpha)//alpha cutoff
                break;
        }
        return beta;
    }
}
Example #6
0
int CAlphabeta_HHEngine::AlphaBeta(int nDepth, int alpha,int beta)
{
	int score;
	int Count,i;
	BYTE type;

	i=IsGameOver(CurPosition, nDepth);
	if(i!=0)
		return i;

	if(nDepth<=0)//叶子节点取估值
		return m_pEval->Eveluate(CurPosition,(m_nMaxDepth-nDepth)%2,m_nUserChessColor);
	
	Count=m_pMG->CreatePossibleMove(CurPosition,nDepth,(m_nMaxDepth-nDepth)%2,m_nUserChessColor);
	if(nDepth==m_nMaxDepth)
	{
		//在根节点设定进度条
		m_pThinkProgress->SetRange(0,Count);
		m_pThinkProgress->SetStep(1);
	}

	//取所有走法的历史得分
	for(i=0;i<Count;i++) 

		m_pMG->m_MoveList[nDepth][i].Score=GetHistoryScore(&m_pMG->m_MoveList[nDepth][i]);

	MergeSort(m_pMG->m_MoveList[nDepth],Count,0);//对Count种走法按历史得分大小排序

	int bestmove=-1;//记录最佳走法的变量

	for(i=0;i<Count;i++) 
	{
		if(nDepth==m_nMaxDepth)
			m_pThinkProgress->StepIt();//走进度条

		type=MakeMove(&m_pMG->m_MoveList[nDepth][i]);
		score=-AlphaBeta(nDepth-1,-beta,-alpha);
		UnMakeMove(&m_pMG->m_MoveList[nDepth][i],type); 

		if(score>alpha)
		{
			alpha=score;
			if(nDepth==m_nMaxDepth)
				m_cmBestMove=m_pMG->m_MoveList[nDepth][i];
			bestmove=i;
		}
        if(alpha>=beta) 
		{
			bestmove=i;
			break;
		}			
	}
	if(bestmove!=-1)
		EnterHistoryScore(&m_pMG->m_MoveList[nDepth][bestmove],nDepth);//将最佳走法汇入历史记录表

	return alpha;
}
void CChineseChessView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ
	if (isMouseDown){
		isMouseDown=false;		
		CRect rect;
		GetClientRect(&rect);

		CPoint logpoint=PhysicalToLogicPoint(point);
		if (logpoint.x>=0){	
			//human move
			Gen();
			newmove.from = LogicPointToNum(selectedPoint); 
			newmove.dest = LogicPointToNum(logpoint);
			for (int i=gen_begin[ply]; i<gen_end[ply]; i++){
				if (gen_dat[i].m.from==newmove.from && gen_dat[i].m.dest==newmove.dest){
					if(UpdateNewMove()){
						UpdateDisplay(rect);
						int ret;
						ret=MessageBox("you are really a lucky dog,dare to try again?","Game Over",MB_YESNO);
						if (ret==IDYES){
							NewGame(true);
							return;
						}else{
							exit(0);
						}
					}
					side = xside; xside = 1-xside;
					//computer move
					short best;			
					best = AlphaBeta(-INFINITY, INFINITY, MAX_PLY);
					if(UpdateNewMove()){
						UpdateDisplay(rect);
						int ret;
						ret=MessageBox("afraid?dare to try again?","Game Over",MB_YESNO);
						if (ret==IDYES){
							NewGame(true);
							return;
						}else{
							exit(0);
						}
					}
					side = xside; xside = 1-xside;
					break;
				}
			}
			
		}

		UpdateDisplay(rect);
		
	}
	CView::OnLButtonUp(nFlags, point);
}
Example #8
0
/*
 @brief 对当前棋局,计算team在board上放置棋子的最好位置。
 @param board 棋局
 @param team 要放子的一方
 @param depth 搜索最大深度
 @return team的最佳放子位置
 */
GBIntPoint getAIPos(int **board, PieceTeam team, int depth)
{
    InDepth = depth;
    AITeam = team;
    
    AlphaBeta(board, depth, -INFINIT, INFINIT, team);
    
    delete2DIntArray(board);
    printf("AI piece: %d, %d", BestPiece.r, BestPiece.c);
    return BestPiece;
}
Example #9
0
void CAlphabeta_HHEngine::SearchAGoodMove(BYTE position[10][9])
{
	memcpy(CurPosition, position, 90);

	m_nMaxDepth = m_nSearchDepth;
	ResetHistoryTable();//初始化历史记录表
	AlphaBeta(m_nMaxDepth, -20000, 20000);
	m_umUndoMove.cmChessMove = m_cmBestMove;
	m_umUndoMove.nChessID = MakeMove(&m_cmBestMove);

	memcpy(position, CurPosition, 90);
}
Example #10
0
 GameMove* AlphaBetaParallel::getNextMove(const GameBoard* board, uint32_t max_depth)
 {
     float score;
     GameMove* move;
     AlphaBeta(board, 0, max_depth,
             -1 * std::numeric_limits<float>::infinity(),
             std::numeric_limits<float>::infinity(), score, move);
     fprintf(stderr, "Turn: %s\n", board->getTurn()==WHITE? "WHITE" : "BLACK");
     move->printMove();
     fprintf(stderr, "Score: %f\n", score);
     return move;
 }
Example #11
0
void CAlphaBeta_TTEngine::SearchAGoodMove(BYTE position[][9])
{
    memcpy(CurPosition,position,90);

    CalculateInitHashKey(CurPosition);//计算初始棋盘的哈希值
    m_nMaxDepth=m_nSearchDepth;
    AlphaBeta(m_nMaxDepth,-20000,20000);
    m_umUndoMove.cmChessMove=m_cmBestMove;
    m_umUndoMove.nChessID=MakeMove(&m_cmBestMove);  

    memcpy(position,CurPosition,90);
}
Example #12
0
int AIInterface::AlphaBeta(Duel* pos, int depth, int player)
{
	if (depth == 0)
	{
		int r = Evaluate(pos, pos->turn);
		//cout << "eval : " << r << endl;
		return r;
	}
	//cout << "depth : " << depth << endl;
	vector<Message> m = getValidMoves(duel);
	int max = -10000;

	bool autotap = duel->castingcard == -1 ? false : true;

	int pmana = duel->manazones[duel->turn].getUntappedMana();
	int puntap = duel->isThereUntappedManaOfCiv(duel->turn, CIV_FIRE);

	for (vector<Message>::iterator i = m.begin(); i != m.end(); i++)
	{
		duel->handleInterfaceInput(*i);
		duel->dispatchAllMessages();
		int x = -AlphaBeta(duel, depth-1, duel->turn);
		duel->undoLastMove();
		vector<Message> m2 = getValidMoves(duel);
		if (m2.size() != m.size())
		{
			cout << "AI: ERROR: moves size mismatch, move: " << (*i).getType() << endl;
			for (int k = 0; k < m.size(); k++)
			{
				cout << m.at(k).getType() << endl;
			}
			for (int k = 0; k < m2.size(); k++)
			{
				cout << m2.at(k).getType() << endl;
			}
			cout << "mana: " << duel->manazones[duel->turn].getUntappedMana() << " " << pmana << " untap: " << duel->isThereUntappedManaOfCiv(duel->turn, CIV_FIRE) << " " << puntap << endl;
			cout << " ";
		}
		//cout << "AI: value " << x << " for move: " << (*i).getType() << endl;
		/*if (duel->hands[0].cards.size() != duel->hands[0].cards.size())
		{
		cout << "AI: undo failed " << i->getType() << duel->hands[0].cards.size() << " " << duel->hands[0].cards.size() << endl;
		}*/
		if (x > max)
		{
			max = x;
		}
		if (autotap) //auto-tap
			break;
	}
	return max;
}
Example #13
0
void G_H::execute(void) {
	Vm = input(0) - 0.01275; //membrane voltage corrected for junction potential;
	
	alpha_1 = AlphaBeta(-2.89e-3, -0.445, 24.02, Vm);
	beta_1 = AlphaBeta(2.71e-2, -1.024, -17.4, Vm);
	
	alpha_2 = AlphaBeta(-3.18e-3, -0.695, 26.72, Vm);
	beta_2 = AlphaBeta(2.16e-2, -1.065, -14.25, Vm);
	
	tau_h_fast = 1.0 / (alpha_1 + beta_1);
	tau_h_slow = 1.0 / (alpha_2 + beta_2);
	h_fast_inf = alpha_1 / (alpha_1 + beta_1);
	h_slow_inf = alpha_2 / (alpha_2 + beta_2);
	
	h_fast = h_fast_inf + (h_fast - h_fast_inf) * exp(-DeltaTSec / tau_h_fast);
	h_slow = h_slow_inf + (h_slow - h_slow_inf) * exp(-DeltaTSec / tau_h_slow);
	
	Im = -Gh_max * (0.65 * h_fast + 0.35 * h_slow) * (Vm - Vh_rev);
	
	Ih = Im;
	output(0) = Ih;
}
Example #14
0
//目前没有用到type,只能用来找黑子
void AlphaBetaEngine::SearchAGoodMove(BYTE position [ ] [ GRID_NUM ],int /*type*/, int & x,int & y)
{
#ifdef _DEBUG_NUM
	branchNum = cutoffNum = 0;
#endif
	memcpy(CurPosition, position, GRID_COUNT);
	AlphaBeta(m_nSearchDepth, -20000, 20000);
#ifdef _DEBUG_NUM
	printf("branchNum %d cutoffNum %d\n", branchNum, cutoffNum);
#endif
	x = m_cmBestMove.StonePos.x;
	y = m_cmBestMove.StonePos.y;
}
Example #15
0
// performs an alpha beta search with iterative deepening and returns the best move found
int IterSearch(board_t *brd, searchinfo_t *sinfo, int post)
{
	int bestScore = -INFINITE;
	int bestMove = NO_MOVE;
	int moveNum = 0;

	int iterDepth;
	int i;
	int tdif = 0;
	ClrForSearch(brd, sinfo);

	for(iterDepth = 1; iterDepth <= sinfo->toDepth; iterDepth++) // increase depth for each iteration
	{
		if(!sinfo->infinite) tdif = -GetTime();
		bestScore = AlphaBeta(brd, -INFINITE, INFINITE, iterDepth, sinfo, true);
		if(!sinfo->infinite) tdif += GetTime();

		// if we received a stop signal, simply break out and use the best move found so far
		if(sinfo->stop) break;

		// Fill 'pvLine' with the sequence of best moves found
		moveNum = GetPvLine(brd, iterDepth);

		// print some search progress depending on the 'post' format
		if(post == 1){
			printf("%d %d %d %" PRIu64,
				iterDepth, bestScore, (GetTime()-sinfo->startTime)/10, sinfo->nodes
			);
			for(i = 0; i < moveNum; i++){
				printf(" %s", StrXmove(brd->pvLine[i]));
			}
			printf("\n");
		}
		else if (post == 2) {
			printf("score:%7d nodes:%9" PRIu64 " eff: %3d%%   ", bestScore,
					sinfo->nodes, (int)(100*sinfo->fhf/sinfo->fh));
			for(i = 0; i < moveNum; i++){
				printf("%s ", StrMove(brd->pvLine[i]));
			}
			printf("\n");
		}
		bestMove = brd->pvLine[0];

		if(!sinfo->infinite && sinfo->startTime + TIME_MULTIPLIER*tdif > sinfo->stopTime) break;
	}
	return bestMove;
}
int Minimax::AlphaBeta(Board *board, GameInfo *gameInfo, Move &move, int depth, const int quiescenceDepth, int alpha, int beta) {
	// If we are at the end of the normal alpha beta search, perform a quiescence search with the given quiescence depth.
	if (depth == 0) return Quiescence(board, gameInfo, quiescenceDepth, alpha, beta);
	MoveList moveList;
	// Generate move list and check game state.
	GameInfo::State state = gameInfo->updateState(board, moveList);
	switch (state) {
		case GameInfo::STALEMATE:
		case GameInfo::FIFTY_MOVE_RULE:
		// Returns a score which will always be disregarded.
		return LARGEST_NUM + 1;
		case GameInfo::CHECKMATE:
		// Return arbitrarily large negative score (But not -LARGEST_NUM, as it would be cut off).
		return -LARGE_NUM;
	}
	MoveList::iterator bestMoveItr = moveList.begin();
	for (MoveList::iterator moveItr = moveList.begin(); moveItr != moveList.end(); moveItr++) {
		Move childMove = *moveItr;
		board->executeMove(childMove);
		// Save any irreversible game info before making a move.
		GameInfo::Irreversible irreversible(gameInfo);
		gameInfo->executeMove(childMove);
		// Here, the child's evaluation is taken to be the negation of its return value, so that seperate if statements for maximising and minimising
		//aren't required.
		int childEval = -AlphaBeta(board, gameInfo, move, depth - 1, quiescenceDepth, -beta, -alpha);
		board->reverseMove(childMove);
		gameInfo->reverseMove(irreversible);
		// If the child evaluates to a score greater than or equal to beta, there is a beta cutoff. This means that there is no further point exploring this
		// node's moves, as it is known that this node will at least be as bad if not worse than another node elsewhere in the game tree.
		if (childEval >= beta) {
			// If a non-capture move caused a beta-cutoff, increase its history weighting. The depth squared is added to the heuristic so that moves near
			//the leaf nodes don't dominate the heuristic (Leaf node score would be 0 * 0).
			if (!move.isCapture()) Move::HistoryHeuristic[move.subject_from][move.subject_to] += depth * depth;
			move = *bestMoveItr;
			return beta;
		}
		// If the child's evaluation is greater than alpha, this is the best move at the moment.
		if (childEval > alpha) {
			alpha = childEval;
			bestMoveItr = moveItr;
		}
	}
	move = *bestMoveItr;
	return alpha;
}
Example #17
0
Message AIInterface::makeMove()
{
	vector<Message> m = getValidMoves(duel);
	if (m.size() == 0)
	{
		return Message("AI: NO VALID MOVES ERROR");
	}
	if (m.size() == 1) //only 1 valid move
	{
		cout << "AI: only 1 legal move" << endl;
		return m.at(0);
	}
	if (duel->castingcard != -1) //auto-tap
	{
		return m.at(0);
	}
	int max = -10000;
	Message maxmove("AI: DEFAULT MOVE ERROR");
	duel->isSimulation = 1;
	for (vector<Message>::iterator i = m.begin(); i != m.end(); i++)
	{
		duel->handleInterfaceInput(*i);
		duel->dispatchAllMessages();
		int x = -AlphaBeta(duel, 4, duel->turn);
		duel->undoLastMove();
		vector<Message> m2 = getValidMoves(duel);
		if (m2.size() != m.size())
		{
			cout << "AI: ERROR: moves size mismatch" << endl;
		}
		cout << "AI: value " << x << " for move: " << (*i).getType() << endl;
		/*if (duel->hands[0].cards.size() != duel->hands[0].cards.size())
		{
			cout << "AI: undo failed " << i->getType() << duel->hands[0].cards.size() << " " << duel->hands[0].cards.size() << endl;
		}*/
		if (x > max)
		{
			maxmove = *i;
			max = x;
		}
	}
	cout << "AI: maxmove value: " << max << endl;
	duel->isSimulation = 0;
	return maxmove;
}
Example #18
0
int AlphaBetaEngine::AlphaBeta(int depth, int alpha, int beta)
{
	int side = (m_nSearchDepth - depth)%2;
	int childNodeCount, score;
	
	if(depth <= 0)
	{
		return m_pEval->Evaluate(CurPosition, side);
	}
	childNodeCount = m_pMG->CreatePossibleMove(CurPosition, depth , side);
#ifdef _DEBUG_NUM
	branchNum += childNodeCount;
#endif
	for (int i=0; i<childNodeCount; i++) 
	{
		m_pMG->m_MoveList[depth][i].Score = 
			7 -abs(m_pMG->m_MoveList[depth][i].StonePos.x-m_pMG->m_MoveList[depth][i].StonePos.y);
	}
	MergeSort(m_pMG->m_MoveList[depth], childNodeCount);
	for(int i=0; i<childNodeCount; ++i)
	{
		MakeMove(&m_pMG->m_MoveList[depth][i], side);
		score = -AlphaBeta(depth  -1, -beta, -alpha);
		UnMakeMove(&m_pMG->m_MoveList[depth][i]);
		if(score >alpha)
		{
		
			alpha = score;
			if(depth == m_nSearchDepth)
			{
				m_cmBestMove = m_pMG->m_MoveList[depth][i];
			}
			if(alpha > beta)
			{
#ifdef _DEBUG_NUM
				cutoffNum += (childNodeCount -i);
#endif
				break;//cutoff
			}
		}
	}
	return alpha;
}
/* Call AlphaBeta short && display some information */
void ComputerThink(void)
{
    short best;
    tickstart = clock(); nodecount = 0;
    best = AlphaBeta(-INFINITY, INFINITY, MAX_PLY);
    /* Display some information */
    tickend = clock(); textcolor(7);
    gotoxy(50, 4); printf("Depth : %d", MAX_PLY);
    gotoxy(50, 5); printf("Node total : %ld ", nodecount);
    gotoxy(50, 6); printf("Brand factor : %.2f ", (float)brandtotal/gencount);
    gotoxy(50, 7); printf("Time (second) : %.2f ", (tickend-tickstart)/1000.0);
    gotoxy(50, 8); printf("Nodes per second : %ld ", (long)(nodecount*1000.0/(tickend-tickstart+1)));
    gotoxy(50, 9); printf("Score : %d ", best);
    gotoxy(50,11); printf("Computer move : %c%d%c%d ",
            (char)(newmove.from%SIZE_X+65),
            (short)(SIZE_X-newmove.from/SIZE_X),
            (char)(newmove.dest%SIZE_X+65),
            (short)(SIZE_X-newmove.dest/SIZE_X));
}
Example #20
0
GameResult RunAIGame::play(Depth depth, BoardWidth size, RulesType rules, bool contenderFirst)
{
	for (int i=0; i<=1; i++)
	{
		PenteGame *p = _players[i];
		p->restartGame();
		p->setColour(i+1);
		p->setNormalDepth(depth);
		p->setBoardSize(size);
		p->setRules(rules);
	}

	int toMove = P1;

	AlphaBeta ab_games[2] = {
		AlphaBeta(*_players[0]),
		AlphaBeta(*_players[1])
	};

	GameResult res = GameResult();
	res._depth = std::to_string((int)depth);
	res._size = std::to_string((int)size);
	res._rules = rules;
	res._contenderP = (contenderFirst ? "P1" : "P2");

	Colour winner = EMPTY;

	while (winner == EMPTY)
	{
		Timer tmr;
		Loc bestMove = ab_games[toMove-1].getBestMove();
		if (!_silent) {
			std::cout << bestMove << std::endl;
		}
		res._times[toMove-1] += tmr.elapsed();
		assert(_players[0]->isLegalMove(bestMove));

		_players[0]->makeMove(bestMove, toMove);
		_players[1]->makeMove(bestMove, toMove);

		toMove = otherPlayer(toMove);
		winner = _players[1]->getWonBy();
		if (!_silent) {
			// TODO: Use another flag for games
			_players[0]->print();

#if 0
			const PriorityLevel &p1Threes
				= _players[0]->_posStats.getPriorityLevel(P1, Line3);
			const PriorityLevel &p2Threes
				= _players[0]->_posStats.getPriorityLevel(P2, Line3);
			const PriorityLevel &p1Fours
				= _players[0]->_posStats.getPriorityLevel(P1, Line4);
			const PriorityLevel &p2Fours
				= _players[0]->_posStats.getPriorityLevel(P2, Line4);

			cout << "P1 3s: " << p1Threes.getNumCands()
				 << "; P2 3s: " << p2Threes.getNumCands()
				 << "; P1 4s: " << p1Fours.getNumCands()
				 << "; P2 4s: " << p2Fours.getNumCands() << endl;
#endif
		}
	}
	res._winnerWasContender = ((winner==P2) xor contenderFirst);

	return res;
}
Example #21
0
Node Janggi::AlphaBeta(Node node, int depth, int alpha, int beta, Turn turn) {
    if (depth==0 || //terminal node
#if WIN32
      abs(node.GetValue()) >= (INT_MAX / 2) // win or lose
      ) {
#else
        fabs(node.GetValue()) >= (INT_MAX/2) // win or lose
        ) {
#endif
        node.SetLeafValue(node.GetValue());
        return node; //only one child. herself.
    }
    
    vector<Node> children = node.GetChildren(turn);
    
    int best_value;
    Node best_node;
    if (turn == TURN_CHO) { //maximizing player
        best_value = INT_MIN;
        best_node.SetLeafValue(best_value);
        for (Node n : children) {
            int v = AlphaBeta(n, depth-1, alpha, beta, TURN_HAN).GetLeafValue();
            if ( beta <= alpha ) break; // beta cut-off
            
            alpha = max(alpha, v);
            if(v > best_value) {
                best_value = v;
                n.SetLeafValue(v);
                best_node = n;
            }
        }
    } else { //TRUN_HAN . minizing player
        best_value = INT_MAX;
        best_node.SetLeafValue(best_value);
        for (Node n : children) {
            int v = AlphaBeta(n, depth-1, alpha, beta, TURN_CHO).GetLeafValue();
            if ( beta <= alpha ) break; // alpha cut-off

            beta = min(beta, v);
            if (v < best_value) {
                best_value = v;
                n.SetLeafValue(v);
                best_node = n;
            }
        }
    }
    
    //debug
    
     if ( depth == MINMAX_DEPTH) {
     int i=0;
     for (Node n: children) {
     Board b= n.board;
     printf("%d) %d,%d -> %d,%d\n", i++, n.GetAction().prev.x, n.GetAction().prev.y, n.GetAction().next.x, n.GetAction().next.y);
     }
     printf("best : %d,%d -> %d,%d. best_score = %d\n",
     best_node.GetAction().prev.x,
     best_node.GetAction().prev.y,
     best_node.GetAction().next.x,
     best_node.GetAction().next.y,
     best_value);
     }
    
    return best_node;
}
Example #22
0
int AlphaBeta(board_t *brd, int alpha, int beta, int depth, searchinfo_t *sinfo, int null)
{
	if(depth == 0){
		//return Eval(brd);
		return Quiece(brd, alpha, beta, sinfo);
	}

	if(!(sinfo->nodes & 0xfff)) CheckUp(sinfo);

	sinfo->nodes++;

	ASSERT(CheckBrd(brd));

	// if we are not the root of the tree and we have a repetition
	// or we exceeded the fifty move rule, then we have a draw and return 0
	if((IsRep(brd) || brd->fifty >= 100) && brd->ply) return 0;
	if(brd->ply >= MAXDEPTH-1) return Eval(brd);	// if we are too deep, we return

	// test if we are in check
	int check = SqAttacked(brd, LOCATEBIT(brd->bb[brd->side][King]), brd->side^1);
	if(check) depth++;

	int score = -INFINITE;
	int pvMain = NO_MOVE;
	// check the transposition table if we have searched the current position before
	// if so, return what we found
	if(TestHashTable(brd, &pvMain, &score, alpha, beta, depth)) return score;

	// Before we search, we try how we do if we don't make a move
	// i.e. make a null move
	if( null && !check && brd->ply && depth >= 4 &&
		(brd->all[brd->side]^brd->bb[brd->side][Pawn]^brd->bb[brd->side][King]) )
	{
		MakeMoveNull(brd);
		// We cannot do two null moves in a row so we set the null argument here to false
		score = -AlphaBeta(brd, -beta, -beta + 1, depth-4, sinfo, false);
		TakeBackNull(brd);

		if(sinfo->stop){
			return 0;
		}
		if(score >= beta){
			return beta;
		}
	}

	mlist_t list;
	int i;
	int legal = 0;
	int bestMove = NO_MOVE;
	int bestScore = -INFINITE;
	int oldAlpha = alpha;
	score = -INFINITE;

	GenMoves(brd, &list);

	// we tested our transposition table for the best move 'pvMain'
	// if it exists we will set this move as the first move to be searched
	if(pvMain != NO_MOVE){

		if(MakeMove(brd, pvMain)){
			score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true);
			TakeBack(brd);

			bestScore = score;
			if(score > alpha){
				if(score >= beta){
					if(!(pvMain & FLAGCAP)){
						brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply];
						brd->betaMoves[0][brd->ply] = pvMain;
					}
					return beta;
				}
				alpha = score;
				bestMove = pvMain;
			}
		}
		/*/
		for(i = 0; i < list.len; i++){
			if(list.move[i].move == pvMain){
				list.move[i].score = 5000000;
				break;
			}
		}//*/
	}

	for(i = 0; i < list.len; i++) // Loop through all moves
	{
		if(sinfo->stop) return 0;

		SelectNextMove(&list, i);

		if(!MakeMove(brd, list.move[i].move)) continue;

		legal++; // we have found a legal move so we need not check for mate afterwards
		// call AlphaBeta in a negamax fashion
		score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true);
		TakeBack(brd);

		if(score > bestScore){
			bestScore = score;
			if(score > alpha){
				if(score >= beta){
					if(legal==1) sinfo->fhf++; 	// count the number of beta cutoffs searched first
					sinfo->fh++;				// compared to all beta cutoffs (measure of efficiency)
					if(!(list.move[i].move & FLAGCAP)){
						brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply];
						brd->betaMoves[0][brd->ply] = list.move[i].move;
					}
					// Store the move in the transposition table as a beta (killer) move
					StorePvMove(brd, bestMove, depth, beta, HFBETA);
					return beta;
				}
				alpha = score;
				bestMove = list.move[i].move;
			}
		}
	}
	if(legal == 0){ // We havn't found a legal move
		if(check){
			// if we are in check it is mate; but we want the shortest path
			// to it so we'll subtract the path length
			return -MATE + brd->ply;
		}
		return 0; // Stalemate
	}

	if(oldAlpha != alpha){
		// Store exact (normal) transposition entry
		StorePvMove(brd, bestMove, depth, bestScore, HFEXACT);
	}
	else {
		// Store alpha cutoff transposition entry
		StorePvMove(brd, bestMove, depth, alpha, HFALPHA);
	}

	return alpha;
}
Example #23
0
Move Engine::IterativeDeepening(int mode, uint64_t wtime, uint64_t btime, uint64_t winc, uint64_t binc, bool print)
{
	int status = pos.getGameStatus();
	if(status==STATUS_WHITEMATED || status == STATUS_BLACKMATED || status == STATUS_STALEMATE)
	{
		return CONS_NULLMOVE;
	}

	vector<Move> moves;
	pos.generateMoves(moves);
	if (moves.size() == 1) //only 1 legal move
		return moves.at(0);

	//init
	prepareSearch();

	timeMode = mode;
	AllocatedTime = 1;
	uint64_t mytime = 1;
	uint64_t opptime = 1;
	if (mode == MODE_MOVETIME)
	{
		AllocatedTime = wtime;
	}
	else
	{
		if (pos.turn == COLOR_WHITE)
		{
			mytime = wtime;
			opptime = btime;
		}
		else
		{
			mytime = btime;
			opptime = wtime;
		}
		AllocatedTime = max((uint64_t)1, mytime / 15);
	}
	if(mode==MODE_DEPTH)
	{
		MAXDEPTH = wtime;
	}
	else
	{
		MAXDEPTH = 100;
	}
	if (opptime < mytime / 4 && timeMode == MODE_DEFAULT)
	{
		AllocatedTime = max((uint64_t)1, mytime / 4); //if opponent is in time trouble lets take our sweet time
	}

#ifdef BLITZKRIEG_DEBUG
	if(print)
		cout << "Allocated Time: " << AllocatedTime << endl;
#endif

	vector<Move> line;
	line.reserve(128);
	
	int score = AlphaBeta(1,CONS_NEGINF,CONS_INF,&line,false,false);
	//int score = think(1,CONS_NEGINF,CONS_INF,&line);
	//PrincipalVariation = line;
	int val = 0;
	int lastscore = 0;
	timer.Start();
	int takeback = 0;
	int initialmovenumber = pos.movelist.size();
	Move bestmove = line.at(line.size()-1);

	/*for (int i = 0;i < 128;i++)
	{
		PrincipalVariation[i] = CONS_NULLMOVE;
	}*/
	//cout << "takeback set " << takeback << " " << PrincipalVariation.size() << endl;
	takeback = setjmp(env);
	if(takeback!=0)
	{
		while(pos.movelist.size()>initialmovenumber)
		{
			pos.takebackMove();
			takeback--;
		}

		if (print)
		{
			cout << "info string ";
			//cout << "Eval time: " << evaltime.time << ", Sort time: " << sorttime.time << ", Quisc time: " << quisctime.time << ", movegen time: " << movegentime.time << ", Timer: " << timer.ElapsedMilliseconds();
			cout << "Nodes: " << nodes << ", Pruned nodes: " << prunednodes << ": " << ((double)(prunednodes * 100) / nodes) << "%, Futility nodes: " << futilitynodes << ": " << ((double)(futilitynodes * 100) / nodes) << "%";
			cout << ", Avg. beta: " << ((double)betacutoff_sum / betacutoff_counter);
			cout << ", First beta: " << ((double)(firstbetacutoffcount*100) / betacutoff_counter) << "%";
			cout << ", Latemove researches: " << latemoveresearch;
			cout << ", PV researches: " << pvresearch;
			//cout << ", Bad null: " << badavoidnull;
			cout << ", Aspiration Resets: " << aspirationresets;
			cout << ", Nullcutoffs: " << nullcutoffs;
			/*cout << ", Avg. alpha first: " << ((double)alphafirst_sum / alpha_counter);
			cout << ", Avg. alpha last: " << ((double)alphalast_sum / alpha_counter);*/
			cout << ", Fake Hits: " << ((double)(Table.hits * 100) / nodes);
			cout << ", TT hits: " << tthitcount << ": " << ((double)(tthitcount * 100) / nodes) << "%" << endl;
			Table.hits = 0;
		}
		
		/*if (PvSize < 0)
		{
			cout << "info string ERROR: pv size is 0\n";
			return CONS_NULLMOVE;
		}*/
		ply = 0;
		return bestmove;
	}
	incheck[0] = pos.underCheck(pos.turn);
	for (int i = 2;i <= MAXDEPTH;i++)
	{
		//mr = think(i,CONS_NEGINF,CONS_INF);
		//mr = think(i,score - 100,score + 100); //aspiration search
		//if(mr.eval <= score-150 || mr.eval >= score+150)
		//{
		//	cout << "Aspiration fail " << mr.eval << endl;
		//	mr = think(i,CONS_NEGINF,CONS_INF);
		//}
		//int low = 8;
		//int high = 8;

		/*PvSize = -1;
		PvPly = -1;*/

		int delta = 32;
		int alpha = max(score - delta, int(CONS_NEGINF));
		int beta = min(score + delta, int(CONS_INF));

		while (true)
		{
			//line = deque<Move>();
			ply = 0;
			//PvSize = -1;
			line.clear();
			val = AlphaBeta(i, alpha, beta, &line, true, true);
			checkup();
			//cout << "asp. " << alpha << " " << beta << endl;
			/*for (int i = 0;i < 2;i++)
			{
				for (int j = 0;j < 100;j++)
				{
					KillerScores[i][j] = CONS_NEGINF;
				}
			}*/
			if (val <= alpha)
			{
				beta = (alpha + beta) / 2;
				alpha = max(score - delta, int(CONS_NEGINF));
				//cout << "val is " << val << endl;
				//low = low << 1;
			}
			else if (val >= beta)
			{
				alpha = (alpha + beta) / 2;
				beta = min(score + delta, int(CONS_INF));
				//cout << "val is " << val << endl;
				//high = high << 1;
			}
			else break;

			delta += delta / 2;
			aspirationresets++;
		}
		lastscore = score;
		score = val;
		assert(score > CONS_NEGINF && score < CONS_INF);
		timer.Stop();
		if (print)
		{
			cout << "info score cp " << score << " depth " << i << " seldepth " << SelectiveDepth << " nodes " << nodes << " nps " << getNPS(nodes, timer.ElapsedMilliseconds()) << " time " << timer.ElapsedMilliseconds() << " pv ";
			for (int j = line.size() - 1;j >= 0;j--)
			{
				cout << line.at(j).toString() << " ";
			}
			cout << endl;
			/*for (int j = 0;j < 128;j++)
			{
				if (PrincipalVariation[j].isNullMove())
					break;
				cout << PrincipalVariation[j].toString() << " ";
			}*/
		}
		PrincipalVariation = line;
		bestmove = line.at(line.size()-1);
		if (timeMode == MODE_DEFAULT)
		{
			if (score > lastscore + 100 || score < lastscore - 100) //score changed? allocate more time
			{
				AllocatedTime = min(AllocatedTime + mytime / 30, max((uint64_t)1, mytime / 4));
			}
		}
	}
	if (print)
	{
		cout << "Nodes: " << nodes << endl;
		cout << "info string Eval time: " << evaltime.ElapsedMilliseconds() << ", Sort time: " << sorttime.ElapsedMilliseconds() << ", Quisc time: " << quisctime.ElapsedMilliseconds() << ", movegen time: " << movegentime.ElapsedMilliseconds() << endl;
	}
	/*if (PvSize < 0)
	{
		cout << "info string ERROR: principal variation size is 0\n";
		return CONS_NULLMOVE;
	}*/
	//Move bestmove = PrincipalVariation[0];
	ply = 0;
	return bestmove;
}
Example #24
0
void IterativeDeep(BOARD *board, CONTROL *control)
{
    MOVE iPV[PVLEN];
    char sPV[SPVLEN];
    char str_mov[MVLEN];
    int eval = 0, pvlen = 0;
    int alpha = -INFINITE;
    int beta = INFINITE;
    int widening = ASP_WINDOW;
    unsigned long long nps = 0;
    MOVE killers[MAXDEPTH][2];
    control->best_move = 0;

/*printf("time %llu %llu\n", control->max_time, control->wish_time);*/
    
    for(unsigned int depth = 1; depth <= control->max_depth;){
        clock_t curr_time = clock();
        memset(sPV, 0, SPVLEN);
        control->node_count = 0;
        
        eval = AlphaBeta(board, depth, alpha, beta, 0, control, 1, killers);
        if(control->stop && !control->ponder){
            break;
        }
        pvlen = RetrievePV(board, iPV, depth+10);
        for(int i = 0; i < pvlen; i++){
            MoveToAlgeb(iPV[i], str_mov);
            strcat(sPV, str_mov);
        }

        curr_time = (clock() - curr_time)/CPMS;
        if(curr_time){
            nps = 1000*(control->node_count/curr_time);
        }
        if(eval > MATE_VALUE/2 && -eval > MATE_VALUE/2){
            printf("info depth %u time %llu nodes %llu nps %llu score cp %i pv %s\n",
                    depth, (unsigned long long)curr_time, control->node_count, nps, eval, sPV);
        }else if(-eval < MATE_VALUE/2){
            printf("info depth %u time %llu nodes %llu nps %llu score mate %i pv %s\n",
                    depth, (unsigned long long)curr_time, control->node_count, nps, (pvlen+1)/2, sPV);
        }else if(eval < MATE_VALUE/2){
            printf("info depth %u time %llu nodes %llu nps %llu score mate %i pv %s\n",
                    depth, (unsigned long long)curr_time, control->node_count, nps, -(pvlen+1)/2, sPV);
        }
        if(eval <= alpha || eval >= beta){
            alpha = -INFINITE;
            beta = INFINITE;
        }else{
            if(3*curr_time > control->wish_time*CPMS - (clock()-control->init_time)){
                control->stop = 1;
            }
            alpha = eval - ASP_WINDOW;
            beta = eval + ASP_WINDOW;
            depth++;
        }
    }
    control->stop = 1;
    MoveToAlgeb(control->best_move, str_mov);
    printf("bestmove %s", str_mov);
    if(pvlen > 1){
        MoveToAlgeb(iPV[1], str_mov);
        printf("ponder %s", str_mov);
    }
    printf("\n");
}
Example #25
0
    /* alpha (lower bound): Keeps track of the highest score obtained at a
     * maximizing node higher up in the tree and is used to perform cut-offs at
     * minimizing nodes.
     * beta (upper bound): Keeps track of the lowest score obtained at a
     * minimizing node higher up in the tree and is used to perform cut-offs at
     * maximizing nodes.
     */
    bool AlphaBetaParallel::AlphaBeta(const GameBoard* board, uint32_t depth,
            uint32_t max_depth,
            float alpha, float beta, float& chosen_score,
            GameMove*& chosen_move)
    {
        // if we've reached the leaves, evaluate board
        if (depth == max_depth) {
            chosen_score = game_->evaluateBoard(board);
            return true;
        }
        // initialize scores
        float score;
        if (board->getTurn() == WHITE)
            score = alpha;
        else
            score = beta;

        // initialize chosen move
        chosen_move = NULL;

        // generate all possible moves
        std::list<GameMove*> moves_list;
        game_->generateMoves(board, moves_list);
        if (moves_list.empty()) {
            chosen_score = game_->evaluateBoard(board);
            return true;
        }

        // calculate the PVS
        std::list<GameMove*>::iterator it = moves_list.begin();
        {
            GameBoard* new_board;
            GameMove* new_move;
            float game_tree_value;
            game_->applyMove(board, new_board, *it);

            // find score of new position
            if (board->getTurn() == WHITE) {
                AlphaBeta(new_board, depth + 1, max_depth, score, beta,
                        game_tree_value, new_move);
                if (game_tree_value >= beta) {
                    chosen_move = *it; // CORRECT?
                    chosen_score = beta;
                } else if (game_tree_value > score) {
                    score = game_tree_value;
                    chosen_move = *it;
                }
            } else {
                AlphaBeta(new_board, depth + 1, max_depth, alpha, score,
                        game_tree_value, new_move);
                if (game_tree_value <= alpha) {
                    chosen_score = alpha;
                    chosen_move = new_move;
                } else if (game_tree_value < score) {
                    score = game_tree_value;
                    chosen_move = *it;
                }
            }
            delete new_board;
        }
        it++;

        std::list<GameMove*>::iterator mov_it;
        std::vector<GameMove*> mvec;
        for ( ; it != moves_list.end(); ++it)
            mvec.push_back(*it);
        bool pruned = false;
        #pragma omp parallel \
                private(score) \
                shared(board, depth, max_depth, alpha, beta, pruned)
        {
            #pragma omp for
            for (uint32_t i=0; i<mvec.size(); i++) {
                #pragma omp flush (pruned)
                if (!pruned) {
                    // generate new board position
                    GameBoard* new_board;
                    GameMove* new_move;
                    float game_tree_value;
                    game_->applyMove(board, new_board, mvec[i]);

                    // find score of new position
                    if (board->getTurn() == WHITE) {
                        AlphaBeta(new_board, depth + 1, max_depth, score, beta,
                                game_tree_value, new_move);
                        #pragma omp flush (beta)
                        if (game_tree_value >= beta) {
                            #pragma omp critical
                            chosen_move = mvec[i]; // CORRECT?
                            chosen_score = beta;
                            pruned = true;
                        }
                        if (game_tree_value > score) {
                            #pragma omp critical
                            score = game_tree_value;
                            chosen_move = mvec[i];
                        }
                    } else {
                        AlphaBeta(new_board, depth + 1, max_depth, alpha, score,
                                game_tree_value, new_move);
                        #pragma omp flush (alpha)
                        if (game_tree_value <= alpha) {
                            #pragma omp critical
                            chosen_score = alpha;
                            chosen_move = new_move;
                            pruned = true;
                        }
                        if (game_tree_value < score) {
                            #pragma omp critical
                            score = game_tree_value;
                            chosen_move = mvec[i];
                        }
                    }
                    delete new_board;
                }
            }
        }
        if (!pruned)
            chosen_score = score;
        it = moves_list.begin();
        for ( ; it != moves_list.end(); ++it)
            if (*it != chosen_move)
                delete *it;
        return true;
    }
Example #26
0
static int AlphaBeta(BOARD *board, unsigned int depth, int alpha, int beta,
               int root, CONTROL *control, char skip_null, MOVE killers[][2])
{
    int nmoves, nlegal = 0;
    MOVE moves[MAXMOVES];
    MOVE best_move = 0;
    char str_mov[MVLEN];
    int val = ERRORVALUE;
    char hash_flag = HASH_ALPHA;
    int reduce = 0, LMR = 0;

    if(depth){
        if(root > 0){
            val = GetHashEval(&hash_table, board->zobrist_key, depth, alpha, beta);
            if(val != ERRORVALUE) return val; 
        }
        if(depth > 2 && !InCheck(board, 0)){

            if(!skip_null && board->piece_material[board->white_to_move] != 0){
                MOVE null_mv = NULL_MOVE;
                MakeMove(board, &null_mv);
                val = -AlphaBeta(board, depth-3, -beta, -beta+1, root+1, control, 1, killers);
                Takeback(board, null_mv);
                if(val >= beta) return beta;
            }
            reduce = 1;	/*Try Late Move reductions.*/
        }
        nmoves = MoveGen(board, moves, 1);
        int good = SortMoves(board, moves, nmoves, killers[root]);
        for(int i = 0; i < nmoves; i++){
            MakeMove(board, &moves[i]);
            control->node_count++;
            if(!LeftInCheck(board)){
                if(root == 0){
                    if(!control->best_move) control->best_move = moves[i];    /* Better than nothing. */
                    if(depth > 6 && !control->ponder){
                        MoveToAlgeb(moves[i], str_mov);
                        printf("info depth %i hashfull %i currmove %s currmovenumber %i\n",
                            depth, hash_table.full/(hash_table.size/1000), str_mov, i+1);
                    }
                }
                nlegal++;
                val = AssesDraw(board);
                if(val) {
                    if(best_move){
                        LMR = (reduce && i > good && !CAPTMASK(moves[i]) && !InCheck(board, 0)) ? 1 : 0;
                        val = -AlphaBeta(board, depth-LMR-1, -alpha-1, -alpha, root+1, control, 0, killers);
                        if(val > alpha){
                            val = -AlphaBeta(board, depth-1, -alpha-1, -alpha, root+1, control, 0, killers);
                            if(val > alpha && val < beta){
                                val = -AlphaBeta(board, depth-1, -beta, -alpha, root+1, control, 0, killers);
                            }
                        }
                    }else val = -AlphaBeta(board, depth-1, -beta, -alpha, root+1, control, 0, killers);
                }
                Takeback(board, moves[i]);
                if(!control->ponder && control->stop) return alpha;
                if(val >= beta){
                    UpdateTable(&hash_table, board->zobrist_key, val, moves[i], depth, HASH_BETA);
                    if(CAPTMASK(moves[i]) == 0
                            && killers[root][0] != moves[i]
                            && killers[root][1] != moves[i]){
                        killers[root][1] = killers[root][0];
                        killers[root][0] = moves[i];
                    }
                    return beta;
                }
                if(val > alpha){
                    alpha = val;
                    hash_flag = HASH_EXACT;
                    best_move = moves[i];
                    if(root == 0) control->best_move = best_move;
                }
                if(root == 0 && ((clock() - control->init_time) > control->wish_time*CPMS)){
                /* if short of time, don't search anymore after current move */
                    control->stop = 1;
                    return alpha;
                }
            }else Takeback(board, moves[i]);
        }
        if(nlegal == 0){
            if(InCheck(board, 0)){
/*UpdateTable(&hash_table, board->zobrist_key, MATE_VALUE+root, 0, depth, HASH_EXACT, hash_table.entries);*/
                return MATE_VALUE;
            }else{
/*UpdateTable(&hash_table, board->zobrist_key, DRAW_VALUE, 0, depth, HASH_EXACT, hash_table.entries);*/
                return DRAW_VALUE;    /*Stalemate*/
            }
        }else UpdateTable(&hash_table, board->zobrist_key, alpha, best_move, depth, hash_flag);
        
    }else if(InCheck(board, 0)){
        alpha = AlphaBeta(board, 1, alpha, beta, root+1, control, 1, killers);
    }else{
        alpha = Quiescent(board, alpha, beta, root, control, killers);
    }
    return alpha;
}
Example #27
0
/*
 @brief alpah-beta搜索函数,寻找最适合的一个放子点
 @param board 棋局
 @param depth 当前深度
 @param alpha MAX结点的搜索下限
 @param beta MIN结点的搜索上限
 @param team 当前要下子的一方
 @return 此时的alpha值
 */
int AlphaBeta(int **oriBoard, int depth, int alpha, int beta, PieceTeam team)
{
    int **board = copy2DIntArray(oriBoard, kBoardRow, kBoardCol);
    
    if (depth == 0) {
        // 评估分综合双方棋局得到
        int s1 = Evaluate(board, team);
        int s2 = Evaluate(board, AnotherTeam(team));
        int score = s1-s2;
        return score;
    }
    
    SeqIntPt candi = getCandidate(board);
    
    // 先对所有可扩展结点进行估价,并排序
    SortType sortedCandi;
    for (SeqIntPt::iterator iter=candi.begin(); iter!=candi.end(); ++iter){
        int score = sortEvaluation(board, team, *iter);
        sortedCandi.insert(SortNode(score, iter->r, iter->c));
    }
    
    // 根据启发函数对可扩展结点排序后的顺序来扩展
    for(SortType::iterator it=sortedCandi.begin(); it!=sortedCandi.end(); ++it)
    {
        GBIntPoint pos = it->pos;
        if (board[pos.r][pos.c] != PieceTeamNone)
            continue;
        board[pos.r][pos.c] = team;
        
        // 第一层的剪枝优化:如果己方或对方在此处有必赢棋局,直接放在此处
        if (depth == InDepth) {
            int tscore = oneStepEvaluation(board, team, pos);
//            printf("candidate: %d, %d; score: %d\n",pos.r, pos.c, tscore);
            if (tscore>alpha){  //评分80及以上的局势都是必赢的局
//                for (int i=kBoardRow-1; i>=0; --i) {
//                    for (int j=0; j<kBoardCol; ++j) {
//                        printf("%d ", board[i][j]);
//                    }
//                    printf("\n");
//                }
//                printf("%d\n", tscore);
//                Evaluate(board, team);
                
                alpha = tscore;
                BestPiece.r = pos.r;
                BestPiece.c = pos.c;
            }
        }
        
        // 递归搜索
        int val = -AlphaBeta(board, depth - 1, -beta, -alpha, AnotherTeam(team));
        
        // 还原现场
        board[pos.r][pos.c] = PieceTeamNone;
        
        // alpha-beta 剪枝
        if (val >= beta) {
            delete2DIntArray(board);
            return beta;
        }
        if (val>alpha && board[pos.r][pos.c]==PieceTeamNone) {
            alpha = val;
            if (depth == InDepth){  // 第一层,更新最优位置
                BestPiece.r = pos.r;
                BestPiece.c = pos.c;
            }
        }
    }
    
    delete2DIntArray(board);
    return alpha;
}
Example #28
0
static int AlphaBeta (BOARD *board, int depth, int alpha, int beta,
               int root, CONTROL *control, char skip_null, MOVE killers[][2])
{
  int nmoves, good = 0, nlegal = 0;
  MOVE moves[MAXMOVES];
  MOVE best_move = 0;
  char str_mov[MVLEN];
  int val = ERRORVALUE;
  char hash_flag = HASH_ALPHA;
  
  int in_check = InCheck(board, 0);

  if (root > control->seldepth) control->seldepth = root;

  if (depth > 0 || in_check) {
    if (root > 0) {
      val = GetHashEval(&hash_table, board->zobrist_key, depth, alpha, beta);
      if (val != ERRORVALUE) return val;
    }
    if (depth > 2 && !in_check) {    
      if (!skip_null && board->piece_material[board->white_to_move] != 0) {
        MOVE null_mv = NULL_MOVE;
        MakeMove(board, &null_mv);
        val = -AlphaBeta(board, depth-3, -beta, -beta+1, root+1, control, 1, killers);
        Takeback(board, null_mv);
        if (val >= beta) return beta;
      }
    }
    nmoves = MoveGen(board, moves, 1);
    good = SortMoves(board, moves, nmoves, killers[root]);
  } else {
    if (!control->ponder && clock() - control->init_time >= control->max_time*CPMS) {
      control->stop = 1;
    }
    val = LazyEval(board);
    if (val-LAZYBETA >= beta) return beta;
    if (val+LAZYALPHA < alpha) return alpha;

    val = StaticEval(board);
    UpdateTable(&hash_table, board->zobrist_key, val, 0, 0, HASH_EXACT);
    if (val >= beta) return beta;
    if (val > alpha) alpha = val;
    
    nmoves = CaptureGen(board, moves);
    nmoves = FilterWinning(board, moves, nmoves);
  }
        
  for (int i = 0; i < nmoves; i++) {
    MakeMove(board, &moves[i]);
    control->node_count++;
    if (LeftInCheck(board)) {
      Takeback(board, moves[i]);
      continue;
    }
    if (root == 0) {
      if (!control->best_move) control->best_move = moves[i];    /* Better than nothing. */
      if (depth > 6 && !control->ponder) {
        MoveToAlgeb(moves[i], str_mov);
        printf("info depth %i seldepth %i hashfull %i currmove %s currmovenumber %i\n",
               depth, control->seldepth, hash_table.full/(hash_table.size/1000), str_mov, i+1);
      }
    }
    nlegal++;
    val = AssessDraw(board, control->contempt);
    if (val == ERRORVALUE) {
      int ext = 0; //InCheck(board, 0) ? 1 : 0;
      if (best_move) {
        int LMR = (depth > 2 && !in_check && i > good &&
                   !CAPTMASK(moves[i]) && !InCheck(board, 0)) ? 1 : 0;
        val = -AlphaBeta(board, depth+ext-LMR-1, -alpha-1, -alpha, root+1, control, 0, killers);
        if (val > alpha) {
          val = -AlphaBeta(board, depth+ext-1, -alpha-1, -alpha, root+1, control, 0, killers);
          if (val > alpha && val < beta) {
            val = -AlphaBeta(board, depth+ext-1, -beta, -alpha, root+1, control, 0, killers);
          }
        }
      } else {
        val = -AlphaBeta(board, depth+ext-1, -beta, -alpha, root+1, control, 0, killers);
      }
    }
    Takeback(board, moves[i]);
    if (!control->ponder && control->stop) return alpha;
    if (val >= beta) {
      UpdateTable(&hash_table, board->zobrist_key, val, moves[i], depth, HASH_BETA);
      if (CAPTMASK(moves[i]) == 0 && killers[root][0] != moves[i] && killers[root][1] != moves[i]) {
        killers[root][1] = killers[root][0];
        killers[root][0] = moves[i];
      }
      return beta;
    }
    if (val > alpha) {
      alpha = val;
      hash_flag = HASH_EXACT;
      best_move = moves[i];
      if (root == 0) control->best_move = best_move;
    }
    if (root == 0 && ((clock() - control->init_time) > control->wish_time*CPMS)) {
    /* if short of time, don't search anymore after current move */
      control->stop = 1;
      return alpha;
    }
  }
  if (nlegal == 0) {
    if (in_check) {
      /*UpdateTable(&hash_table, board->zobrist_key, MATE_VALUE+root, 0, depth, HASH_EXACT, hash_table.entries);*/
      return MATE_VALUE;
    } else if (depth > 0) {
      /*UpdateTable(&hash_table, board->zobrist_key, DRAW_VALUE, 0, depth, HASH_EXACT, hash_table.entries);*/
      return DRAW_VALUE;    /*Stalemate*/
    }
  } else {
    UpdateTable(&hash_table, board->zobrist_key, alpha, best_move, depth, hash_flag);
  }
  return alpha;
}
Example #29
0
int CAlphaBeta_TTEngine::AlphaBeta(int nDepth, int alpha, int beta)
{
    int score;
    int Count,i;
    BYTE type;
    int side;

    i=IsGameOver(CurPosition,nDepth);
    if(i!=0)
        return i;
    
    //察看当前节点是否在置换表中有有效数据
    side=(m_nMaxDepth-nDepth)%2;
    score=LookUpHashTable(alpha,beta,nDepth,side); 
    if(score!=66666) 
        return score;//命中,直接返回表中的值

    //叶子节点取估值
    if(nDepth<=0)
    {
        score=m_pEval->Eveluate(CurPosition,side,m_nUserChessColor);
        EnterHashTable(exact,score,nDepth,side);//将求得的估值放进置换表
        return score;
    }

    Count=m_pMG->CreatePossibleMove(CurPosition,nDepth,side,m_nUserChessColor);
    if(nDepth==m_nMaxDepth)
    {
        //在根节点设定进度条        
        progress->setTotalSteps(Count);
        progress->setProgress(1);
    }

    int eval_is_exact=0;//数据类型标志

    for(i=0;i<Count;i++)//对当前节点的下一步每一可能的走法
    {
        if(nDepth==m_nMaxDepth)
            progress->nextStep();

        Hash_MakeMove(&m_pMG->m_MoveList[nDepth][i],CurPosition);//产生该走法所对应子节点的哈希值
        type=MakeMove(&m_pMG->m_MoveList[nDepth][i]);            //产生子节点
        
        score=-AlphaBeta(nDepth-1,-beta,-alpha);//递归搜索子节点

        Hash_UnMakeMove(&m_pMG->m_MoveList[nDepth][i],type,CurPosition);//恢复当前节点的哈希值 
        UnMakeMove(&m_pMG->m_MoveList[nDepth][i],type);                //撤销子节点
        if(score>=beta)//beta剪枝
        {
            EnterHashTable(lower_bound,score,nDepth,side);//将节点下边界存入置换表
            return score;//返回下边界
        }

        if(score>alpha)
        {
            alpha=score;    //取最大值
            eval_is_exact=1;//设定确切值标志
            if(nDepth==m_nMaxDepth)
                m_cmBestMove=m_pMG->m_MoveList[nDepth][i];
        }
    }

    //将搜索结果放进置换表
    if(eval_is_exact) 
        EnterHashTable(exact,alpha,nDepth,side);      //确切值
    else 
        EnterHashTable(upper_bound,alpha,nDepth,side);//上边界

    return alpha;//返回最佳值/上界
}
Example #30
0
int AlphaBeta(int depth, int alpha, int beta, int turn)// turn=1 if blue; else 0;
{
    int val;
    int * legal_columns;
    int * legal_pieces;
    int max_legal;
    int i;
    
    
    /*check win*/
    val = checkComp(evaluated_column, total_rows, board);
    if (val != 0) // if finds win, return
    {
#ifdef ZZZ
        printf("FOUND WIN: column%d val:%d\n", evaluated_column, val);
        
        dispboard();
#endif
        return val;
    }

    if(depth == 0)
    {
        val = Evaluate();
        return val;
    }
    /* GenerateLegalMoves();                                                      */
	max_legal = 0;
	legal_columns = (int*)calloc(columns*2,sizeof(int));
	if (legal_columns == NULL)
		return alpha;
    
	legal_pieces = (int*)calloc(columns*2,sizeof(int));
    
	if (legal_pieces == NULL)
	{
		free(legal_columns);
		return alpha;
	}
    
    if (turn == 1) 
    {
        for (i = 0; i < columns; i++)
        {
            if (board[order[i] * total_rows + rows - 1] == SPACE)
            {
                legal_columns[max_legal] = order[i];
                legal_pieces[max_legal++] = BLUE;
                legal_columns[max_legal] = order[i];
                legal_pieces[max_legal++] = GREEN;
            }
        }
    }
    else
    {
        for (i = 0; i < columns; i++)
        {
            if (board[order[i] * total_rows + rows - 1] == SPACE)
            {
                legal_columns[max_legal] = order[i];
                legal_pieces[max_legal++] = RED;
                legal_columns[max_legal] = order[i];
                legal_pieces[max_legal++] = GREEN;
            }
        }
    }

    turn = turn==1?0:1; // swithch turn
    if(max_legal == 0)// full board
        return alpha;
    
    
    /* while (MovesLeft()) {                                                      */
	for (i = 0; i < max_legal; i++) {
        
        /*    MakeNextMove();                                                         */
		AddToBoard(legal_columns[i], legal_pieces[i]);
        
        /*    val = Min(depth - 1);                                                   */
        evaluated_column = legal_columns[i];
        
        /* FOR DEBUGGING */
        /* FOR DEBUGGING */
        static int count = 0;
#ifdef ZZZ
        printf("\t\tMAX called %d times.\n", ++count);
        
        dispboard();
#endif
        /* FOR DEBUGGING */
        /* FOR DEBUGGING */
        
		val = -AlphaBeta(depth-1, -beta, -alpha, turn);
#ifdef ZZZ
        printf("MAX::Depth:%d column:%d piece:%d val:%d best:%d\n", maxdepthval - depth, evaluated_column, legal_pieces[i], val, alpha);
#endif
        
        
        /*    UnmakeMove();                                                           */
		RemoveFromBoard(legal_columns[i]);
        
        /*    if (val > best)                                                         */
        /*       best = val;
         */
		if (val > alpha)
		{
			alpha = val;
			if (depth == maxdepthval)
			{
                
				piece = legal_pieces[i];
				column = legal_columns[i];
//                if(best == 1000)// blocking case
//                    piece = BLUE;
#ifdef ZZZ
                printf("MAX::Best has changed:%d, column:%d, piece:%d \n", alpha, column, piece);
#endif
			}
		}
        /* }                                                                          */
	}
    free(legal_columns);
	free(legal_pieces);
    return alpha;
    
}