Skip to content

Add ACK!MUD and DSA dialects; read ROM 2.3 and ROM OLC/ROT variants - #20

Merged
ctoth merged 6 commits into
masterfrom
feat/mongoose-corpus-dialects
Sep 24, 2026
Merged

ctoth merged 6 commits into
masterfrom
feat/mongoose-corpus-dialects

Conversation

@ctoth

@ctoth ctoth commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Extends dialect coverage using a 321-file corpus of MUD areas (mud-areas/ + rom/). A corpus sweep (detect, then parse with the detected reader, falling back to ROM/Merc/SMAUG) went from 221 ok / 100 fail with 44 fallback rescues to 295 ok / 26 fail with 0 fallback rescues. Every file now parses with the reader detect_area_type picks.

New dialects

Dialect Reader Detection Corpus files
ACK!MUD AckAreaFile #AREA name string followed by a K keyword~ line 25
Devil's Silence DsaAreaFile first #AREA string is DSA Format~ 12
  • ACK!MUD: letter-keyed header (K/L/N/I/V/X/F/U/O/R/W plus text flag lines T/P/B/M/S), rooms with two numbers (sector may be missing) and raw exit bits, mobiles with a ! line and inline >trigger ... ~ | MOBprograms, four-value objects with A/E/L records, #OBJFUNS.
  • DSA: ROM bodies ending in keyed lines up to End on the header, mobiles, objects, rooms and exits. These lines are kept verbatim, since their meaning is DSA-specific. The area help is bare text ended by -1 $~. Resets are Reset ... lines inside each room, and they are read as typed DsaReset records on the room.

Both come with native writers (dumps()/write()), and every one of the 37 corpus files round-trips to an equal model.

ROM variants read by RomAreaFile

  • ROM 2.3 with a Merc-style header (#AREA {5 15} Author Name~). These were detected as Merc because the header has one string. They are now routed to ROM when the first mobile has a race string. RomArea.header_format records "merc". RomMob.group is None where the file has ROM 2.3's literal S. M/P resets read a fourth argument only when one is present on the line.
  • ROM OLC / ROT #AREADATA (Name/Filename/Builders/VNUMs/Credits/Security/Zone). These were detected as GodWars, which rejected Credits. They are now routed to ROM when a Credits line or a race string on the first mobile is present. ROM reads and writes this header (header_format == "areadata", plus builders, security and zone). ROT mobiles carry shielded_by between affected_by and alignment.
  • The ROM writer now emits #MOBPROGS. Before this, it dropped them on write.

Leniency

  • Dice accepts a flat number (mana 100) and a +- negative bonus (1d5+-1).
  • Room sector numbers outside SECTOR_TYPES are kept as raw ints instead of raising.
  • An unknown ROM object condition letter reads as 100, which matches ROM's loader. A numeric condition is consumed whole.

Remaining corpus failures (26)

  • 4 are not area files (rom/group.are, help.are, rom.are, social.are). They fail cleanly with "no rooms". keep.are also has no rooms.
  • Records that look hand-damaged:
    • court (dice with no bonus)
    • aliens2 and grail (dice written where the wealth number belongs)
    • olympus2, templofm, templofs, elvandar
    • gnome, gragh and grave (unterminated strings)
    • ephradle (broken header)
    • rom/proto.are (a template with XX00 vnums)
  • Rarer layouts not handled here:
    • Merc mobiles with E .trigger~ records (alice, deathdun)
    • container values written as '' (mirror2, ocean, zoo)
    • Merc-style > MOBprograms inside ROM mobiles (swroad)
    • lhouse, AsylumGrounds, pagesvisited, dethkeep

Tests

Small trimmed fixtures are under test/ack, test/dsa, test/rom23 and test/rot, with tests in test_ack.py, test_dsa.py, test_rom23.py, test_rom_areadata.py and test_lenient_values.py. The full suite gives 1064 passed and 1 failed. The failure is test_medievia.py::test_loads_standalone_medievia_world_file, which already fails on master because cli.load_area is missing; the concurrent CLI PR fixes it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN

ctoth and others added 6 commits September 23, 2026 19:45
Read and write ACK!MUD areas: the letter-keyed #AREA header (K/L/N/I/V/X/F/U/O/R/W
plus text flag lines), two-number rooms with raw exit bits, "!"-line mobiles with
inline MOBprograms, four-value objects with A/E/L records, and #OBJFUNS.
Detected by an #AREA name string followed by a "K keyword~" line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN
ROM 2.3-era areas keep Merc's one-string "#AREA {levels} Author Name~" header,
write a literal "S" where ROM 2.4 writes the mob group, and end M/P resets after
the third argument. Detect them from the race string on the first mobile, record
the header and group layouts so the native writer reproduces them, and read an
M/P fourth argument only when it is present on the line.

Dice also accept a flat number (e.g. mana "100") and a "+-" negative bonus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN
ROM OLC and ROT write a keyed #AREADATA header (Name, Filename, Builders,
VNUMs, Credits, Security, Zone) over ROM bodies. Detection sent these to
GodWars, which rejected Credits; route #AREADATA files with a Credits line
or a race string on the first mobile to the ROM reader, which now reads and
writes the header itself.

ROT mobiles carry a shielded_by flag between affected_by and alignment;
read it when the line holds the extra word and keep that line together on
write. The ROM writer also emits #MOBPROGS instead of dropping them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN
Keep room sector numbers outside SECTOR_TYPES as raw ints instead of
failing, since several dialects extend the sector table. Treat unknown ROM
object condition letters as perfect (100), as ROM's loader does, and consume
a numeric condition whole so the record stays aligned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN
DSA is a ROM derivative marked by a "DSA Format~" string at the top of
#AREA. Its header, mobiles, objects, rooms, and exits end in keyed lines up
to "End", which are kept verbatim; the area help is bare text ended by
"-1 $~"; and resets are "Reset" lines inside each room, read as typed
DsaReset records. Mobiles reuse the ROM reader, including ROT's
shielded_by word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsTyuYeZHogKAnGhufs9gN
@ctoth
ctoth merged commit c2a948b into master Sep 24, 2026
4 checks passed
@ctoth
ctoth deleted the feat/mongoose-corpus-dialects branch September 24, 2026 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant