-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfetch_walkthroughs.py
More file actions
executable file
·154 lines (123 loc) · 4.48 KB
/
Copy pathfetch_walkthroughs.py
File metadata and controls
executable file
·154 lines (123 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
"""
Fetch human-generated walkthroughs from IF Archive and other sources
"""
import sys
import json
import requests
from pathlib import Path
from urllib.parse import urljoin
# IF Archive solutions index
IF_ARCHIVE_BASE = "https://www.ifarchive.org/if-archive/solutions/"
# Known solution files for our games
# Format: game_name: (solution_file, base_url)
# If base_url is None, uses IF_ARCHIVE_BASE
KNOWN_SOLUTIONS = {
# Infocom classics (in hints.many)
# Note: Most Infocom games are in the compiled hints.many file
# Individual solutions available via Infocom hints directory
"zork1": ("hints.many", None), # Contains Zork I-III
"zork2": ("hints.many", None),
"zork3": ("hints.many", None),
"enchanter": ("hints.many", None),
"planetfa": ("hints.many", None),
# Classic adventures
"advent": ("Adventure.sol", None),
"acheton": ("acheton.sol", None),
# Modern IF classics
"curses": ("Curses.sol", None),
"trinity": ("trinity.txt", "https://www.ifarchive.org/if-archive/infocom/hints/solutions/"),
"photopia": ("photopia.sol", None),
"shade": ("shade-walkthrough.txt", None),
"aisle": ("putpbaa.sol", None), # Covers Phone Booth and Aisle
"lostpig": ("LostPig.sol", None),
"anchor": ("anchor.sol", None),
"dreamhold": ("Dreamhold.zip", None), # ZIP file with walkthrough
"jigsaw": ("Jigsaw.sol", None),
"galatea": ("galatea-walkthrough.txt", None),
}
def fetch_solution(game_name: str, output_dir: Path) -> bool:
"""
Fetch walkthrough for a game from IF Archive
Returns True if successful
"""
if game_name not in KNOWN_SOLUTIONS:
print(f" No known solution file for {game_name}")
return False
solution_info = KNOWN_SOLUTIONS[game_name]
if isinstance(solution_info, tuple):
solution_file, base_url = solution_info
base_url = base_url or IF_ARCHIVE_BASE
else:
solution_file = solution_info
base_url = IF_ARCHIVE_BASE
url = urljoin(base_url, solution_file)
output_path = output_dir / f"{game_name}_human_walkthrough.txt"
if output_path.exists():
print(f" ✓ Already have {game_name}")
return True
try:
print(f" Downloading {solution_file}...")
response = requests.get(url, timeout=30)
response.raise_for_status()
output_path.write_text(response.text)
print(f" ✓ Saved {game_name} ({len(response.text)} bytes)")
return True
except requests.exceptions.RequestException as e:
print(f" ✗ Failed to fetch {game_name}: {e}")
return False
def parse_solution_txt(text: str) -> list:
"""
Parse a text walkthrough into command list
Simple heuristic: lines that look like commands
"""
commands = []
for line in text.split('\n'):
line = line.strip()
# Skip empty lines, headers, comments
if not line or line.startswith('#') or line.startswith(';'):
continue
if line.startswith('>'):
line = line[1:].strip()
# Lines that are likely commands
if len(line) < 100 and not line.endswith(':'):
commands.append(line.lower())
return commands
def main():
output_dir = Path("walkthroughs")
output_dir.mkdir(exist_ok=True)
print(f"Fetching walkthroughs from IF Archive")
print(f"Output directory: {output_dir}\n")
success = 0
failed = 0
skipped = 0
for game_name in KNOWN_SOLUTIONS:
result = fetch_solution(game_name, output_dir)
if result:
success += 1
elif game_name not in KNOWN_SOLUTIONS:
skipped += 1
else:
failed += 1
print(f"\n{'='*60}")
print(f"SUMMARY:")
print(f" ✓ Downloaded: {success}")
print(f" ✗ Failed: {failed}")
print(f" - Skipped: {skipped}")
print(f"{'='*60}")
# Parse downloaded walkthroughs
print(f"\nParsing walkthroughs...")
for txt_file in output_dir.glob("*_human_walkthrough.txt"):
game_name = txt_file.stem.replace("_human_walkthrough", "")
text = txt_file.read_text()
commands = parse_solution_txt(text)
json_path = output_dir / f"{game_name}_commands.json"
json_path.write_text(json.dumps({
"game": game_name,
"source": "IF Archive",
"commands": commands,
"total_commands": len(commands)
}, indent=2))
print(f" ✓ {game_name}: {len(commands)} commands")
if __name__ == "__main__":
main()