logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·30.10.26
← Back to news

Infidel goes wild

Original article
blog.zarfhome.com|175 points|36 comments|by tobr|Oct 3, 2026

Infidel Goes Wild

Zarf Updates | Exploring interactive fiction, game narratives, and the technical depths of the Z-machine.


The Discovery of a "Sinfull" Bug

While the public release of Planetfall happened yesterday, my primary focus over the last few weeks has been Infidel. During this process, I stumbled upon what I consider the most egregious bug ever found in an Infocom title.

Detecting this issue through standard gameplay is nearly impossible. I likely only spotted it because I am the first person to approach the game using a memory-level debugger. To a casual observer, this would be a trivial bug since it rarely disrupts the player's experience. However, from a technical perspective, it is a wild pointer bug that scribbles over memory haphazardly.

As a C programmer, I am legally obligated to view memory corruption as the absolute worst of all possible sins.

Technical Parameters

  • Analyzed Version: Infidel release 22, serial 840522 (Macintosh update).
  • Note: The original release (serial 830916) contains the same flaw, though the specific memory addresses differ.

The Mechanics of the Endless Desert

To understand the bug, we first need to understand how the game handles the vast wasteland.

If you wander too far from your camp or the specific region containing the buried pyramid, you become "lost." In reality, you aren't moving through a massive map; instead, you are trapped in a single room called ENDLESS-DESERT. This is a clever design trick first utilized in Enchanter.

How the "Endless" loop works:

  • Move in any direction →\rightarrow→ Loop back to ENDLESS-DESERT.
  • Drop an item →\rightarrow→ Item is shifted "offstage."
  • Record location →\rightarrow→ The item's coordinates are stored in the DESERT-TABLE.
  • Return to coordinates →\rightarrow→ The game moves the item from the table back into the room.

Note: There is a 1/31/31/3 probability that an item dropped in the desert is immediately buried by sand and deleted. This randomness actually makes the bug harder to trigger and detect.

Gameplay Example

Imagine the following sequence:

  1. Location: Desert (You are in a wasteland of sand and heat).
  2. Event: A gust of wind blinds you; you lose your shovel.
  3. Action: Move EAST →\rightarrow→ You are still in the Desert.
  4. Action: Move WEST →\rightarrow→ You are still in the Desert.

Even though you are in the same ENDLESS-DESERT room, the game maintains the illusion of distance.


Diving into the ZIL Code

The logic governing this movement is handled by the DESERT-TO-TABLE routine. Here is the high-level ZIL (Zork Implementation Language) logic:

ROUTINE DESERT-TO-TABLE ( SLOC AUX (TBL ,DESERT-TABLE) (CNT 0) (F FIRST?)
    GET .TBL .CNT 0 
    PUT .TBL .CNT .SLOC 
    PUT .TBL + .CNT 1 .F 
    SET CNT + .CNT 2 
    REMOVE .F 
    RETURN 
) (ELSE SET CNT + .CNT 2 ) ) SET F .N

Data Structure Breakdown

The routine takes one required argument: SLOC (the encoded latitude/longitude coordinate). It uses "AUX" for optional arguments/local variables:

  • TBL: The target table.
  • CNT: The current index counter.
  • F: The first object in the ENDLESS-DESERT contents list.
FeatureDetail
Table NameDESERT-TABLE
Start Address11129
Total Size100 values (200 bytes)
Entry Size2 values per object (SLOC + Object ID)

The function iterates through all objects in the ENDLESS-DESERT. It ignores scenery and the player, removing every portable object and storing its coordinate and ID in the TBL array.

Visualizing the Flow


The "C Nerd" Concern: Array Overflow

Whenever a programmer sees a fixed-size array, the first question is: What happens when it overflows?

I checked the source comments for DESERT-TABLE, which stated: ; length should be 2*number of takeable objects

Using LaTeX to verify the math: Capacity=100 values2 values/entry=50 objects\text{Capacity} = \frac{100 \text{ values}}{2 \text{ values/entry}} = 50 \text{ objects}Capacity=2 values/entry100 values​=50 objects

Since there are only approximately 45 portable objects in the entire game, it seems impossible to overflow the table. To verify this, I added a monitor to my debugger's "State" tab to watch the DESERT-TABLE in real-time.

The Deep Dive: Disassembly

To truly see what was happening, I disassembled the function from the game file.

Routine 109bc (5 locals: 0000, 001e, 0000, 0000, 0000)

109c7: GET_CHILD ENDLESS-DESERT - .F [TRUE] 
109cb 
109cb: JZ .F [TRUE] RTRUE 
109ce: GET_SIBLING .F - .N [TRUE] 
109d2 
109d2: JE .F, G70 [FALSE] 
109d9 
109d6: JUMP 10a02 
109d9: TEST_ATTR .F, #0f [FALSE] 
10a02 
109dd: LOADW .TBL, .CNT - -(SP) 
109e1: JZ (SP)+ [FALSE] 
109fb 
109e4: STOREW .TBL, .CNT, .SLOC 
109e9: ADD .CNT, #01 - -(SP) 
109ed: STOREW .TBL, (

(The disassembly continues, revealing the underlying Z-machine instructions that manage the memory movement...)