Advertisement
Hinski2

Untitled

Jun 5th, 2024
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement