Beispiel #1
0
double Player::alphabeta(Board *b, int depth, double alpha, double beta, bool max_player) {
    if(depth == 0 || b->isDone())
        return b->score(side);

    double v;
    if(max_player) {
        v = -INF;
        vector<Move *> moves = b->possibleMoves(side);
        for(auto &m : moves) {
            Board *child = b->copy();
            child->doMove(m, side);
            v = max(v, alphabeta(child, depth - 1, alpha, beta, false));
            alpha = max(alpha, v);
            if(beta <= alpha)
                break;
        }
        
        return v;
    }
    else {
        v = INF;
        vector<Move *> moves = b->possibleMoves(opp_side);
        for(auto &m : moves) {
            Board *child = b->copy();
            child->doMove(m, opp_side);
            v = min(v, alphabeta(child, depth - 1, alpha, beta, true));
            beta = min(beta, v);
            if(beta <= alpha)
                break;
        }
        
        return v;
    }
}
Beispiel #2
0
/**
*\brief Fonction where_play, utilisée pour savoir où l'IA doit jouer.
*\details Cette fonction permet à l'IA (modulo sa profondeur) de savoir dans quelle colonne jouer, en se basant sur les
fonctions alphabeta et pond.
*\return a de type \a int, c'est le numéro de colonne (entre 1 et 7 donc) dans lequel l'IA doit jouer.
*/
int where_play(grid g,int depth,token t) {
	int i;
	int BestMove=1000 ;
	int tmp=1000 ;
	/* On initialise buf, mais Valgrind râle quand même, cf ligne 105 */
	char buf[7] = { 0 } ;
	int j=0 ;
	int z ;
	for(i=1;i<8;i++) {
		if(g->heights[i-1] != LINE_NB) {
			/* On pose un jeton */
			put_token(g,i,t) ;
			/* Si on est RED ... */
			if(t==RED) { 
				/* ... On lance alphabeta en indiquant que le prochain joueur à joueur joue les YELLOW */
				tmp=alphabeta(g,-1000,1000,depth,YELLOW) ; 
			}
			/* Si on est YELLOW ... */
			if(t==YELLOW) { 
				/* ... On lance alphabeta en indiquant que le prochain joueur à joueur joue les RED */
				tmp=alphabeta(g,-1000,1000,depth,RED) ; 
			}
			/* En cas d'égalité, on stocke à la suite dans un tableau, en vue de décider du choix aléatoirement : 
			permet de gérer le cas où quel que soit la colonne dans laquelle on joue " le cas est le même " */
			if(tmp==BestMove) { 
				buf[j]=i ;
				j = j+1 ;
			}
			/* Si une valeur renvoyée est < BestMove, alors on remet les indices à 0, et on écrase le tableau, pour
			favoriser les pondérations " faibles " */
			if(tmp<BestMove) { 
				j=0 ;
				for(z=0;z<7;z++) {
					buf[z] = 0 ;
				} 
				BestMove = tmp ;
				buf[j]=i ;
				j = j + 1 ;
			}
			/* On enlève le jeton : parcours destructif de l'arbre */
			erase_token(g,i) ;
		}
	}
	int k=0 ;
	int l=0 ;
	/* On compte le nombre de valeurs non nulles dans le tableau. */
	while(k<7&&buf[k]!=0) { 
		l = l + 1 ;
		k = k + 1 ;
	}
	/* On balance une fonction aléatoire, avec une seed horaire */
  	srand (time (NULL)); 
  	/* On module modulo le nombre de valeurs non nulle qu'il faut considérer dans buf[]
  	-> permet de choisir aléatoirement en cas d'égalité !*/
   	int a = rand()%l; 
	return(buf[a]) ; 
}
Beispiel #3
0
void makeComputerMove(struct game *state)
{

  printf("makeComputerMove: Making computer move on board '%s' with player %c\n",state->board,state->player);

  /* Get the next possible states and choose the one with the least
	 minimax value */

  struct gamelist *nextstates = gennextstates(state);

  /* Set the minstatevalue to 2, larger than the minimax function will
	 return, so that the nextgame variable is definitely set */

  int minstatevalue = 2;
  int minimaxvalue;
  struct game *nextgame;

  puts("looping through next states checking minimax");

  while (nextstates != NULL)
	{
	  minimaxvalue = alphabeta(nextstates->state,-2,2);
	  if (minimaxvalue < minstatevalue) {
		minstatevalue = minimaxvalue;
		nextgame = nextstates->state;
	  }
      printf("Minimax value of board '%s' = %i\n",nextstates->state->board,minimaxvalue);
	  nextstates = nextstates->next;
	}

  strcpy(state->board,nextgame->board);
  state->player = nextgame->player;

}
void BOARD::iterativeDeepening()
{
	int bestscore=-INFINITE;
	int bestmove =NOMOVE;
	int numPv=0;

	clearForSearch();
	for(int i=1;i<=info.depth;i++)
	{
		bestscore=alphabeta(i,-INFINITE,INFINITE,true);
		if(info.stopped)
		break;
		numPv=getPvLine(i);
		bestmove=PVARRAY[0];
		printf("info score cp %d depth %d nodes %lld time %d ",bestscore,i,info.nodes,getTime()-info.starttime);
	
	printf("pv");
	for(int j=0;j<numPv;j++)
	{
		printf(" ");
		printMove(PVARRAY[j]);
	}
	printf("\n");
	//printf("Ordering : %0.2f\n",info.fhf/info.fh);
	}
	printf("bestmove ");printMove(bestmove);
	printf("\n");
}
int CAlphaBetaEngine::alphabeta(int depth, int alpha, int beta)
{
	int score;
	int Count,i;
	BYTE type;

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

	if (depth <= 0)	//叶子节点取估值
		return m_pEval->Eveluate(CurPosition, (m_nMaxDepth-depth)%2);
	
	Count = m_pMG->CreatePossibleMove(CurPosition, depth, (m_nMaxDepth-depth)%2);

	for (i=0;i<Count;i++) 
	{

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

		if (score > alpha)
		{
			alpha = score;
			if(depth == m_nMaxDepth)
				m_cmBestMove = m_pMG->m_MoveList[depth][i];
		}
        if (alpha >= beta) 
              break;

				
	}
	return alpha;
}
Beispiel #6
0
/*
 * Compute the next move given the opponent's last move. Your AI is
 * expected to keep track of the board on its own. If this is the first move,
 * or if the opponent passed on the last move, then opponentsMove will be NULL.
 *
 * msLeft represents the time your AI has left for the total game, in
 * milliseconds. doMove() must take no longer than msLeft, or your AI will
 * be disqualified! An msLeft value of -1 indicates no time limit.
 *
 * The move returned must be legal; if there are no valid moves for your side,
 * return NULL.
 */
