|
1 | 1 | import json |
| 2 | +import re |
2 | 3 | import shlex |
3 | 4 | import subprocess |
4 | 5 | from collections import Counter |
|
13 | 14 | "js": ["function robot(state, unit) {"], |
14 | 15 | "py": ["def robot(state, unit):", "def robot(state: State, unit: Obj)"], |
15 | 16 | } |
| 17 | +# Recognizes a valid `robot(state, unit)` entry point regardless of type annotations, return |
| 18 | +# hints, or extra whitespace (e.g. `def robot(state, unit) -> Action:` or |
| 19 | +# `def robot(state: State, unit: Obj) -> Optional[Action]:`). The MAP_EXT_TO_HEADER strings |
| 20 | +# above stay as the human-readable examples shown in the validation error message. |
| 21 | +MAP_EXT_TO_SIGNATURE_RE = { |
| 22 | + "js": re.compile(r"function\s+robot\s*\(\s*state\b[^)]*,\s*unit\b[^)]*\)"), |
| 23 | + "py": re.compile(r"def\s+robot\s*\(\s*state\b[^)]*,\s*unit\b[^)]*\)"), |
| 24 | +} |
16 | 25 | ROBOTRUMBLE_HIDDEN_EXEC = ".codeclash_exec" |
17 | 26 |
|
18 | 27 |
|
@@ -155,10 +164,10 @@ def validate_code(self, agent: Player) -> tuple[bool, str | None]: |
155 | 164 | return False, "There should be a `robot.js` or `robot.py` file" |
156 | 165 | agent.environment.execute(f'echo "robot.{ext}" > {ROBOTRUMBLE_HIDDEN_EXEC}') |
157 | 166 |
|
158 | | - # Check that the robot function is defined |
159 | | - if not any( |
160 | | - [header in agent.environment.execute(f"cat robot.{ext}")["output"] for header in MAP_EXT_TO_HEADER[ext]] |
161 | | - ): |
| 167 | + # Check that the robot function is defined. Match on a signature regex (tolerant of type |
| 168 | + # annotations, return hints, and whitespace) rather than an exact substring, so a valid |
| 169 | + # entry point like `def robot(state, unit) -> Action:` is not spuriously rejected. |
| 170 | + if not MAP_EXT_TO_SIGNATURE_RE[ext].search(agent.environment.execute(f"cat robot.{ext}")["output"]): |
162 | 171 | headers = "\n- ".join(MAP_EXT_TO_HEADER[ext]) |
163 | 172 | return ( |
164 | 173 | False, |
|
0 commit comments