NAIL v1.0

I created a system for writing very small Z-code games. It’s derived from PunyInform, and it works a lot like PunyInform, except it (a) produces smaller story files, and (b) has a much simpler parser, lacks some nice features, requires Ruby for the build process, and is all-around less convenient to work with.

It’s not really a library, but more a build environment, and a source code template for a game. Start editing the template, build, test, repeat until happy.

An absolutely minimal game in PunyInform is about 23 KB. In NAIL, it’s 11 KB. Cloak of Darkness is 12.5 KB, unless you start removing verbs/actions which aren’t strictly necessary for the game.

I expect this to come in handy for projects targeting tiny 8-bit machines, possibly without a disk drive. E.g. on a 48K Spectrum, it should be possible to run a 29 KB Z-code game, using Vezza.

6 Likes

Using checksums for dictionary words is really clever!

Though I’d worry that a game might not have a encoding factor that makes all words unique.

I feel that lacking multiple commands per input line might be a deal breaker for many people. Being able to type stuff like s.e.e.w is something people take for granted.

1 Like

Whoah, I didn’t even know you could do that. ( I’m just getting into the genre :slight_smile: )

2 Likes

Thanks for your comments!

The build script will write comments in generated_dictionary.inf, noting any collisions. In some cases it may be okay, e.g. if a verb has the same checksum as a noun or a preposition, that will never be a problem, or if synonyms for two objects that will never be in scope at the same time have the same checksum, that’s not a problem.

If you do find that there’s a collision that will cause problems, you can consider renaming an object. Maybe a stone can be named a rock, etc. If you aren’t interested in making compromises, this just isn’t the system you’re looking for.

I can’t easily run a test on all Infocom games, as I’d need to go through the dictionary of each game and figure out what characters are missing for words that have been cut off.

I have tried to do this for Zork I (690 words) and PunyInform Adventure (740 words), and at least for these games, I could find factors causing no collisions.

I also tried this for Trinity (2100+ words), and got something like 15 words with non-unique checksums. That’s a much bigger game than what NAIL is meant for though.

There’s a lot that people take for granted that isn’t supported by NAIL. You can’t take a library that’s been heavily optimized for size, such as PunyInform, reduce the size by 50%, and still have support for everything that’s nice to have.

Note that NAIL isn’t meant to supersede PunyInform. It’s a lot cruder, but may be good enough for some kinds of games, where both authors and players accept cutting some corners in order to get a small enough game.

I may have a look at this particular feature, to see if it can be implemented cheaply enough. If it’s 50 bytes, then sure. If it’s 500 bytes, it’s not happening.

The ZIL parsing I’ve done for Visible Zorker makes this tractable. E.g. for Zork 1 I get:

Summary

