DarshanScripts commited on
Commit
1df56e4
·
verified ·
1 Parent(s): 5862e39

Upload stratego\env\custom_env.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. stratego//env//custom_env.py +144 -0
stratego//env//custom_env.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+
3
+ class CustomStrategoEnv:
4
+ """
5
+ Versiune simplificată de Stratego cu simboluri reale.
6
+ Tabla se poate redimensiona, iar piesele sunt distribuite automat.
7
+ """
8
+
9
+ def __init__(self, env_id="Stratego-v0", board_size=10, **kwargs):
10
+ self.env_id = env_id
11
+ self.board_size = board_size
12
+ self.turn = 0
13
+ self.done = False
14
+ self.players = [0, 1]
15
+ self.symbols = ["A", "B"]
16
+ self.board = []
17
+ self.reset()
18
+
19
+ # ---------------------- BOARD SETUP ----------------------
20
+ def _generate_board(self):
21
+ n = self.board_size
22
+ board = [["." for _ in range(n)] for _ in range(n)]
23
+
24
+ # Lista de piese tipice Stratego
25
+ piece_types = ["BM", "FL", "MN", "SG", "LT", "CP", "MJ", "SP", "GN", "CL"]
26
+
27
+ # numărul de piese per jucător crește odată cu dimensiunea tablei
28
+ num_pieces = max(6, n * n // 6)
29
+
30
+ # selectăm piese aleatoriu, cu repetiție
31
+ p0_pieces = [random.choice(piece_types) for _ in range(num_pieces)]
32
+ p1_pieces = [random.choice(piece_types) for _ in range(num_pieces)]
33
+
34
+ # jumătate superioară — player 0
35
+ for i in range(num_pieces):
36
+ row = i // n
37
+ col = i % n
38
+ if row < n // 2:
39
+ board[row][col] = p0_pieces[i]
40
+
41
+ # jumătate inferioară — player 1
42
+ for i in range(num_pieces):
43
+ row = n - 1 - (i // n)
44
+ col = i % n
45
+ if row >= n // 2:
46
+ board[row][col] = p1_pieces[i]
47
+
48
+ # adăugăm câteva lacuri (~) dacă tabla e suficient de mare
49
+ if n >= 8:
50
+ for i in range(n // 3, n // 3 + 2):
51
+ for j in range(n // 3, n // 3 + 2):
52
+ board[i][j] = "~"
53
+ board[n - i - 1][n - j - 1] = "~"
54
+
55
+ return board
56
+
57
+ # ---------------------- API METHODS ----------------------
58
+ def reset(self, num_players=2):
59
+ self.turn = 0
60
+ self.done = False
61
+ self.board = self._generate_board()
62
+ return self.get_observation()
63
+
64
+ def get_observation(self):
65
+ player = self.turn % 2
66
+ board_text = "\n".join([" ".join(row) for row in self.board])
67
+ legal_moves = self._get_legal_moves(player)
68
+ obs = (
69
+ f"Player {player} ({self.symbols[player]}) turn.\n"
70
+ f"Board:\n{board_text}\n\n"
71
+ f"Legal moves:\n{', '.join(legal_moves)}"
72
+ )
73
+ return player, obs
74
+
75
+ def step(self, action):
76
+ moved = self._apply_move(action)
77
+ if not moved:
78
+ pass # dacă mutarea e invalidă, doar trecem rândul
79
+
80
+ # verificăm dacă un jucător mai are piese
81
+ half = self.board_size // 2
82
+ top_pieces = sum(cell not in [".", "~"] for row in self.board[:half] for cell in row)
83
+ bottom_pieces = sum(cell not in [".", "~"] for row in self.board[half:] for cell in row)
84
+
85
+ if top_pieces == 0 or bottom_pieces == 0:
86
+ self.done = True
87
+
88
+ self.turn += 1
89
+ return self.done, {}
90
+
91
+ def close(self):
92
+ rewards = {0: 0, 1: 0}
93
+ info = {"board_size": self.board_size}
94
+ return rewards, info
95
+
96
+ # ---------------------- MOVE LOGIC ----------------------
97
+ def _get_legal_moves(self, player):
98
+ n = self.board_size
99
+ moves = []
100
+ sym = self.symbols[player]
101
+ dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
102
+
103
+ for i in range(n):
104
+ for j in range(n):
105
+ cell = self.board[i][j]
106
+ if cell != "." and cell != "~": # piesă reală
107
+ for di, dj in dirs:
108
+ ni, nj = i + di, j + dj
109
+ if 0 <= ni < n and 0 <= nj < n:
110
+ if self.board[ni][nj] == ".":
111
+ move = f"{self._pos_to_label(i, j)} {self._pos_to_label(ni, nj)}"
112
+ moves.append(move)
113
+ random.shuffle(moves)
114
+ return moves[:10]
115
+
116
+ def _apply_move(self, action):
117
+ parts = action.strip().split()
118
+ if len(parts) != 2:
119
+ return False
120
+ src_label, dst_label = parts
121
+ si, sj = self._label_to_pos(src_label)
122
+ di, dj = self._label_to_pos(dst_label)
123
+
124
+ n = self.board_size
125
+ if not (0 <= si < n and 0 <= sj < n and 0 <= di < n and 0 <= dj < n):
126
+ return False
127
+ if self.board[si][sj] in [".", "~"]:
128
+ return False
129
+
130
+ self.board[di][dj] = self.board[si][sj]
131
+ self.board[si][sj] = "."
132
+ return True
133
+
134
+ # ---------------------- UTILS ----------------------
135
+ def _pos_to_label(self, i, j):
136
+ return f"{chr(65 + i)}{j}"
137
+
138
+ def _label_to_pos(self, label):
139
+ try:
140
+ row = ord(label[0].upper()) - 65
141
+ col = int(label[1:])
142
+ return row, col
143
+ except Exception:
144
+ return -1, -1