Move *Player::doMove(Move *opponentsMove, int msLeft) {
    /* 
     * TODO: Implement how moves your AI should play here. You should first
     * process the opponent's opponents move before calculating your own move
     */ 
    board->doMove(opponentsMove, opp_side);
    vector<Move *> moves = board->possibleMoves(side);
    if(moves.empty())
        return NULL;

    double max_score, best_move = 0;

     for(int i = 0; i < moves.size(); i++) {
        Board *next = board->copy();
        next->doMove(moves[i], side);
        int s = alphabeta(next, 6, -INF, INF, false);
        if(i == 0)
            max_score = s;
        else if(s > max_score) {
            max_score = s;
            best_move = i;
        }
    }

    board->doMove(moves[best_move], side);
    return moves[best_move];
}
Beispiel #7
0
float alphabeta(BNTBoard board, int depth, float alpha, float beta, BNTPlayer player)
{
	if (depth == 0 || IsGameEnd(board))
		return EvaluateBoard(board, player) * (player == BNTPlayerX ? 1 : -1);
	
	if (player == BNTPlayerX)
	{
		for (int x = 0; x < BOARD_SIZE; ++x)
		{
			for (int y = 0; y < BOARD_SIZE; ++y)
			{
				if (board[x][y] == BNTPlayerNone)
				{
					board[x][y] = player;
					alpha = DEPTH_PENALTY * MAX(alpha, alphabeta(board, depth-1, alpha, beta, OppositePlayer(player)));
					board[x][y] = BNTPlayerNone;
					if (beta <= alpha)
					{
						break;/* Beta cut-off */
					}
				}
			}
		}
		return alpha;
	}
	else
	{
		
		for (int x = 0; x < BOARD_SIZE; ++x)
		{
			for (int y = 0; y < BOARD_SIZE; ++y)
			{
				if (board[x][y] == BNTPlayerNone)
				{
					board[x][y] = player;
					beta = DEPTH_PENALTY * MIN(beta, alphabeta(board, depth-1, alpha, beta, OppositePlayer(player)));
					board[x][y] = BNTPlayerNone;
					if (beta <= alpha)
					{
						break;/* Alpha cut-off */
					}
				}
			}
		}
		return beta;
	}
}
void CAlphaBetaEngine::SearchAGoodMove(BYTE position[10][9])
{
	memcpy(CurPosition, position, 90);
	m_nMaxDepth = m_nSearchDepth;
	alphabeta(m_nMaxDepth, -20000, 20000);
	MakeMove(&m_cmBestMove);
	memcpy(position, CurPosition, 90);
}
Beispiel #9
0
bool Board_AB::alphabeta_helper(num i, bool maximize, num depth,
				char& score, num& loc,
				char& alpha, char& beta,
				bool& firstChild
				){
  if (i >= n || grid[i] != '.') { return false; }
  if (depth > 0 && closestDist(i) > bound) { return false; }

  grid[i] = (maximize?'R':'B');

  Bitstring z = (maximize?assignmentZ[i].first:assignmentZ[i].second);
  zobrist ^= z;

  Bitstring g = (maximize?assignmentG[i].first:assignmentG[i].second);
  gamestate |= g;
  
  char curScore = 0;

  //PVS
  if (firstChild) {
    curScore = -alphabeta(!maximize, -beta, -alpha, depth+1, i).first;
    firstChild = false;
  }
  else {
    curScore = -alphabeta(!maximize, -alpha - 1, -alpha, depth+1, i).first;
    if (alpha < curScore && curScore < beta)
      { curScore = -alphabeta(!maximize, -beta, -curScore, depth+1, i).first; }
  }
  

  if (curScore > score) {
    loc = i;
    score = curScore;
    alpha = (alpha<score?score:alpha);
  }

  grid[i] = '.';
  zobrist ^= z;
  gamestate ^= g;

  return alpha >= beta;

}
Beispiel #10
0
std::pair<int, const typename boost::graph_traits<Graph>::vertex_descriptor>
alphabeta(const Graph &g, const typename boost::graph_traits<Graph>::vertex_descriptor vd, int depth, int alpha, int beta, bool player1, Heuristic heuristic)
{
  typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
  typename boost::graph_traits<Graph>::out_edge_iterator out_i, out_end;
  dout<<vd;

  if(depth == 0 || out_degree(vd, g) == 0) {
    dout<<std::endl;
    return std::make_pair(heuristic(vd), vd);
  }
  Vertex vert;

  if(player1) {
    int v = INT_MIN;
    for(boost::tie(out_i, out_end) = boost::out_edges(vd, g); out_i != out_end; ++out_i) {
        dout<<"   children "<<out_end - out_i;
        dout<<"   true";
        dout<<" calling "<<target(*out_i, g);
        dout<<std::endl;
      vert = target(*out_i, g);
      v = std::max(v, alphabeta(g, vert, depth-1, alpha, beta, !player1, heuristic).first);
      alpha = std::max(alpha, v);
      if(beta <= alpha)
        break;//beta cut-off
    }
    return std::make_pair(v, vert);
  } else {
    int v = INT_MAX;
    for(boost::tie(out_i, out_end) = boost::out_edges(vd, g); out_i != out_end; ++out_i) {
        dout<<"   children "<<out_end - out_i;
        dout<<"   false";
        dout<<" calling "<<target(*out_i, g);
        dout<<std::endl;
      vert = target(*out_i, g);
      v = std::min(v, alphabeta(g, vert, depth-1, alpha, beta, !player1, heuristic).first);
      beta = std::min(beta, v);
      if(beta<=alpha)
        break;//alpha cut-off
    }
    return std::make_pair(v, vert);
  }
}
Beispiel #11
0
int printMoveValue(char* command){
	int exitcode;
	int depth;
	int bestOffset = 0;
	if (command[10] == 'b'){
		depth = computeBestDepth();
		bestOffset = 3;
	}
	else{
		if (sscanf(command, "get_score %d", &depth) < 0){
			return -1;
		}
	}
	
	if (!strstr(command, "move") && !strstr(command, "castle")){
		return -1;
	}
	
	if (strstr(command, "move")){
		PossibleMove* move = readMove(command + 12 + bestOffset, &exitcode);
		if (exitcode != 0){ // illegal input or illegal move
			return exitcode;
		}
		else{
			int score = alphabeta(move, depth, !turn, INT_MIN, INT_MAX);
			printf("%d\n", score);
			PossibleMove_free(move);			
		}
	}
	// castling move
	else{
		int rookX, rookY;
		exitcode = readTile(command + 19, &rookX, &rookY); 
		if (exitcode == 0){
			PossibleMove* castlingMove = PossibleMove_new(rookX, rookY, 0, 0, 0, &board);
			int score = alphabeta(castlingMove, depth, !turn, INT_MIN, INT_MAX);
			printf("%d\n", score);
			PossibleMove_free(castlingMove);	
		}
	}
	return exitcode;
}
Beispiel #12
0
int main2()
{
    printf("\n\nSize of node is %zd bytes\n\n", sizeof(Node));
    int randSeed = time(NULL);
    printf("Random Seed: %d\n", randSeed);
    srand(randSeed);
    // 3, and 4 are good. 6,7,8 are very good
    // 10 is excellent
    srand(10);
    // generate a random tree
    printf ("generating random tree of depth %d\n", g_depth);
    Node root = {0};
    START_TIMER
    genTree(&root, g_depth);
    STOP_TIMER
    printf("random tree generated, total nodes: %d, leaf nodes: %d, time: %g ms\n", gTotalNodes, gLeafNodes, gTime);



    float bestVal = 0;
    // search the best move using min-max search
    printf("searching the tree using min-max\n");
    START_TIMER
    bestVal = negaMax(&root, g_depth, g_depth);
    STOP_TIMER
    printf ("best move %d, score: %f, time: %g\n", root.bestChild, root.nodeVal, gTime);

    // search the best move using alpha-beta search
    printf("searching the tree using alpha-beta\n");
    START_TIMER
    bestVal = alphabeta(&root, g_depth, g_depth, -INF, INF);
    STOP_TIMER
    printf ("best move %d, score: %f\nnodes visited (leaves/interior/total): %d/%d/%d\n", 
            root.bestChild, root.nodeVal, gLeafNodesVisited, gInteriorNodesVisited, gLeafNodesVisited + gInteriorNodesVisited);
    printf("time taken: %g\n", gTime);

    START_TIMER
    exploreTree(&root, g_depth);
    STOP_TIMER
    printf("time taken: %g\n", gTime);    
    

    float val;
    START_TIMER
    val = SSS_star(&root, g_depth);
    STOP_TIMER
    printf("SSS* best node: %d, score: %f, nodes explored: %d, time taken: %g\n", root.bestChild, val, g_sssNodes, gTime);

    freeTree(&root);
    getchar();

    return 0;
}
Beispiel #13
0
int depthSearch(SearchThread* self, ChessHNode* start,
    int depth, move_t* line, int* lineLength){
    int real_depth = DEPTH_ORDERS[depth];
    int quiecense = QUIECENSE_ORDERS[depth];
    int deep_quiecense = DEEP_QUIECENSE_ORDERS[depth];
    self->table->minHalfMoveNumber = start->halfMoveNumber;
    int eval = alphabeta(
        self, start, real_depth, quiecense, deep_quiecense,
        INT_MIN, INT_MAX, line, lineLength
    );
    return eval;
}
Beispiel #14
0
    /**
     * Builds a game tree and searches for a good movme in it using 
     * the minmax algorithm combined with alpha-beta pruning. 
     *  
     * @param board current state of the game
     * @param treeDepth depth of the game tree we build
     * @param score_out the score of the best move is returned here
     *  
     * @return cmove move chosen by the AI 
     */
    int findMove(chessBoard &board, int treeDepth, cmove &aimove) {
        moveTree mt;
        clock_t start = clock();
        mt.buildTree(board, mt.gameTree, treeDepth);
        clock_t end = clock();
        printf("Built move tree with depth %d in %f seconds.\n", 
               treeDepth,
               ((float)end - (float)start) / CLOCKS_PER_SEC);

        // printf("current player is %d\n", board.currentPlayer);
        
        linkedList< tree<moveNode*>* > *ch = mt.gameTree->children;
        linkedList< cmove > *moves = mt.moveList;

        if (moves->size != ch->size ) {
            cout << "ERROR: move numbers do not match" << endl;
        }

        // printf("moves depth 1: %d\n", sumMoves(mt.gameTree, 0));
        // printf("moves depth 2: %d\n", sumMoves(mt.gameTree, 1));
        // printf("moves depth 3: %d\n", sumMoves(mt.gameTree, 2));
        
        int bestValue = INT_MIN;
        
        start = clock();
        for (int i = 0; i < ch->size; i++) {
            tree<moveNode*> *n = (*ch)[i];

            // start with min value (bmax = false) because in the situation we
            // are evaluating it is the opponent's turn!
            int value = alphabeta(n, treeDepth-1, INT_MIN, INT_MAX, false);
            // int value = minimax(n, treeDepth-1, false);

#if 0
            cmove move = (*ch)[i]->item->prev_move;
            printf("Move %c%d %c%d, score %d\n",
                   move.from.x + 'a', move.from.y + 1,
                   move.to.x + 'a', move.to.y + 1, value);
#endif

            if (value > bestValue) {
                // aimove = (*ch)[i]->item->prev_move;
                aimove = (*moves)[i];
                bestValue = value;
            }
        }
        end = clock();

        printf("Minimax search with alpha-beta took %f seconds.\n", 
               ((float)end - (float)start) / CLOCKS_PER_SEC);

        return bestValue;
    }
Beispiel #15
0
int main()
{
    for (int i = 0; i < 1000; i++)
    {
        int randSeed = i + time(NULL);

        gTotalNodes = 0;
        gLeafNodes = 0;
        gLeafNodesVisited = 0;
        gInteriorNodesVisited = 0;


        printf("Random Seed: %d\n", randSeed);
        srand(randSeed);

        printf("generating random tree of depth %d\n", g_depth);
        Node root = { 0 };
        START_TIMER
            genTree(&root, g_depth);
        STOP_TIMER
        printf("random tree generated, total nodes: %d, leaf nodes: %d, time: %g ms\n", gTotalNodes, gLeafNodes, gTime);

        float bestValAB = 0;
        float bestValET = 0;
        // search the best move using alpha-beta search
        printf("searching the tree using alpha-beta\n");
        START_TIMER
            bestValAB = alphabeta(&root, g_depth, g_depth, -INF, INF);
        STOP_TIMER
        printf("best move %d, score: %f\nnodes visited (leaves/interior/total): %d/%d/%d\n",
               root.bestChild, root.nodeVal, gLeafNodesVisited, gInteriorNodesVisited, gLeafNodesVisited + gInteriorNodesVisited);
        printf("time taken: %g\n", gTime);


        START_TIMER
            bestValET = exploreTree(&root, g_depth);
        STOP_TIMER
        printf("time taken: %g\n\n\n\n", gTime);

        if (bestValET != bestValAB)
        {
            printf("\n*Mismatch found!*\n");
            getchar();
        }

        freeTree(&root);
        //getchar();
    }
    getchar();

    return 0;
}
Beispiel #16
0
int printBestMoves(char* command){
	int depth;
	if (command[15] == 'b'){
		depth = computeBestDepth();
	}
	else{
		if (sscanf(command, "get_best_moves %d", &depth) != 1){
			return -1;
		}
	}
	
	LinkedList* allPossibleMoves = Board_getPossibleMoves(&board, turn);
	if (!allPossibleMoves){
		return 1;
	}
	int bestScore = INT_MIN;
	Iterator iterator;
	Iterator_init(&iterator, allPossibleMoves);
	LinkedList* bestMoves = PossibleMoveList_new();
	if (!bestMoves){
		PossibleMoveList_free(allPossibleMoves);
		return 1;
	}
	while(Iterator_hasNext(&iterator)){
		PossibleMove* currentMove = (PossibleMove*)Iterator_next(&iterator);
		int score = alphabeta(currentMove, depth, !turn, INT_MIN, INT_MAX);
		if (score > bestScore) {
			LinkedList_removeAll(bestMoves);
			if(LinkedList_add(bestMoves, currentMove)){
				LinkedList_removeAll(bestMoves);
				LinkedList_free(bestMoves);
				PossibleMoveList_free(allPossibleMoves);
				return 1;
			}
			bestScore = score;
		}
		else if (score == bestScore){
			if(LinkedList_add(bestMoves, currentMove)){
				LinkedList_removeAll(bestMoves);
				LinkedList_free(bestMoves);		
				PossibleMoveList_free(allPossibleMoves);
				return 1;
			}
		}
	}
	PossibleMoveList_print(bestMoves);
	LinkedList_removeAll(bestMoves);	//removes the nodes
	LinkedList_free(bestMoves);			//frees the struct
	LinkedList_free(allPossibleMoves);	//frees the moves
	return 0;
}
Beispiel #17
0
/**
*\brief Fonction alphabeta, qui est l'implémentation de l'algorithme alpha/beta.
*\details Cette fonction permet de générer l'arbre (détruit au fur et à mesure) de l'ensemble des coups et des
grilles possibles. Note pour l'utilisation pratique : Il faut alpha < beta, typiquement alpha = -INFINI et beta = INFINI.
*\return best de type \a int : c'est la valeur de la pondération affectée à une grille.
*/
int alphabeta(grid g, int alpha, int beta, int depth, token t) { 
	if(winner(g)==1||depth==1) {								
		return(pond(g)) ;
	}
	else {
		int best ;
		int column ;
		best = -INFINI ;
		for(column=1; column<=COLUMN_NB; column++) {
			if(g->heights[column-1]!=LINE_NB) {
				int val ;
				/* On joue le coup */
				put_token(g, column, t) ; 
				if(t==RED) {
					/* On alterne les coups */
					val = - alphabeta(g, -beta, -alpha, depth-1, YELLOW) ; 
				}
				if(t==YELLOW) {
					/* On alterne les coups */
					val = - alphabeta(g, -beta, -alpha, depth-1, RED) ; 
				}
				/* On annule le coup -> Parcours destructif de l'arbre */
				erase_token(g, column) ; 
				/* Coupures Alpha et Beta */
				if(val > best) { 
					best = val ;
					if(best > alpha) {
						alpha = best ;
						if(alpha >= beta) {
							return(best) ;
						}
					}
				}
			}
		}
		return(best) ;
	}
}
Beispiel #18
0
double OmokAI::alphabeta(std::shared_ptr<OmokNode> node, double alpha, double beta, size_t depth)
{
    size_t size = _game->getBoardSize();
    if (depth == _depth || node->state->isWin()) {
        return node->state->getScore();
        /*if (depth % 2 == 1) {
            return node->state->getBlackScore();
        }
        else {
            return -node->state->getWhiteScore();
        }*/
        
    } else {
        if (node->children.size() == 0) {
            buildChildren(node, depth);
        }
        if (depth % 2 == 0) { //maximizing
            for (auto &node : node->children) {
                double a = alphabeta(node.second, alpha, beta, depth + 1);
                alpha = a > alpha? a : alpha;
                if (beta <= alpha) { // beta cut-off
                    break;
                }
            }
            return alpha;
        } else { // minimizing
            for (auto &node : node->children) {
                double b = alphabeta(node.second, alpha, beta, depth + 1);
                beta = b < beta ? b : beta;
                if (beta <= alpha) { // beta cut-off
                    break;
                }
            }
            return beta;
        }
    }
}
Beispiel #19
0
int Board::alphabeta(int ply, int depth, int alpha, int beta)
{
  // Negascout
  
  int i, j, val;
  
  triangularLength[ply] = ply;
  if (depth == 0) return board.eval();
  
  moveBufLen[ply+1] = movegen(moveBufLen[ply]);
  for (i = moveBufLen[ply]; i < moveBufLen[ply+1]; i++)
  {
    makeMove(moveBuffer[i]);
    {
      if (!isOtherKingAttacked())
      {
        inodes++;
        if (!ply) displaySearchStats(3, ply, i);
        val = -alphabeta(ply+1, depth-1, -beta, -alpha);
        unmakeMove(moveBuffer[i]);
        if (val >= beta)
        {
          return beta;
        }
        if (val > alpha)
        {
          alpha = val;                                                                              // both sides want to maximize from *their* perspective
          triangularArray[ply][ply] = moveBuffer[i];                                  // save this move
          for (j = ply + 1; j < triangularLength[ply + 1]; j++)
          {
            triangularArray[ply][j] = triangularArray[ply+1][j];   // and append the latest best PV from deeper plies
          }
          triangularLength[ply] = triangularLength[ply + 1];
          if (!ply)
          {
            msStop = timer.getms();
            displaySearchStats(2, depth, val);
          }
        }
      }
      else unmakeMove(moveBuffer[i]);
    }
  }
  return alpha;
}
Beispiel #20
0
int minvalue(struct gamelist *nextstates, int alpha, int beta)
{

  int minstatevalue = 2;
  int minimaxvalue;

  while (nextstates != NULL)
	{
	  minimaxvalue = alphabeta(nextstates->state,alpha,beta);
	  if (minimaxvalue < minstatevalue) minstatevalue = minimaxvalue;
	  if (minstatevalue <= alpha) return minstatevalue;
	  if (beta > minstatevalue) beta = minstatevalue;

	  nextstates = nextstates->next;
	}

  return minstatevalue;

}
Beispiel #21
0
int maxvalue(struct gamelist *nextstates,int alpha, int beta)
{

  int maxstatevalue = -2;
  int minimaxvalue;

  while (nextstates != NULL)
	{
	  minimaxvalue = alphabeta(nextstates->state,alpha,beta);
	  if (minimaxvalue > maxstatevalue) maxstatevalue = minimaxvalue;
	  if (maxstatevalue >= beta) return maxstatevalue;
	  if (alpha < maxstatevalue) alpha = maxstatevalue;

	  nextstates = nextstates->next;
	}

  return maxstatevalue;

}
Beispiel #22
0
/*A problem found in alphabeta pruning is that once I get a 0 value for a certain MAX node (guaranteed draw) if any of the next nodes has a value of -1 alphabeta allocates it as a 0 value node. Although these children don't really affect the true value of father's alphabeta (as max node if there's a 0, it can't get less) it can happen that I have to count the number of winnning leaves and naturally I can't choose a path that seems 0 (draw) while it is indeed -1 (lose) so that I developed this function that returns the TRUE value of a certain node that normally is allocated as 0 but in reality can also be -1*/
static int TrueValue(NODE *T) {
	NODE *tmpSubTree; //temporarily to this function
	int valore;
	if ((tmpSubTree = (NODE*)malloc(sizeof(NODE))) == NULL) exit(0);

	tmpSubTree->depth = T->depth;
	tmpSubTree->i = T->i;
	tmpSubTree->j = T->j;
	tmpSubTree->leftchild = NULL;
	tmpSubTree->rightbrothers = NULL;
	tmpSubTree->player = T->player;
	tmpSubTree->value == (T->player == MAX) ? (-2) : (2);
	tmpSubTree->transboard = copyv(T->transboard);


	valore = alphabeta(&tmpSubTree, tmpSubTree->depth, -1, 1, tmpSubTree->player); //simply I recreate a sub-tree with the technique used to create the whole tree so that I get the TRUE value and I store it in the real tree
	DeleteTree(&tmpSubTree); //eventually I free tmpSubTree

	return (valore); //returns the TRUE value of that child
}
Beispiel #23
0
PossibleMove* getBestMove(){
	LinkedList* allPossibleMoves = Board_getPossibleMoves(&board, turn);
	if (!allPossibleMoves){
		return NULL;
	}
	int depth = getDepth();
	int bestScore = INT_MIN;
	PossibleMove* bestMove;
	Iterator iterator;
	Iterator_init(&iterator, allPossibleMoves);
	while(Iterator_hasNext(&iterator)){
		PossibleMove* currentMove = (PossibleMove*)Iterator_next(&iterator);
		int score = alphabeta(currentMove, depth, !turn, INT_MIN, INT_MAX);
		if (score > bestScore || (score == bestScore && rand()%2)) {
			bestScore = score;
			bestMove = currentMove;
		}
	}
	LinkedList_freeAllButOne(allPossibleMoves, bestMove);
	return bestMove;
}
Beispiel #24
0
void OmokAI::normalSearch()
{
    Position w = _game->getPreviousWhite();
    auto iter = _root->children.find(w);
    if (iter == _root->children.cend()) {
        _root->state->set(Piece::createWhite(w));
        _root->children.clear();
    } else {
        _root = iter->second;
    }

    double alpha = -std::numeric_limits<double>::infinity();
    double beta = std::numeric_limits<double>::infinity();

    std::shared_ptr<OmokNode> maxOmokNode;
    Position maxMove(-1, -1);

    if (!_root->state->isWin()) {
        if (_root->children.size() == 0) {
            buildChildren(_root, 0);
        }
        for (auto &node : _root->children) {
            double a = alphabeta(node.second, alpha, beta, 1);
            if (a > alpha) {
                alpha = a;
                maxOmokNode = node.second;
                maxMove = node.first;
            }
            if (beta <= alpha) { // beta cut-off
                break;
            }
        }

        assert(_game->isBlackTurn());
        _game->put(maxMove);
        assert(maxOmokNode);
        _root = maxOmokNode;
    }
    
}
Beispiel #25
0
float alphabeta(Node *node, int depth, int origDepth, float alpha, float beta)
{
    if (depth == 0)
    {
        gLeafNodesVisited++;

        // eval for even depths, -eval for odd depths
        if (origDepth % 2 == 0)
            return node->nodeVal;
        else
            return -node->nodeVal;
    }

    gInteriorNodesVisited++;

    // choose the best child
    int bestChild = 0;

    for (int i = 0; i < node->nChildren; i++)
    {
        float curScore = -alphabeta(&node->children[i], depth - 1, origDepth, -beta, -alpha);
        if (curScore >= beta)
        {
            return beta;
        }

        if (curScore > alpha)
        {
            alpha = curScore;
            bestChild = i;
        }
    }

    node->nodeVal = alpha;
    node->bestChild = bestChild;

    return alpha;

}
Beispiel #26
0
BNTField NextBestMove(BNTBoard board, BNTPlayer player, int lookahead)
{
	float score = player == BNTPlayerX ? -INFINITY : +INFINITY;
	float bestX = 0, bestY = 0;
	
	int movesCount = 0;
	BNTField moves[BOARD_SIZE * BOARD_SIZE];
	
	for (int x = 0; x < BOARD_SIZE; ++x)
	{
		for (int y = 0; y < BOARD_SIZE; ++y)
		{
			if (board[x][y] == BNTPlayerNone)
			{
				moves[movesCount] = BNTFieldMake(x, y);
				++movesCount;
			}
		}
	}
	
	//shuffle legal moves
	shuffle(moves, movesCount);
	
	for (int i = 0; i < movesCount; ++i)
	{
		BNTField f = moves[i];
		board[f.x][f.y] = player;
		float v = DEPTH_PENALTY * alphabeta(board, lookahead, -INFINITY, +INFINITY, OppositePlayer(player));
		board[f.x][f.y] = BNTPlayerNone;
		
		if ((player == BNTPlayerX ? v > score : v < score)) {
			score = v, bestX = f.x, bestY = f.y;
		}
	}
	
	return BNTFieldMake(bestX, bestY);
}
/**
 * Entry point for search
 *
 * Does iterative deepening and alpha/beta width handling, and
 * calls alpha/beta search
 */
void ABIDStrategy::searchBestMove()
{    
	int alpha = -15000, beta = 15000;
	int nalpha, nbeta, currentValue = 0;

	_pv.clear(_maxDepth);
	_currentBestMove.type = Move::none;
	_currentMaxDepth=1;

	/* iterative deepening loop */
	do {

		/* searches on same level with different alpha/beta windows */
		while(1) {

			nalpha = alpha, nbeta = beta;
			_inPV = (_pv[0].type != Move::none);

			if (_sc && _sc->verbose()) {
				char tmp[100];
				sprintf(tmp, "Alpha/Beta [%d;%d] with max depth %d", alpha, beta, _currentMaxDepth);
				_sc->substart(tmp);
			}

			currentValue = alphabeta(0, alpha, beta);

			/* stop searching if a win position is found */
			if (currentValue > 14900 || currentValue < -14900)
				_stopSearch = true;

			/* Don't break out if we haven't found a move */
			if (_currentBestMove.type == Move::none)
				_stopSearch = false;

			if (_stopSearch) break;

			/* if result is outside of current alpha/beta window,
			 * the search has to be rerun with widened alpha/beta
			 */
			if (currentValue <= nalpha) {
				alpha = -15000;
				if (beta<15000) beta = currentValue+1;
				continue;
			}
			if (currentValue >= nbeta) {
				if (alpha > -15000) alpha = currentValue-1;
				beta=15000;
				continue;
			}
			break;
		}

		/* Window in both directions cause of deepening */
		alpha = currentValue - 200, beta = currentValue + 200;

		if (_stopSearch) break;

		_currentMaxDepth++;
	}
	while(_currentMaxDepth <= _maxDepth);

	_bestMove = _currentBestMove;
}
/*
 * Alpha/Beta search
 *
 * - first, start with principal variation
 * - depending on depth, we only do depth search for some move types
 */
int ABIDStrategy::alphabeta(int depth, int alpha, int beta)
{
	int currentValue = -14999+depth, value;
	Move m;
	Move bestMove;
	MoveList list;
	bool depthPhase, doDepthSearch;
	int i=0;
	int movecounter =-1;
	int flag=0;

	/* We make a depth search for the following move types... */
	int maxType = (depth < _currentMaxDepth-1)  ? Move::maxMoveType :
		(depth < _currentMaxDepth)    ? Move::maxPushType :
		Move::maxOutType;

	_board->generateMoves(list);

	if (_sc && _sc->verbose()) {
		char tmp[100];
		sprintf(tmp, "Alpha/Beta [%d;%d], %d moves (%d depth)", alpha, beta,
				list.count(Move::none), list.count(maxType));
		_sc->startedNode(depth, tmp);
	}

	/* check for an old best move in principal variation */
	if (_inPV) {
		m = _pv[depth];

		if ((m.type != Move::none) &&
				(!list.isElement(m, 0, true)))
			m.type = Move::none;

		if (m.type == Move::none) _inPV = false;
	}

	// first, play all moves with depth search
	depthPhase = true;

	while (1) {

		pretty_print("movecounter", movecounter);
		movecounter++;
		// get next move
		if (m.type == Move::none) {
			if (depthPhase)
				depthPhase = list.getNext(m, maxType);
			if (!depthPhase)
				if (!list.getNext(m, Move::none)) break;
		}
		if((thread_rank == movecounter% num_threads) || (depth > 0))// we could start with a non-depth move from principal variation
		{
			doDepthSearch = depthPhase && (m.type <= maxType);

			_board->playMove(m);

			/* check for a win position first */
			if (!_board->isValid()) {

				/* Shorter path to win position is better */
				value = 14999-depth;
			}
			else {

				if (doDepthSearch) {
					/* opponent searches for its maximum; but we want the
					 * minimum: so change sign (for alpha/beta window too!)
					 */
					value = -alphabeta(depth+1, -beta, -alpha);
				}
				else {
					value = evaluate();
				}
			}

			_board->takeBack();

			/* best move so far? */
			if (value > currentValue) {
				currentValue = value;
				_pv.update(depth, m);

				if (_sc) _sc->foundBestMove(depth, m, currentValue);
				if (depth == 0)
					_currentBestMove = m;

				/* alpha/beta cut off or win position ... */
				if (currentValue>14900 || currentValue >= beta) {
					if (_sc) _sc->finishedNode(depth, _pv.chain(depth));
					flag = 1;
					break;
					//return currentValue;
				}

				/* maximize alpha */
				if (currentValue > alpha) alpha = currentValue;
			}
		}
		if (_stopSearch) break; // depthPhase=false;
		m.type = Move::none;
	}



	if(depth == 0){
		//all threads send value to thread 0
		if(thread_rank == 0)
		{
			Move *moves=NULL;
			Variation *PVs=NULL;
			int *eval_results;
			PVs=(Variation*)malloc((num_threads -1)*sizeof(Variation));
			moves=(Move*)malloc((num_threads -1)*sizeof(Move));
			eval_results=(int*)malloc((num_threads - 1)*sizeof(int));




			for(i=0;i<num_threads-1;i++)
			{		
				MPI_Status status;	
				MPI_Recv (&moves[i], sizeof(Move), MPI_BYTE, i+1 ,10, MPI_COMM_WORLD, &status);
				MPI_Recv (&PVs[i], sizeof(Variation), MPI_BYTE, i+1 ,10, MPI_COMM_WORLD, &status);
				MPI_Recv (&eval_results[i], 1, MPI_INT, i+1 ,10, MPI_COMM_WORLD, &status);
			}

			for(i=0;i<num_threads-1;i++)
			{
				if(eval_results[i] > currentValue)
				{
					currentValue = eval_results[i];
					_pv=PVs[i];
					_currentBestMove = moves [i];
				}

			}
			for(i=0;i<num_threads-1;i++)
			{
				MPI_Send(&_currentBestMove, sizeof(Move), MPI_BYTE, i+1 ,10, MPI_COMM_WORLD);
				MPI_Send(&_pv, sizeof(Variation), MPI_BYTE, i+1 ,10, MPI_COMM_WORLD);
				MPI_Send(&currentValue, 1, MPI_INT, i+1 ,10, MPI_COMM_WORLD);
			}
			pretty_print("thread_rank", thread_rank);

			free(PVs);
			free(moves);
			free(eval_results);
		}
		else
		{
			MPI_Status status;
			MPI_Send(&_currentBestMove, sizeof(Move), MPI_BYTE, 0 ,10, MPI_COMM_WORLD);
			MPI_Send(&_pv, sizeof(Variation), MPI_BYTE, 0 ,10, MPI_COMM_WORLD);
			MPI_Send(&currentValue, 1, MPI_INT, 0 ,10, MPI_COMM_WORLD);
			MPI_Recv(&_currentBestMove, sizeof(Move), MPI_BYTE, 0 ,10, MPI_COMM_WORLD, &status);
			MPI_Recv(&_pv, sizeof(Variation), MPI_BYTE, 0 ,10, MPI_COMM_WORLD, &status);
			MPI_Recv(&currentValue, 1, MPI_INT, 0 ,10, MPI_COMM_WORLD, &status);
		}	
	}

	if(!flag)
	if (_sc) _sc->finishedNode(depth, _pv.chain(depth));

	return currentValue;
}
Beispiel #29
0
void            test_game2()
{
    int             nlegmov;
    char            bestply2[10];
    float           tmpres;
    MOVE_LIST       movelist;

    string_execute_move("a2a4", w, b);
    string_execute_move("b8c6", w, b);
    string_execute_move("e2e3", w, b);
    string_execute_move("a8b8", w, b);
    string_execute_move("g1h3", w, b);
    string_execute_move("g8h6", w, b);
    string_execute_move("h3g5", w, b);
    string_execute_move("g7g6", w, b);
    string_execute_move("b2b3", w, b);
    string_execute_move("a7a6", w, b);
    string_execute_move("h2h3", w, b);
    string_execute_move("f7f6", w, b);
    string_execute_move("g5f3", w, b);
    string_execute_move("c6a7", w, b);
    string_execute_move("f3d4", w, b);
    string_execute_move("c7c5", w, b);
    string_execute_move("d4f3", w, b);
    string_execute_move("h8g8", w, b);
    string_execute_move("c2c4", w, b);
    string_execute_move("g6g5", w, b);
    string_execute_move("f3h2", w, b);
    string_execute_move("g5g4", w, b);
    string_execute_move("h2g4", w, b);
    string_execute_move("f6f5", w, b);
    string_execute_move("g4h6", w, b);
    string_execute_move("f8h6", w, b);
    string_execute_move("d1h5", w, b);
    string_execute_move("g8g6", w, b);
    string_execute_move("h5f5", w, b);
    string_execute_move("h6g7", w, b);
    string_execute_move("d2d4", w, b);
    string_execute_move("d7d6", w, b);
    string_execute_move("f5h5", w, b);
    string_execute_move("e8f8", w, b);
    string_execute_move("h5h7", w, b);
    string_execute_move("g6h6", w, b);
    string_execute_move("h7e4", w, b);
    string_execute_move("g7f6", w, b);
    string_execute_move("f1d3", w, b);
    string_execute_move("b8a8", w, b);
    string_execute_move("h1h2", w, b);
    string_execute_move("e7e6", w, b);
    string_execute_move("b1c3", w, b);
    string_execute_move("d8a5", w, b);
    string_execute_move("b3b4", w, b);
    string_execute_move("a5b4", w, b);
    string_execute_move("e1d2", w, b);
    string_execute_move("c5d4", w, b);

    white_leg_mov(w, b);

    crt_list(&movelist);
    nlegmov = push_leg_mov(w, &movelist);

    depthmax = STARTDPTH;

    tmpres = alphabeta(depthmax, -200, 200, -1, bestply2);

    printf("%s\n", bestply2);
}
Beispiel #30
0
void            test_game()
{
    int             nlegmov;
    char            bestply2[10];
    float           tmpres;
    MOVE_LIST       movelist;

    string_execute_move("d2d4", w, b);
    string_execute_move("e7e6", w, b);
    string_execute_move("c2c3", w, b);
    string_execute_move("d7d5", w, b);
    string_execute_move("g1h3", w, b);
    string_execute_move("d8f6", w, b);
    string_execute_move("c1g5", w, b);
    string_execute_move("f6f5", w, b);
    string_execute_move("d1d3", w, b);
    string_execute_move("f5d3", w, b);
    string_execute_move("e2d3", w, b);
    string_execute_move("f8d6", w, b);
    string_execute_move("b1d2", w, b);
    string_execute_move("f7f6", w, b);
    string_execute_move("g5e3", w, b);
    string_execute_move("c7c6", w, b);
    string_execute_move("h3g1", w, b);
    string_execute_move("b7b5", w, b);
    string_execute_move("b2b3", w, b);
    string_execute_move("c8d7", w, b);
    string_execute_move("h2h4", w, b);
    string_execute_move("g8e7", w, b);
    string_execute_move("f1e2", w, b);
    string_execute_move("e7f5", w, b);
    string_execute_move("e2g4", w, b);
    string_execute_move("f5e3", w, b);
    string_execute_move("f2e3", w, b);
    string_execute_move("h7h5", w, b);
    string_execute_move("g4h3", w, b);
    string_execute_move("d6g3", w, b);
    string_execute_move("e1e2", w, b);
    string_execute_move("g3h4", w, b);
    string_execute_move("h3e6", w, b);
    string_execute_move("d7e6", w, b);
    string_execute_move("h1h4", w, b);
    string_execute_move("g7g5", w, b);

    string_execute_move("h4h2", w, b);
    string_execute_move("h8h7", w, b);
    string_execute_move("a1f1", w, b);
    string_execute_move("h7f7", w, b);
    string_execute_move("h2h1", w, b);
    string_execute_move("e8f8", w, b);
    string_execute_move("b3b4", w, b);
    string_execute_move("a7a6", w, b);
    string_execute_move("e2f3", w, b);
    string_execute_move("b8d7", w, b);
    string_execute_move("h1h5", w, b);
    string_execute_move("a8a7", w, b);
    string_execute_move("a2a3", w, b);
    string_execute_move("e6f5", w, b);
    string_execute_move("f3g3", w, b);
    string_execute_move("f5d3", w, b);

    string_execute_move("f1f3", w, b);
    string_execute_move("g5g4", w, b);
    string_execute_move("g3g4", w, b);
    string_execute_move("f6f5", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("d7f6", w, b);
    string_execute_move("h5h8", w, b);
    string_execute_move("f8g7", w, b);
    string_execute_move("h8d8", w, b);
    string_execute_move("f6e4", w, b);
    string_execute_move("d2e4", w, b);
    string_execute_move("f5e4", w, b);
    string_execute_move("f3f7", w, b);
    string_execute_move("a7f7", w, b);
    string_execute_move("d8e8", w, b);
    string_execute_move("g7f6", w, b);
    string_execute_move("e8h8", w, b);
    string_execute_move("f7g7", w, b);
    string_execute_move("h8c8", w, b);
    string_execute_move("g7h7", w, b);

    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
    string_execute_move("g4h4", w, b);
    string_execute_move("g7h7", w, b);
    string_execute_move("h4g4", w, b);
    string_execute_move("h7g7", w, b);
/*ok     */
    string_execute_move("g4f4", w, b);
    string_execute_move("g7f7", w, b);
    string_execute_move("c8c6", w, b);
    string_execute_move("f6g7", w, b);
    string_execute_move("f4g5", w, b);
    string_execute_move("a6a5", w, b);
    string_execute_move("c6g6", w, b);
    string_execute_move("g7h8", w, b);
    string_execute_move("b4a5", w, b);
    string_execute_move("h8h7", w, b);
    string_execute_move("a5a6", w, b);
    string_execute_move("h7h8", w, b);
    string_execute_move("g2g4", w, b);
    string_execute_move("h8h7", w, b);
    string_execute_move("g6h6", w, b);
    string_execute_move("h7g8", w, b);
    string_execute_move("h6g6", w, b);
    string_execute_move("g8h8", w, b);
    string_execute_move("g5h5", w, b);
    string_execute_move("d3c4", w, b);

    string_execute_move("g4g5", w, b);
    string_execute_move("c4d3", w, b);
    string_execute_move("g6h6", w, b);
    string_execute_move("h8g8", w, b);
    string_execute_move("h6g6", w, b);
    string_execute_move("g8h8", w, b);
    string_execute_move("h5h4", w, b);
    string_execute_move("d3c4", w, b);
    string_execute_move("g6h6", w, b);
    string_execute_move("f7h7", w, b);
    string_execute_move("a6a7", w, b);

    black_leg_mov(w, b);

    crt_list(&movelist);
    nlegmov = push_leg_mov(b, &movelist);

    depthmax = STARTDPTH;

    tmpres = alphabeta(depthmax, -200, 200, 1, bestply2);

    printf("%s\n", bestply2);
}