DarshanScripts commited on
Commit
324748b
·
verified ·
1 Parent(s): e67e8d3

Upload stratego/game_logger.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. stratego/game_logger.py +134 -0
stratego/game_logger.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # stratego/game_logger.py
2
+ from __future__ import annotations
3
+ import csv, os, datetime
4
+ from typing import Optional, List
5
+
6
+
7
+ class GameLogger:
8
+ """
9
+ One CSV file per game stored in logs/games/ folder.
10
+
11
+ CSV Fields for training:
12
+ - turn, player, model_name
13
+ - move, from_pos, to_pos, piece_type
14
+ - board_state, available_moves, move_direction
15
+ - target_piece, battle_outcome
16
+ - prompt_name
17
+ - game_winner, game_result (filled post-game)
18
+ """
19
+ def __init__(self, out_dir: str, game_id: Optional[str] = None, prompt_name: str = "", game_type: str = "standard", board_size: int = 10):
20
+ # Create games subfolder
21
+ games_dir = os.path.join(out_dir, "games")
22
+ os.makedirs(games_dir, exist_ok=True)
23
+
24
+ ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
25
+ self.game_id = game_id or ts
26
+ self.prompt_name = prompt_name
27
+ self.game_type = game_type # "standard", "duel", or "custom"
28
+ self.board_size = board_size
29
+ self.path = os.path.join(games_dir, f"{self.game_id}.csv")
30
+ self._f = open(self.path, "w", newline="", encoding="utf-8")
31
+ # Use full set of fields up-front so partial logs are readable during play
32
+ self._writer = csv.DictWriter(
33
+ self._f,
34
+ fieldnames=[
35
+ "turn", "player", "model_name",
36
+ "move", "from_pos", "to_pos", "piece_type",
37
+ "board_state", "available_moves", "move_direction",
38
+ "target_piece", "battle_outcome",
39
+ "prompt_name", "game_type", "board_size",
40
+ "outcome",
41
+ ],
42
+ quoting=csv.QUOTE_MINIMAL,
43
+ escapechar="\\"
44
+ )
45
+ self._writer.writeheader()
46
+ self._rows: List[dict] = [] # Store rows for post-game update
47
+
48
+ def log_move(
49
+ self,
50
+ turn: int,
51
+ player: int,
52
+ move: str,
53
+ model_name: str = "",
54
+ src: str = "",
55
+ dst: str = "",
56
+ piece_type: str = "",
57
+ outcome: str = "",
58
+ board_state: str = "",
59
+ available_moves: str = "",
60
+ move_direction: str = "",
61
+ target_piece: str = "",
62
+ battle_outcome: str = "",
63
+ ):
64
+ row = {
65
+ "turn": turn,
66
+ "player": player,
67
+ "model_name": model_name,
68
+ "move": move,
69
+ "from_pos": src,
70
+ "to_pos": dst,
71
+ "piece_type": piece_type,
72
+ "board_state": board_state,
73
+ "available_moves": available_moves,
74
+ "move_direction": move_direction,
75
+ "target_piece": target_piece,
76
+ "battle_outcome": battle_outcome,
77
+ "prompt_name": self.prompt_name,
78
+ "game_type": self.game_type,
79
+ "board_size": self.board_size,
80
+ "outcome": outcome,
81
+ }
82
+
83
+ # Store row in memory for post-game rewrite and write immediately to the file
84
+ self._rows.append(row)
85
+ try:
86
+ self._writer.writerow(row)
87
+ self._f.flush()
88
+ except Exception:
89
+ # If writing fails, keep going (file may be temporarily locked)
90
+ pass
91
+
92
+ def finalize_game(self, winner: Optional[int], game_result: str = ""):
93
+ """
94
+ Rewrite CSV with game outcome in every row.
95
+ This allows each move to be labeled with the game result for training.
96
+ """
97
+ self._f.close()
98
+
99
+ # Update all rows with game outcome
100
+ winner_str = str(winner) if winner is not None else "draw"
101
+ for row in self._rows:
102
+ row["game_winner"] = winner_str
103
+ row["game_result"] = game_result
104
+
105
+ # Rewrite the file with updated data
106
+ with open(self.path, "w", newline="", encoding="utf-8") as f:
107
+ writer = csv.DictWriter(
108
+ f,
109
+ fieldnames=[
110
+ "turn", "player", "model_name",
111
+ "move", "from_pos", "to_pos", "piece_type",
112
+ "board_state", "available_moves", "move_direction",
113
+ "target_piece", "battle_outcome",
114
+ "prompt_name", "game_type", "board_size",
115
+ "outcome", "game_winner", "game_result",
116
+ ],
117
+ quoting=csv.QUOTE_MINIMAL,
118
+ escapechar="\\"
119
+ )
120
+ writer.writeheader()
121
+ writer.writerows(self._rows)
122
+
123
+ def close(self):
124
+ try:
125
+ self._f.close()
126
+ except Exception:
127
+ pass
128
+
129
+ def __enter__(self):
130
+ return self
131
+
132
+ def __exit__(self, exc_type, exc_val, exc_tb):
133
+ self.close()
134
+ return False