Hinski2

Untitled

Jun 5th, 2024
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.91 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. //enumy
  5. enum animal_enum {NO_ANIMAL, RAT, CAT, DOG, WOLF, JAGUAR, TIGER, LION, ELEPHANT};
  6. enum type_enum {FIELD, TRAP, RIVER, DEN_P1, DEN_P2};
  7. enum player_enum {P1, P2, NO_PLAYER};
  8.  
  9. //skróty
  10. #define fi first
  11. #define se second
  12.  
  13. //typy danych
  14. typedef pair<short, short> pss;
  15.  
  16. //consty
  17. const int inf = 1e9 + 7;
  18. const short n = 9, m = 7;
  19. const short tile_type[n][m] = {
  20.     {FIELD, FIELD, TRAP, DEN_P1, TRAP, FIELD, FIELD},
  21.     {FIELD, FIELD, FIELD, TRAP, FIELD, FIELD, FIELD},
  22.     {FIELD, FIELD, FIELD, FIELD, FIELD, FIELD, FIELD},
  23.     {FIELD, RIVER, RIVER, FIELD, RIVER, RIVER, FIELD},
  24.     {FIELD, RIVER, RIVER, FIELD, RIVER, RIVER, FIELD},
  25.     {FIELD, RIVER, RIVER, FIELD, RIVER, RIVER, FIELD},
  26.     {FIELD, FIELD, FIELD, FIELD, FIELD, FIELD, FIELD},
  27.     {FIELD, FIELD, FIELD, TRAP, FIELD, FIELD, FIELD},
  28.     {FIELD, FIELD, TRAP, DEN_P2, TRAP, FIELD, FIELD}};
  29. const pss shift[] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
  30.  
  31. //struktury
  32. struct pon {
  33.     animal_enum animal;
  34.     player_enum player;
  35. };
  36.  
  37. struct move_struct {
  38.     pss from;
  39.     pss shift;
  40. };
  41.  
  42. //funcje pomocjicze
  43. inline bool valid_coord(pss p);
  44.  
  45. //generowanie ziarna
  46. long seed() {
  47.     auto t=chrono::system_clock::now();
  48.     return std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch()).count();
  49. }
  50.  
  51. //klasa przedstawiająca stan gry
  52. class State {
  53. public:
  54.     short player;                       // który gracz wykonuje ruch
  55.     vector<vector<pon>> board;          // nasza plansza
  56.     vector<vector<pss>> animal_poss;    // dokładne pozycje zwierząt
  57.  
  58.     //konstruktor
  59.     State(short player, vector<vector<pon>> board, vector<vector<pss>> animal_poss) : player(player), board(board), animal_poss(animal_poss) {}
  60.  
  61.     //destruktor
  62.     ~State() {
  63.     }
  64.  
  65.     // wypisanie planszy
  66.     void print() {
  67.         for(int i = 0; i < n; i++) {
  68.             for(int j = 0; j < m; j++) {
  69.                 char c;
  70.                 if(board[i][j].animal == NO_ANIMAL) c = '.';
  71.                 else if(board[i][j].animal == RAT) c = 'R' | ((board[i][j].player == P1) * 32);
  72.                 else if(board[i][j].animal == CAT) c = 'C' | ((board[i][j].player == P1) * 32);
  73.                 else if(board[i][j].animal == DOG) c = 'D' | ((board[i][j].player == P1) * 32);
  74.                 else if(board[i][j].animal == WOLF) c = 'W' | ((board[i][j].player == P1) * 32);
  75.                 else if(board[i][j].animal == JAGUAR) c = 'J' | ((board[i][j].player == P1) * 32);
  76.                 else if(board[i][j].animal == TIGER) c = 'T' | ((board[i][j].player == P1) * 32);
  77.                 else if(board[i][j].animal == LION) c = 'L' | ((board[i][j].player == P1) * 32);
  78.                 else if(board[i][j].animal == ELEPHANT) c = 'E' | ((board[i][j].player == P1) * 32);
  79.  
  80.                 cout << c;
  81.             }
  82.             cout << endl;
  83.         }
  84.         cout << endl;
  85.     }
  86.  
  87.     vector<move_struct> generate_possible_moves() {
  88.         vector<move_struct> possible_moves;
  89.         pss my_den = (player == P1 ? make_pair(0, 3) : make_pair(8, 3));
  90.         for(int animal = 1; animal < 9; animal++) {
  91.             if(animal_poss[player][animal] == (pss) {-1, -1}) continue; //jeśli to zwierze jest zbite
  92.  
  93.             for(auto s: shift){
  94.                 pss poss = {animal_poss[player][animal].fi + s.fi, animal_poss[player][animal].se + s.se};
  95.  
  96.                 //początkowe / ogólne sprawdzenia
  97.                 if(!valid_coord(poss)) continue; //jeśli wychodzimy poza plansza
  98.                 if(board[poss.fi][poss.se].animal != NO_ANIMAL && board[poss.fi][poss.se].player == player) continue; // jeśli w poss znajduje się zwierze i to nasze zwierze
  99.                 if(poss == my_den) continue; //jeśli whodzimy do swojej jamy
  100.                 if(animal != RAT && animal != TIGER && animal != LION && tile_type[poss.fi][poss.se] == RIVER) continue; // tylko szczur może wchodzić do wody,a tygrys i lew mogą nad nią skakać
  101.  
  102.                 switch(animal) {
  103.                     case RAT:
  104.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > RAT && board[poss.fi][poss.se].animal != ELEPHANT) continue;
  105.                         if(tile_type[animal_poss[player][animal].fi][animal_poss[player][animal].se] == RIVER && tile_type[poss.fi][poss.se] != RIVER && board[poss.fi][poss.se].animal) continue; //jeśli szczur był w wodzi i z niej wychodzi to nie może bić
  106.                         possible_moves.push_back({animal_poss[player][animal], s});
  107.                         break;
  108.  
  109.                     case CAT:
  110.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > CAT) continue;
  111.                         possible_moves.push_back({animal_poss[player][animal], s});
  112.                         break;
  113.  
  114.                     case DOG:
  115.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > DOG) continue;
  116.                         possible_moves.push_back({animal_poss[player][animal], s});
  117.                         break;
  118.  
  119.                     case WOLF:
  120.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > WOLF) continue;
  121.                         possible_moves.push_back({animal_poss[player][animal], s});
  122.                         break;
  123.  
  124.                     case JAGUAR:
  125.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > JAGUAR) continue;
  126.                         possible_moves.push_back({animal_poss[player][animal], s});
  127.                         break;
  128.  
  129.                     case TIGER:
  130.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > TIGER) continue;
  131.                         if(tile_type[poss.fi][poss.se] == RIVER) poss = make_jump_over_water(poss, animal, s);
  132.                         if(poss == (pss){-1, -1}) continue;
  133.                         possible_moves.push_back({animal_poss[player][animal], s});
  134.                         break;
  135.  
  136.                     case LION:
  137.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > LION) continue;
  138.                         if(tile_type[poss.fi][poss.se] == RIVER) poss = make_jump_over_water(poss, animal, s);
  139.                         if(poss == (pss){-1, -1}) continue;
  140.                         possible_moves.push_back({animal_poss[player][animal], s});
  141.                         break;
  142.  
  143.                     case ELEPHANT:
  144.                         if(tile_type[poss.fi][poss.se] != TRAP && board[poss.fi][poss.se].animal > ELEPHANT) continue;
  145.                         possible_moves.push_back({animal_poss[player][animal], s});
  146.                         break;                        
  147.                 }
  148.             }
  149.         }
  150.  
  151.         return possible_moves;
  152.     }
  153.  
  154.     inline pss make_jump_over_water(pss poss, int animal, pss s) {
  155.         while(tile_type[poss.fi][poss.se] == RIVER){
  156.             if(board[poss.fi][poss.se].animal > 0){ //trafiliśmy na szczura
  157.                 poss = {-1, -1};
  158.                 return poss;
  159.             }
  160.  
  161.             poss.fi += s.fi, poss.se += s.se; //lecimy dalej jak Jordan
  162.         }
  163.  
  164.         if(board[poss.fi][poss.se].player == player || board[poss.fi][poss.se].animal > animal) poss = {-1, -1}; //przeskoczyliśmy wode ale wskakujemy na nasze inne zwierze albo na zwirze przeciwnika o większej mocy
  165.         return poss;
  166.     }
  167.  
  168.     void do_move(move_struct move){
  169.         short animal = board[move.from.fi][move.from.se].animal;
  170.         pss new_poss = {move.from.fi + move.shift.fi, move.from.se + move.shift.se};
  171.  
  172.         if(board[new_poss.fi][new_poss.se].animal) //zbijam zwierze przeciwnikowi
  173.             animal_poss[player ^ 1][board[new_poss.fi][new_poss.se].animal] = {-1, -1};
  174.  
  175.         board[move.from.fi][move.from.se] = {NO_ANIMAL, NO_PLAYER};                         // czyszcze stare pole
  176.         board[new_poss.fi][new_poss.se] = {(animal_enum) animal, (player_enum) player};     // ustawiam nowe pole
  177.         animal_poss[player][animal] = new_poss;                                             // zmieniam pozycje mojego zwierzaka w spisie pozycji zwierząt
  178.     }
  179.  
  180.     inline int no_of_animals(short p){
  181.         int ans = 0;
  182.         for(int i = 1; i < 9; i++)
  183.             if(animal_poss[p][i] != (pss) {-1, -1}) ans++;
  184.         return ans;
  185.     }
  186.  
  187.     int cnt_aval_pons(short p){
  188.         int cnt = 0;
  189.         for(int i = 1; i < 9; i++)
  190.             if(animal_poss[p][i] != (pss) {-1, -1}) cnt++;
  191.         return cnt;
  192.     }
  193.  
  194.     int evaluate(int noumber_of_games) {
  195.         player ^= 1;
  196.         int ans = 0;
  197.         for(int i = 0; i < noumber_of_games; i++) {
  198.             // robimy kopie
  199.             short copy_of_player = player;
  200.             vector<vector<pon>> copy_of_board = board;
  201.             vector<vector<pss>> copy_of_animal_poss = animal_poss;
  202.  
  203.             int cnt = 100;
  204.             int no_pons_p1 = cnt_aval_pons(P1), no_pons_p2 = cnt_aval_pons(P2); // liczba pionków przed robieniem ruchów
  205.             while(!game_over()) {
  206.                 if(!cnt) break;
  207.                 // generujemy wszystkie ruchy
  208.                 vector<move_struct> possible_moves = generate_possible_moves();
  209.  
  210.                 //wybieramy losowy
  211.                 move_struct chosen_move = possible_moves[rand() % possible_moves.size()];
  212.  
  213.                 // robimy ten ruch
  214.                 do_move(chosen_move);
  215.  
  216.                 // zminiamy state (pozostała tylko zmiana gracza)
  217.                 player ^= 1;
  218.                 cnt--;
  219.             }
  220.  
  221.             //doszliśmy do końca gry
  222.             ans += heura(cnt, no_pons_p1, no_pons_p2);
  223.             player = copy_of_player ^ 1;
  224.             board = copy_of_board; // przywracanie sptanu z przed ewaluacji
  225.             animal_poss = copy_of_animal_poss;
  226.         }
  227.  
  228.         return ans;
  229.     }
  230.  
  231.     int dist_from_edge(){
  232.         int ans = 0;
  233.         if(player == P1){
  234.             for(int i = 1; i < 9; i++)
  235.                 if(animal_poss[player][i] != (pss) {-1, -1})
  236.                     ans += animal_poss[player][i].fi;
  237.         }
  238.         else{
  239.             for(int i = 1; i < 9; i++)
  240.                 if(animal_poss[player][i] != (pss) {-1, -1})
  241.                     ans += 8 - animal_poss[player][i].fi;
  242.         }
  243.  
  244.         return ans;
  245.     }
  246.  
  247.     int heura(int cnt, int pons_before_p1, int pons_before_p2){
  248.         int ans = 0, pons_after_p1 = cnt_aval_pons(P1), pons_after_p2 = cnt_aval_pons(P2);
  249.         // ans += dist_from_edge() * (cnt / 10 + 1);
  250.  
  251.         if(player == P1){
  252.             ans += 10 * (pons_after_p1 - pons_before_p1);
  253.             ans -= 10 * (pons_after_p2 - pons_before_p2);
  254.         }
  255.         else{
  256.             ans -= 10 * (pons_after_p1 - pons_before_p1);
  257.             ans += 10 * (pons_after_p2 - pons_before_p2);
  258.         }
  259.  
  260.         ans += 1000 * dist_from_edge() * (cnt / 10 + 1);
  261.         return ans;
  262.     }
  263.  
  264.     inline bool game_over() {
  265.         if(board[0][3].animal || board[8][3].animal) return 1;
  266.         return generate_possible_moves().size() == 0;
  267.     }
  268. };
  269.  
  270. void make_random_move(State &s) {
  271.     vector<move_struct> possible_moves = s.generate_possible_moves();
  272.     int choosen_move = rand() % possible_moves.size();
  273.  
  274.     s.do_move(possible_moves[choosen_move]);
  275.     s.player ^= 1;
  276. }
  277.  
  278. void make_smart_move(State &s) {
  279.     vector<move_struct> possible_moves = s.generate_possible_moves();   // generacja wszystkich ruchów
  280.     pair<move_struct, int> best_move; best_move.se = -inf;              // najlepszy ruch
  281.  
  282.     int no_sym = 200 / possible_moves.size();                           // liczba symulacji dla każdego mov
  283.     for(auto move: possible_moves){
  284.         State next_s(s.player, s.board, s.animal_poss);
  285.         next_s.do_move(move);
  286.         int eval = next_s.evaluate(no_sym);
  287.         if(eval > best_move.se){
  288.             best_move.se = eval;
  289.             best_move.fi = move;
  290.         }
  291.     }
  292.     s.do_move(best_move.fi);
  293.     s.player ^= 1;
  294. }
  295.  
  296. int main(){
  297.     //ustawianie gry
  298.     srand(seed());
  299.     pss score = {0, 0};
  300.     for(int i = 0; i < 1000; i++){
  301.         vector<vector<pon>> init_board(n, vector<pon>(m, {NO_ANIMAL, NO_PLAYER}));
  302.         short player = P1;
  303.         init_board[0][0] = {LION, P1}, init_board[0][6] = {TIGER, P1}, init_board[1][1] = {DOG, P1}, init_board[1][5] = {CAT, P1}, init_board[2][0] = {RAT, P1}, init_board[2][2] = {JAGUAR, P1}, init_board[2][4] = {WOLF, P1}, init_board[2][6] = {ELEPHANT, P1};
  304.         init_board[8][6] = {LION, P2}, init_board[8][0] = {TIGER, P2}, init_board[7][5] = {DOG, P2}, init_board[7][1] = {CAT, P2}, init_board[6][6] = {RAT, P2}, init_board[6][4] = {JAGUAR, P2}, init_board[6][2] = {WOLF, P2}, init_board[6][0] = {ELEPHANT, P2};
  305.  
  306.         vector<vector<pss>> animal_poss(2, vector<pss>(9));
  307.         animal_poss[P1][LION] = {0, 0}, animal_poss[P1][TIGER] = {0, 6}, animal_poss[P1][DOG] = {1, 1}, animal_poss[P1][CAT] = {1, 5}, animal_poss[P1][RAT] = {2, 0}, animal_poss[P1][JAGUAR] = {2, 2}, animal_poss[P1][WOLF] = {2, 4}, animal_poss[P1][ELEPHANT] = {2, 6};
  308.         animal_poss[P2][LION] = {8, 6}, animal_poss[P2][TIGER] = {8, 0}, animal_poss[P2][DOG] = {7, 5}, animal_poss[P2][CAT] = {7, 1}, animal_poss[P2][RAT] = {6, 6}, animal_poss[P2][JAGUAR] = {6, 4}, animal_poss[P2][WOLF] = {6, 2}, animal_poss[P2][ELEPHANT] = {6, 0};
  309.  
  310.         State s(player, init_board, animal_poss);
  311.  
  312.         //graj dopuki ktoś nie wygrał
  313.         int move_type = 0; // jeśli 0 to mcts, 1 to random
  314.         while(!s.game_over()){
  315.             if(move_type == 0)
  316.                 make_smart_move(s);
  317.             else
  318.                 make_random_move(s);
  319.            
  320.             move_type ^= 1;
  321.             // s.print();
  322.         }
  323.  
  324.  
  325.         //zmiana wyniku
  326.         if(s.board[0][3].animal) score.se++;
  327.         else score.fi++;
  328.  
  329.         //wypisanie wyniku
  330.         cout << score.fi << ' ' << score.se << endl;
  331.     }
  332.  
  333. }
  334.  
  335. inline bool valid_coord(pss p){
  336.     return 0 <= p.fi && p.fi < n && 0 <= p.se && p.se < m;
  337. }
Add Comment
Please, Sign In to add comment