Advertisement
Guest User

Untitled

a guest
May 30th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.50 KB | None | 0 0
  1. #include "../inc/minimax.hh"
  2.  
  3. int MiniMax::evaluate(Board& board, const Color& color)
  4. {
  5.     // Wycena
  6.     int value = 0, pawn_value = 0;
  7.  
  8.     // Wskaźnik na aktualnie oceniany pionek
  9.     Pawn* ptr = NULL;
  10.  
  11.     // Ilość pionków gracza
  12.     int player_pawns = 0;
  13.  
  14.     // Ilość pionków przeciwnika
  15.     int opponent_pawns = 0;
  16.  
  17.     // Przeglądamy całą planszę
  18.     for(int x = 0; x<TILES_COUNT; ++x)
  19.         for(int y = 0; y<TILES_COUNT; ++y)
  20.         {
  21.             // Jeżeli pionek na tym polu istnieje
  22.             ptr = board.getPawn(Vector(x, y));
  23.             if(ptr)
  24.             {
  25.                 // Zerujemy wartość tymczasową
  26.                 pawn_value = 0;
  27.  
  28.                 /*** DAMKA / PIONEK ***/
  29.                 if(ptr->isQueen()) pawn_value += 50;
  30.                 else pawn_value += 1;
  31.  
  32.                 /*** SPRAWDZAMY MOŻLIWE BICIA ***/
  33.                 if(board.isPossibleBeating(Vector(x, y))) pawn_value += 1000;
  34.  
  35.                 ///*** SPRAWDZAMY, CZY PIONEK MOŻE BYĆ ZBITY ***/
  36.                 //if(board.isEndangered(Vector(x, y))) pawn_value -= 10;
  37.  
  38.                 /*** ZASADA TRZECH OBSZARÓW ***/
  39.                 {
  40.                     // Jeżeli pionek należy do obszaru III (środkowego) -- waga 1
  41.                     if(((ptr->getPosition().x >= 3) && (ptr->getPosition().y >= 3)) &&
  42.                             ((ptr->getPosition().x < (TILES_COUNT-3)) && (ptr->getPosition().y < (TILES_COUNT-3))))
  43.                         pawn_value += 0; // więc nie ruszamy
  44.  
  45.                     // Jeżeli pionek należy do obszaru II -- waga 2
  46.                     else if(((ptr->getPosition().x >= 2) && (ptr->getPosition().y >= 2)) &&
  47.                             ((ptr->getPosition().x < (TILES_COUNT-2)) && (ptr->getPosition().y < (TILES_COUNT-2))))
  48.                         pawn_value += 100;
  49.  
  50.                     // Jeżeli pionek należy do obszaru I (skrajnego) -- waga 3
  51.                     else
  52.                         pawn_value += 500;
  53.  
  54.                 }
  55.  
  56.                 // Jeżeli NIE jest to pionek należący do gracza zdefiniowanego kolorem color
  57.                 // przemnażamy przez -1
  58.                 // Do tego zliczamy ilość pionków
  59.                 if(ptr->getColor() != color) { pawn_value *= -1; ++opponent_pawns; }
  60.                 else ++player_pawns;
  61.  
  62.                 // Dodajemy pawn_value do wyceny
  63.                 value += pawn_value;
  64.  
  65.  
  66.             }
  67.         }
  68.  
  69.  
  70.     // Jeżeli nie ma już pionków przeciwnika na planszy, zwracamy INF (gdyż jest to wygrana)
  71.     if(!opponent_pawns) return INF;
  72.  
  73.     // Jeżeli nie ma już pionków gracza na planszy, zwracamy -INF (przegrana)
  74.     if(!player_pawns) return -INF;
  75.  
  76.     // Zwracamy wycenę
  77.     return value;
  78. }
  79.  
  80. int MiniMax::alphabeta(Board board, int depth, int alpha, int beta, const Color& player, Movement& best_movement)
  81. {
  82.     // Jeżeli jest to liść, zwróć wartość funkcji heurystycznej
  83.     if(depth == DEPTH_MAX) return evaluate(board, player);
  84.  
  85.     // Jeżeli jest teraz ruch przeciwnika
  86.     if(player != AI_COLOR)
  87.     {
  88.         // Dla każdego potomka
  89.         for(auto& m: board.getPossibleGlobalMovements(player))
  90.         {
  91.             // Tworzymy nowy stan gry
  92.             Board new_board(board);
  93.  
  94.             // Wykonujemy ruch
  95.             new_board.movePawn(m);
  96.  
  97.             // Pobieramy wartość MIN (czyli gracz minimalizuje zysk AI) -- ruch AI
  98.             beta = std::min(beta, alphabeta(new_board, depth+1, alpha, beta, AI_COLOR, best_movement));
  99.  
  100.             // Jeżeli alfa >= beta odcinamy gałąź alfa
  101.             if(alpha >= beta) break;
  102.         }
  103.  
  104.         // Zwracamy wartość najlepszego ruchu
  105.         return beta;
  106.     }
  107.  
  108.     // Jeśli jest teraz ruch AI
  109.     else
  110.     {
  111.         // Dla każdego potomka
  112.         for(auto& m: board.getPossibleGlobalMovements(player))
  113.         {
  114.             // Tworzymy nowy stan gry
  115.             Board new_board(board);
  116.  
  117.             // Wykonujemy ruch
  118.             new_board.movePawn(m);
  119.  
  120.             // Pobieramy wartość stanu gry dla potomka (ruch przeciwnika)
  121.             int temp = alphabeta(new_board, depth+1, alpha, beta, getOpposedColor(AI_COLOR), best_movement);
  122.  
  123.             // Liczymy MAX (czyli AI maksymalizuje własny zysk)
  124.             // oraz jednocześnie warunek najlepszego ruchu
  125.             if(temp > alpha)
  126.             {
  127.                 // Jeśli temp > alpha, przypisujemy alpha a= temp (z definicji MAX(a, b))
  128.                 alpha = temp;
  129.  
  130.                 // Na poziomie rekurencji = 1 zwracamy w referencji
  131.                 // ruch, za pomocą którego doszliśmy do najlepszego rozwiązania według strategii minimax
  132.                 if(depth == 0) best_movement = m;
  133.             }
  134.  
  135.             // Jeżeli ruch najlepszy nie został wybrany, to wybieramy ruch, który nie jest optymalny, ale jest...
  136.             //else if((depth == 0) && (best_movement == Movement())) best_movement = m;
  137.  
  138.             // Jeżeli alfa >= beta odcinamy gałąź beta
  139.             if(alpha >= beta) break;
  140.  
  141.         }
  142.  
  143.         // Zwracamy wartość najlepszego ruchu
  144.         return alpha;
  145.     }
  146. }
  147.  
  148. Movement MiniMax::getBestMovement(Board board)
  149. {
  150.     // Tworzymy bufor na ruch
  151.     Movement best_movement;
  152.  
  153.     // Pobieramy algorytmem minimax z cięciem alfa-beta najlepszy ruch
  154.     alphabeta(board, 0, -INF, INF, AI_COLOR, best_movement);
  155.  
  156.     // Zwracamy najlepszy ruch
  157.     return best_movement;
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement