Replace eighth battle map with hand-painted asset

This commit is contained in:
2026-07-09 14:59:36 +09:00
parent 56e73117f6
commit 4482a7e17a
7 changed files with 83 additions and 101 deletions

View File

@@ -82,6 +82,15 @@ MAP_CONFIGS = {
"before": BATTLE_IMAGE_DIR / "seventh-battle-map.svg",
"seed": 240764,
},
"eighth": {
"slug": "eighth-battle-map",
"terrain_export": "eighthBattleMap",
"units_export": "eighthBattleUnits",
"ally_positions_export": "eighthBattleAllyPositions",
"out": BATTLE_IMAGE_DIR / "eighth-battle-map.webp",
"before": BATTLE_IMAGE_DIR / "eighth-battle-map.svg",
"seed": 240774,
},
}
@@ -132,12 +141,77 @@ def extract_balanced(text: str, start: int, open_char: str, close_char: str) ->
raise RuntimeError(f"Could not find balanced block starting at {start}")
def ts_condition_to_python(condition: str) -> str:
expression = condition.replace("\n", " ")
expression = expression.replace("!==", "!=")
expression = expression.replace("===", "==")
expression = expression.replace("&&", " and ")
expression = expression.replace("||", " or ")
expression = expression.replace("Math.floor", "math.floor")
return expression
def evaluate_terrain_factory(text: str, factory_name: str) -> list[list[str]]:
start = text.index(f"function {factory_name}")
brace_start = text.index("{", start)
block = extract_balanced(text, brace_start, "{", "}")
size_match = re.search(
r"Array\.from\(\{\s*length:\s*(\d+)\s*\}.*?Array\.from\(\{\s*length:\s*(\d+)\s*\}",
block,
re.S,
)
if not size_match:
raise RuntimeError(f"Could not read terrain dimensions from {factory_name}")
height = int(size_match.group(1))
width = int(size_match.group(2))
rules: list[tuple[str, str]] = []
cursor = 0
while True:
match = re.search(r"\bif\s*\(", block[cursor:])
if not match:
break
paren_start = cursor + match.end() - 1
condition_block = extract_balanced(block, paren_start, "(", ")")
brace_start = block.index("{", paren_start + len(condition_block))
body = extract_balanced(block, brace_start, "{", "}")
terrain_match = re.search(r"return\s+'([^']+)';", body)
if terrain_match:
rules.append((ts_condition_to_python(condition_block[1:-1]), terrain_match.group(1)))
cursor = brace_start + len(body)
returns = re.findall(r"return\s+'([^']+)';", block)
if not returns:
raise RuntimeError(f"Could not read terrain fallback from {factory_name}")
fallback = returns[-1]
terrain: list[list[str]] = []
for y in range(height):
row: list[str] = []
for x in range(width):
tile = fallback
for expression, terrain_type in rules:
if eval(expression, {"__builtins__": {}}, {"x": x, "y": y, "math": math}):
tile = terrain_type
break
row.append(tile)
terrain.append(row)
return terrain
def parse_battle_terrain(export_name: str) -> list[list[str]]:
text = SCENARIO_FILE.read_text(encoding="utf-8")
start = text.index(f"export const {export_name}")
terrain_key = text.index("terrain:", start)
bracket_start = text.index("[", terrain_key)
return ast.literal_eval(extract_balanced(text, bracket_start, "[", "]"))
brace_start = text.index("{", text.index("=", start))
map_block = extract_balanced(text, brace_start, "{", "}")
terrain_key = map_block.index("terrain:")
terrain_source = map_block[terrain_key + len("terrain:") :].lstrip()
if terrain_source.startswith("["):
return ast.literal_eval(extract_balanced(terrain_source, 0, "[", "]"))
factory_match = re.match(r"(\w+)\(\)", terrain_source)
if factory_match:
return evaluate_terrain_factory(text, factory_match.group(1))
raise RuntimeError(f"Unsupported terrain source for {export_name}")
def parse_export_array_source(export_name: str) -> str: