Download Game! Currently 71 players and visitors. Last logged in:KandaharSecderArasakaFrenor

Blitzer's Blog >> 72418

Back to blogs index
Posted: 15 Sep 2026 12:41 [ permalink ]
Haha, that is the perfect analogy! You are experiencing the classic "guess the
verb" puzzle of 1980s interactive fiction, but this time, the parser is doing
exactly what we told it to doperhaps a bit *too* strictly.

The reason you are stuck in a time loop on the beach comes down to a classic
string matching bug between our CLI and the LLM's compiled artifact.

### The Diagnosis: The Shouting Match

If you recall, in `cli.js`, we did this to normalize the user's input:

```javascript
const formattedAnswer = answer.trim().toUpperCase(); // "NORTH"

```

But Gemma, being a polite model trained on prose, likely wrote its condition
checks in lowercase:

```fso-code
JMP_IF player_command "north" room1

```

When the VM runs the `IS` condition, it evaluates `"NORTH" === "north"`, which
evaluates to `false`. Every single jump condition fails, the VM hits the end
of the block, and the game loop dutifully dumps you right back on the beach!

### The Fix: A Case-Insensitive VM

To align with our "forgiving VM" philosophy, the virtual machine should handle
case normalization internally. This ensures that no matter what the LLM
generates (uppercase, lowercase, or Title Case), the condition checks will
always resolve logically.

We can patch the `JMP_IF` handler in `opcodes.js` to force both sides of the
comparison to uppercase.

While we are in there, we can add a simple `CONTAINS` operator. If the user
types "go north", an `IS` check will fail even if the casing matches. A
`CONTAINS` check acts as a fuzzy matcher, which makes the game feel infinitely
more responsive.

Here is the patched logic for `opcodes.js`:

```javascript
/ In opcodes.js -> JMP_IF handler
vm.register('JMP_IF', (ctx, args) => {
    if (args.length === 3) {
        args.splice(1, 0, 'IS'); // Auto-fill missing operator
    }
    
    const [varName, condition, val, targetLabel] = args;
    
    // Safely grab memory value and expected value, cast to uppercase for
comparison
    const memVal = String(ctx.memory[varName] || '').toUpperCase();
    const expectedVal = String(val).toUpperCase();
    
    let isTrue = false;
    
    if (condition === 'IS') {
        isTrue = (memVal === expectedVal);
    } 
    else if (condition === 'NOT') {
        isTrue = (memVal !== expectedVal);
    } 
    // New forgiving fuzzy matcher!
    else if (condition === 'CONTAINS') {
        isTrue = memVal.includes(expectedVal);
    }
    
    if (isTrue) {
        if (!ctx.labels[targetLabel]) {
            console.error(`[VM FAULT] Attempted jump to unknown label:
${targetLabel}`);
        } else {
            ctx.pc = ctx.labels[targetLabel];
        }
    }
});

```

*(You may also need to peek at `game_idea.md` and manually change the `JMP_IF`
operator from `"north"` to `CONTAINS "north"` for this specific run, or update
the prompt in `compiler.js` to instruct Gemma to use `CONTAINS` for user
inputs).*

With this small patch, typing "north", "NORTH", or "go north" will all trigger
the correct jump.

Shall we apply this patch to get you off the beach, or are you ready to start
building the Shadow Registry so the Node.js runtime can spawn that physical
boat onto the island?