Add script to import a Nethack logfile
This commit is contained in:
parent
cb3818fd57
commit
5ecd480f98
1 changed files with 119 additions and 0 deletions
119
scripts/import-nethack-logfile.py
Executable file
119
scripts/import-nethack-logfile.py
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env python3
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
Converts a Nethack logfile (or record file) to JSON for easier parsing by my
|
||||
website's templating engine.
|
||||
|
||||
See https://nethackwiki.com/wiki/Logfile for information about the format of these
|
||||
logfiles.
|
||||
'''
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import json
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
DUNGEONS = {
|
||||
0: 'The Dungeons of Doom',
|
||||
1: 'Gehennom',
|
||||
2: 'The Gnomish Mines',
|
||||
3: 'The Quest',
|
||||
4: 'Sokoban',
|
||||
5: 'Fort Ludios',
|
||||
6: "Vlad's Tower",
|
||||
7: 'The Elemental Planes',
|
||||
}
|
||||
|
||||
# The "dungeon level" field is normally positive, but negatives indicate one of these
|
||||
# levels.
|
||||
SPECIAL_DUNGEON_LEVELS = {
|
||||
-5: 'Astral Plane',
|
||||
-4: 'Plane of Water',
|
||||
-3: 'Plane of Fire',
|
||||
-2: 'Plane of Air',
|
||||
-1: 'Plane of Earth',
|
||||
}
|
||||
|
||||
RACES = {
|
||||
'Hum': 'Human',
|
||||
}
|
||||
|
||||
ROLES = {
|
||||
'Mon': 'Monk',
|
||||
'Rog': 'Rogue',
|
||||
'Sam': 'Samurai',
|
||||
}
|
||||
|
||||
GENDERS = {
|
||||
'Fem': 'Female',
|
||||
}
|
||||
|
||||
ALIGNMENTS = {
|
||||
'Law': 'Lawful',
|
||||
'Neu': 'Neutral',
|
||||
'Cha': 'Chaotic',
|
||||
}
|
||||
|
||||
def parse_args(argv, *a, **kw):
|
||||
parser = argparse.ArgumentParser(*a, **kw)
|
||||
parser.add_argument('logfile', help='Path to the Nethack log file to convert')
|
||||
args = parser.parse_args(argv)
|
||||
return args
|
||||
|
||||
def main(argv):
|
||||
args = parse_args(argv[1:], prog=argv[0])
|
||||
|
||||
if not os.path.isfile(args.logfile):
|
||||
print('Given path is not a real file!', file=sys.stderr)
|
||||
return -1
|
||||
|
||||
records = []
|
||||
with open(args.logfile) as logfile:
|
||||
for record in logfile.readlines():
|
||||
fields = record.split(maxsplit=15)
|
||||
|
||||
dungeon_number = int(fields[2])
|
||||
dungeon_name = DUNGEONS[dungeon_number]
|
||||
|
||||
dungeon_level = int(fields[3])
|
||||
if dungeon_level > 0:
|
||||
dungeon_level_descriptive = f"Level {dungeon_level}"
|
||||
else:
|
||||
dungeon_level_descriptive = SPECIAL_DUNGEON_LEVELS[dungeon_level]
|
||||
|
||||
start_date = datetime.datetime.strptime(fields[9], '%Y%m%d').strftime('%Y-%m-%d')
|
||||
end_date = datetime.datetime.strptime(fields[8], '%Y%m%d').strftime('%Y-%m-%d')
|
||||
|
||||
name, reason = fields[15].split(',', maxsplit=1)
|
||||
|
||||
records.append({
|
||||
'nethack_version': fields[0],
|
||||
'score': int(fields[1]),
|
||||
'dungeon_number': int(fields[2]),
|
||||
'dungeon_name': dungeon_name,
|
||||
'level': dungeon_level,
|
||||
'level_descriptive': dungeon_level_descriptive,
|
||||
'max_level': int(fields[4]),
|
||||
'hit_points': int(fields[5]),
|
||||
'max_hit_points': int(fields[6]),
|
||||
'number_of_deaths': int(fields[7]),
|
||||
'end_date': end_date,
|
||||
'start_date': start_date,
|
||||
'user_id': int(fields[10]),
|
||||
'role': ROLES[fields[11]],
|
||||
'race': RACES[fields[12]],
|
||||
'gender': GENDERS[fields[13]],
|
||||
'alignment': ALIGNMENTS[fields[14]],
|
||||
'name': name.strip(),
|
||||
'reason_for_death': reason.strip(),
|
||||
})
|
||||
|
||||
json.dump(records, sys.stdout, indent=2)
|
||||
print('\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
result = main(sys.argv)
|
||||
sys.exit(0 if not result else result)
|
Loading…
Add table
Add a link
Reference in a new issue