Esempio n. 1
0
int NegaMax::negaMax(int depth, bool is_white_turn)
{
    int score = -EVAL_MAX;
    int maxscore = -EVAL_MAX;
	// 叶子节点  评估返回
    if(depth <= 0)
        return _evaluator.Evaluate(_chessboard, is_white_turn);

	// 非叶子节点 游戏结束 返回评估值
	if (_evaluator.IsGameOver(_chessboard, is_white_turn, score))
		return score;
	ChessType cur_chess = is_white_turn ? CT_WHITE : CT_BLACK;
    int count = _move_generator.GenAllPossibleMove(_chessboard, depth);
    for (int i=0; i<count; i++)
    {
        assert(_move_generator.MakeMove(_chessboard, depth, i, cur_chess));
        score = -negaMax(depth-1, !is_white_turn);
        if(score > maxscore)
        {
            maxscore = score;
            if(depth == _search_depth)
                _bestmove = _move_generator.GetMovement(depth, i);
        }
        assert(_move_generator.UnMakeMove(_chessboard, depth, i));
    }
	return maxscore;
}
Esempio n. 2
0
float negaMax(Node *node, int depth, int origDepth)
{
    if (depth == 0)
    {
        // eval for even depths, -eval for odd depths
        if (origDepth % 2 == 0)
            return node->nodeVal;
        else
            return -node->nodeVal;
    }

    // choose the best child
    float bestScore = -INF;
    int bestChild = 0;

    for (int i = 0; i < node->nChildren; i++)
    {
        float curScore = -negaMax(&node->children[i], depth - 1, origDepth);
        if (curScore > bestScore)
        {
            bestScore = curScore;
            bestChild = i;
        }
    }

    node->nodeVal = bestScore;
    node->bestChild = bestChild;

    return bestScore;
}
Esempio n. 3
0
/** Un exemplu de functie de gandire care foloseste rezultatele furnizate de
 * o abordare negaMax exhaustiva. */
XOBoard negaMaxThink(XOBoard::Player player, XOBoard board)
{
  /* La inceput, consideram alpha -8 si beta 8. Cu alte cuvinte, daca tabla ar
   * fi plina de marcajele oponentului, el ar castiga 3 linii, 3 coloane si 2
   * diagonale (deci eu n-am cum sa fac mai rau de -8). Similar, din ce stiu eu
   * pana acum, oponentul n-are cum sa ma forteze sa joc in vreun fel, deci
   * consider ca as putea sa castig, ipotetic, pana la 8 (beta).
   */
  return (negaMax(player, board, -INF, +INF)).second;
}
Esempio n. 4
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;
}
Esempio n. 5
0
int ChessBoard::negaMax(int depth, int& mv)
{
    if (depth==0)
    {
        return m_sdPlayer?m_vlBlack - m_vlRed:m_vlRed - m_vlBlack;
    }
    m_searchCallTimes++;
    int best = INT_MIN;
    Moves mvs;
    generateMoves(mvs);
    for(int i=0; i<mvs.count(); i++)
    {
        int oldVal = m_vlBlack - m_vlRed;
        int pcCapture;
        //qDebug()<<mvString(mvs[i]);
        if (makeMove(mvs[i], pcCapture))
        {
            int temp_mv;
            int val = -1 * negaMax(depth-1, temp_mv);

            if (temp_mv)
            {
                //qDebug()<<mvString(temp_mv)<<" 评分"<<val;
            }
            if (val>best)
            {
               best = val;
               mv = mvs[i];
            }
            undoMakeMove(mvs[i], pcCapture);
            //qDebug()<<"UndoMakeMove";
        }

        int newVal = m_vlBlack - m_vlRed;
        Q_ASSERT(oldVal==newVal);
    }
    return best;
}
Esempio n. 6
0
bool NegaMax::searchAGoodMove(bool is_white_turn, Movement& bestmove)
{
    negaMax(_search_depth, is_white_turn);
	bestmove = _bestmove;
	return true;
}
Esempio n. 7
0
/** Puteti folosi functia negaMax pentru a implementa un AI pe baza de negaMAX.
 *
 * Functia primeste ca parametri:
 * 
 * player = Jucatorul care trebuie sa mute in continuare (identitatea
 *          calculatorului care gandeste cu aceasta functie).
 *           Valorile posibile sunt { XOBoard::PlayerX, XOBoard::PlayerO }
 *
 * board = Tabla pe care o vede jucatorul care trebuie sa mute in continuare.
 *
 * alpha = Inseamna ca player a gasit deja o cale prin care pot sa termin
 *         jocul cu un scor cel putin egal cu alpha.
 *
 * beta = Inseamna ca OPPONENT(player) a gasit o cale prin care sa-l forteze pe
 *        player sa termine jocul cu un scor cel mult egal cu beta (cu alte
 *        cuvinte daca player gaseste o modalitate sa castige mai mult de beta,
 *        cel mai probabil analizeaza un scenariu nerealist in care a presupus
 *        ca OPPONENT(player) a fost prost la un moment dat si a facut o
 *        greseala.
 */