$ A ACROSS ACTIVATE ADVENTURER ADVERTISEMENT AGAIN AIR AIR-PUMP ALL ALTAR AN ANCIENT AND ANSWER ANTIQUE APPLY AROUND ART ASK AT ATTACH ATTACK AVIATOR AWAKE AWAY AX AXE BACK BAG BANISH BAR BARE BARF BARROW BASKET BAT BATHE BAUBLE BEAUTI BEETLE BEGONE BEHIND BELL BELOW BENEATH BIRD BIRDS BITE BLACK BLADE BLAST BLESSINGS BLOCK BLOODY BLOW BLUE BOARD BOARDED BOARDS BOAT BODIES BODY BOLT BONES BOOK BOOKLET BOOKS BOTTLE BOX BRACELET BRANCH BRANDISH BRASS BREAK BREATH BRIEF BROKEN BROWN BRUSH BUBBLE BUG BUOY BURN BURNED BURNING BUT BUTTON CAGE CANARY CANDLES CANVAS CARPET CARRY CARVED CASE CASKET CAST CATCH CHALICE CHANT CHASE CHEST CHESTS CHIMNEY CHOMP CHUCK CHUTE CLEAN CLEAR CLIFF CLIFFS CLIMB CLOCKWORK CLOSE CLOVE COAL COFFIN COIL COINS COLONI COME COMMAND CONSUME CONTAINER CONTROL COUNT COVER CRACK CRAWLWAY CRETIN CROSS CRYSTAL CUP CURSE CUT CYCLOPS D DAM DAMAGE DAMN DARK DEAD DEFLATE DERANGED DESCRIBE DESTROY DIAGNOSE DIAMOND DIG DINNER DIRT DISEMBARK DISENCHANT DISPATCH DIVE DONATE DOOR DOUSE DOWN DRINK DRIP DRIVE DRIVER DROP DRYER DUMBWAITER DUSTY E EAST EAT ECHO EGG EGYPTIAN ELONGATED ELVISH EMERALD ENAMELED ENCHANT ENCRUSTED ENGRAVINGS ENORMOUS ENTER EVIL EXAMINE EXCEPT EXIT EXORCISE EXQUISITE EXTINGUISH EYE FALL FANTASIZE FASTEN FCD#3 FEAR FEEBLE FEED FEEL FENCE FERMENT FIENDS FIERCE FIGHT FIGURINE FILCH FILL FIND FINE FINEPRINT FIREPROOF FIX FLAMING FLATHEAD FLIP FLOAT FLOOR FLUORESCE FOLLOW FOOD FOOTPAD FOR FORBIDDING FORCE FORD FOREST FORK FREE FREEZE FRIGID FROBOZZ FROM FRONT FROTZ FRY FUCK FUDGE FUMBLE G GARLIC GATE GATES GAZE GET GHOSTS GIANT GIVE GLAMDRING GLASS GLUE GO GOLD GOLDEN GOTHIC GRAB GRACES GRANITE GRATE GRATING GREASE GREEN GROUND GROUP GRUE GUIDE GUIDEBOOKS GUNK H2O HAND HAND-HELD HANDS HATCH HEAD HEAP HELLO HEMLOCKS HEMP HER HERE HI HIDE HIM HIT HOLD HOP HOT HOUSE HUGE HUNGRY HURL HURT I IGNITE IMBIBE IMPASSABLE IN INCANT INCINERATE INFLAT INJURE INSCRIPTION INSERT INSIDE INTNUM INTO INVENTORY INVISIBLE IS IT IVORY JADE JEWEL JEWELED JEWELS JUMP KEY KICK KILL KISS KITCHEN KNIFE KNIVES KNOCK L LABEL LADDER LAMP LANTERN LARGE LAUNCH LEAF LEAFLET LEAK LEAN LEAP LEATHER LEAVE LEAVES LEDGE LETTERING LID LIFT LIGHT LIQUID LIQUIFY LISTEN LOCK LONG LOOK LOSE LOWER LOWERED LUBRICATE LUNCH LUNGS LURKING MACHINE MAGIC MAIL MAILBOX MAKE MAN MANGLED MANUAL MAP MARBLE MASSIVE MATCH MATCHBOOK MATCHES MATERIAL ME MELT METAL MIRROR MOLEST MONSTER MOUNTAIN MOUTH MOVE MUMBLE MURDER MYSELF N NARROW NASTY NE NEST NO NORTH NORTHE NORTHWEST NUT NW ODYSSEUS OF OFF OFFER OIL OLD ON ONE ONTO OPEN ORCRIST ORIENTAL OUT OVER OVERBOARD OWN OWNERS OZMOO PAGE PAINTING PAIR PANEL PAPER PARCHMENT PASSAGE PASTE PAT PATCH PATH PDP10 PEAL PEDESTAL PEPPER PERSON PET PICK PIECE PIERCE PILE PINES PIPE PLACE PLASTIC PLATINUM PLAY PLUG PLUGH POKE POSEIDON POT POUR PRAY PRAYER PRESS PRINT PROCEED PULL PUMP PUNCTURE PURSUE PUSH PUT Q QUANTITY QUIT RAFT RAIL RAILING RAINBOW RAISE RAMP RANGE RAP RAPE READ RED REFLECTION RELEASE REMAINS REMOVE REPAIR REPENT REPLY RESTART RESTORE RICKETY RING RIVER ROBBER ROCKY ROLL ROPE RUB RUG RUN RUSTY S SACK SAILOR SAND SANDWICH SAPPHIRE SAVE SAY SCARAB SCEPTER SCEPTRE SCORE SCREAM SCREW SCREWDRIVER SCRIPT SE SEARCH SEAWORTHY SECURE SEE SEEDY SEEK SELF SEND SET SHADY SHAKE SHARP SHEER SHIT SHOUT SHOVEL SHUT SIGH SILENT SILVER SINISTER SIT SKELETON SKIM SKIP SKULL SLAG SLAY SLICE SLIDE SMALL SMASH SMELL SMELLY SNIFF SOLID SONG SONGBIRD SOUTH SOUTHE SOUTHWEST SPILL SPIN SPIRITS SPRAY SQUEEZE STAB STAIRCASE STAIRS STAIRWAY STAND STARE STARTLE STAY STEEP STEP STEPS STILETTO STONE STORM STRANGE STRIKE STUFF SUPER SUPERBRIEF SURPRISE SURROUNDING SUSPICIOUS SW SWALLOW SWIM SWING SWITCH SWORD TABLE TAKE TALK TAN TASTE TAUNT TEETH TELL TEMPLE THE THEM THEN THIEF THIEFS THROUGH THROW THRU THRUST TIE TIMBERS TO TOMB TOOL TOOLCHESTS TOOLS TOOTH TORCH TOSS TOUCH TOUR TRAIL TRAP TRAP-DOOR TRAPDOOR TREASURE TREE TREES TRIDENT TROLL TROPHY TRUNK TUBE TUG TURN TWISTING U ULYSSES UNATTACH UNDER UNDERNEATH UNFASTEN UNHOOK UNLOCK UNRUSTY UNSCRIPT UNTIE UP USELESS USING VALVE VAMPIRE VERBOSE VERIFY VERSION VICIOUS VISCOUS VITREOUS W WADE WAIT WAKE WALK WALL WALLS WATER WAVE WEAR WEST WHAT WHATS WHERE WHITE WIN WIND WINDING WINDOW WINNAGE WISH WITH WOODEN WRENCH WRITING XYZZY Y YANK YELL YELLOW YES Z ZORK ZORKMID ZZMGCK , .

That’s approximate – I’m sure I missed some parsing details – but it gives you an idea.