DarshanScripts commited on
Commit
a441863
·
verified ·
1 Parent(s): 51c8e36

Upload stratego/utils/parsing.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. stratego/utils/parsing.py +94 -0
stratego/utils/parsing.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from typing import Any, List, Sequence
3
+
4
+ MOVE_RE = re.compile(r"\[[A-J]\d\s+[A-J]\d\]")
5
+ # Allow leading spaces so 6x6 duel headers like " 0 1 2 3 4 5" are captured
6
+ BOARD_HEADER_RE = re.compile(r"^\s*0(\s+\d+)+$")
7
+ FORBID_LINE_RE = re.compile(r"^FORBIDDEN.*:$", re.IGNORECASE)
8
+
9
+ def _obs_to_str(observation: Any) -> str:
10
+
11
+ if isinstance(observation, str):
12
+ return observation
13
+
14
+ if isinstance(observation, Sequence):
15
+ parts: List[str] = []
16
+ for item in observation:
17
+ # (from_id, message, obs_type)
18
+ if isinstance(item, tuple) and len(item) >= 2 and isinstance(item[1], str):
19
+ parts.append(item[1])
20
+ else:
21
+ parts.append(str(item))
22
+ return "\n".join(parts)
23
+
24
+ return str(observation)
25
+
26
+ def extract_legal_moves(observation: Any) -> List[str]:
27
+ text = _obs_to_str(observation)
28
+ legal: List[str] = []
29
+ for line in text.splitlines():
30
+ if line.strip().startswith("Available Moves:"):
31
+ legal = MOVE_RE.findall(line)
32
+ return legal
33
+
34
+ def extract_forbidden(observation: Any) -> List[str]:
35
+ text = _obs_to_str(observation)
36
+ forb: List[str] = []
37
+ lines = text.splitlines()
38
+ for i, line in enumerate(lines):
39
+ if FORBID_LINE_RE.match(line.strip()):
40
+ j = i + 1
41
+ while j < len(lines) and "[" in lines[j]:
42
+ forb.extend(MOVE_RE.findall(lines[j]))
43
+ j += 1
44
+ break
45
+ return forb
46
+
47
+ def extract_board_block_lines(observation: str, size: int = 10) -> List[str]:
48
+ text = _obs_to_str(observation)
49
+ lines = text.splitlines()
50
+ header_idx = None
51
+ detected_size = size
52
+
53
+ for i in range(len(lines) - 1, -1, -1):
54
+ if BOARD_HEADER_RE.match(lines[i].strip()):
55
+ header_idx = i
56
+ # Auto-detect board size from header numbers (e.g., "0 1 2 3 4 5" -> size 6)
57
+ try:
58
+ nums = [int(n) for n in lines[i].split() if n.isdigit()]
59
+ if nums:
60
+ detected_size = max(nums) + 1
61
+ except Exception:
62
+ pass
63
+ break
64
+ if header_idx is None or header_idx + detected_size >= len(lines):
65
+ return []
66
+ return lines[header_idx: header_idx + detected_size + 1]
67
+
68
+ def slice_board_and_moves(observation: Any, size: int = 10) -> str:
69
+ text = _obs_to_str(observation)
70
+ lines = text.splitlines()
71
+ out: List[str] = []
72
+
73
+ block = extract_board_block_lines(text, size)
74
+ if block:
75
+ out.extend(block)
76
+
77
+ for i in range(len(lines) - 1, -1, -1):
78
+ if lines[i].strip().startswith("Available Moves:"):
79
+ out.append(lines[i])
80
+ break
81
+
82
+ for i in range(len(lines) - 1, -1, -1):
83
+ if FORBID_LINE_RE.match(lines[i].strip()):
84
+ out.append(lines[i])
85
+ k = i + 1
86
+ while k < len(lines) and "[" in lines[k]:
87
+ out.append(lines[k])
88
+ k += 1
89
+ break
90
+
91
+ return "\n".join(out).strip()
92
+
93
+ def strip_think(s: str) -> str:
94
+ return re.sub(r"<think>.*?</think>", "", s, flags=re.DOTALL | re.IGNORECASE).strip()