When I think about retro games, forget Mario, Sonic or even Tetris. I think Zork. The quirky text adventure, published by Personal Software (and then Infocom) back in 1980, screwed with players in many, many ways (when it wasn't sending grues after them). I thought I knew its best secrets — that is until prominent developer Ryan C. Gordon revealed the granddaddy of them all... and the most underhanded use of randomness I've seen in a game for a while.
According to Gordon, while Zork checks the player's item count to determine if they're carrying too much, it also uses a random roll just to mess with the player. The roll used a number between 0 and 100, forcing players to keep trying to pick things up until it finally worked.
This is how we hang on Saturdays. pic.twitter.com/NdteyUDidB
— Ryan C. Gordon (@icculus) August 26, 2017
I was sceptical at first — surely a system as important as inventory wouldn't be so cavalier with capacity? My scepticism grew when searches of Zork's MDL code from MIT and the public domain source from Infocom came up empty.
Here are the relevant lines from the decompiled Zork assembly:
L0007: JE G78,#5d [FALSE] L0008 CALL R0240 (G6f) -> L01 JG L01,G3b [FALSE] L0008 MUL L01,G3a -> L03 RANDOM #64 -> -(SP) JG L03,(SP)+ [FALSE] L0008 PRINT "You're holding too many things already!" NEW_LINE RFALSE L0008: INSERT_OBJ G76,G6f SET_ATTR G76,#03 CALL R0013 -> -(SP) CALL R0235 (G76) -> -(SP) RTRUE
The random call uses "64", a hexadecimal (base 16) value, which converts to 100 in decimal (base 10).
And here's the disassembled code Gordon found on the Wayback Machine, which includes comments:
.label4; if( Verb ~= ##Take ) ?label8; num_items = CCount(player); if( num_items <= Maximum_held ) ?label8; weight = num_items * Max_held_mult; if( weight <= random(100) ) ?label8; print "You're holding too many things already!"; new_line; rfalse; .label8; move noun to player; give noun visited; Zork2_deletion(); ScoreObj(noun); rtrue;
I knew Zork didn't play fair sometimes, but this is next level.