std::pair<int, XOBoard> negaMax(XOBoard::Player player,
                                XOBoard board,
                                int alpha,
                                int beta)
{
  /* Daca s-a terminat jocul, scorul este cel raportat. */
  if (board.game_over()) {
    int myScore = board.get_score(player) - board.get_score(OPPONENT(player));
    return std::pair<int, XOBoard>(myScore, board);
  }

  /* Generam lista de expansiuni ale tablei (toate mutarile viitoare). */
  std::vector<XOBoard> expansions;
  for (unsigned int i = 0; i < 3; ++i) {
    for (unsigned int j = 0; j < 3; ++j) {
      if (board.get(i, j) == '_') {
        board.put(player, i, j);
        expansions.push_back(board);
        board.erase(i, j);
      }
    }
  }

  /* Verificam care este mutarea cea mai inteleapta. */
  XOBoard nextMove;
  for (unsigned int i = 0; i < expansions.size(); ++i) {
    /* Fiindca urmatorul nivel de negaMax este privit din partea oponentului,
     * cand apelez functia trebuie sa neg pe alfa si sa i-l servesc drept
     * beta pentru ca asta inseamna ca il "avertizez" ca nu sunt fraier si ca
     * deja stiu un mod prin care el nu poate sa faca mai mult decat -alpha.
     *
     * Pe de alta parte, desi eu il limitez pe el superior, din punct de vedere
     * inferior nu am nici un motiv sa-l limitez, asa ca ii voi servi un alpha
     * egal cu -INF (nu stiu cat de prost poate el sa joace, n-am cum sa-mi dau
     * seama).
     */

    /* Acum ne gandim cum s-ar descurca el in situatia asta. */
    std::pair<int, XOBoard> outcome = negaMax(
        OPPONENT(player), expansions[i], -INF, -alpha);

    /* Vedem ce miscare a reusit sa scoata el in conditiile date. */
    int myScore = -outcome.first;

    /* Analizam jocul din perspectiva taierii alfa-beta. */
    if (myScore > beta) {
      /* Inseamna ca asta e un scenariu in care el ar fi facut o greseala. Noi
       * stim ca el nu e prost, asa ca din moment ce a gasit deja mai sus in
       * arbore o modalitate prin care sa ma faca sa termin jocul cu cel mult
       * beta, n-o sa joace in asa fel incat sa ma puna pe mine in situatia
       * asta de acum. Aplicam deci, taierea beta. */
      return std::pair<int, XOBoard>(beta, nextMove);
    } else if (myScore > alpha) {
      /* Inseamna ca tocmai am gasit o miscare prin care eu sa castig la sigur
       * mai mult decat stiam inainte ca pot sa castig (daca vreti, un fel de
       * plan "la sigur" mai bun).
       */
      alpha = myScore;
      nextMove = expansions[i];
    }
  }

  /* Raportam mutarea aleasa ca fiind cea mai buna. */
  return std::pair<int, XOBoard>(alpha, nextMove);
}