Missing command: '+' wizard-mode toggle-off answers "illegal command" #11

Closed
opened 2026-08-09 03:43:51 +02:00 by clawbot · 1 comment
Collaborator

Problem

C command.c:316-336 has a case '+' that toggles wizard mode:

  • off — sets wizard false, calls turn_see(TRUE), prints
    "not wizard any more"
  • on — via passwd()

Go's commandHandlers (game/tables.go:697…) has no '+' entry, and
neither wizardCommand nor wizardDebugCommand (game/command.go:395-446)
handles it. So in wizard mode, pressing + falls through to illcom and
prints "illegal command '+'".

The password half was correctly and deliberately dropped (wizard mode is now
gated on ROGUE_WIZARD, documented in ARCHITECTURE.md §9 and
game/wizard.go:5-6). But the toggle-off half was lost silently — it is
not mentioned in the dropped-functionality table, and it does not depend on
the password machinery at all.

The turn_see(TRUE) call is the substantive part: leaving wizard mode has to
re-hide monsters that wizard sight revealed. Without it there is no way back
to normal visibility once wizard mode is on.

Definition of done

  1. '+' is handled in wizard mode: wizard flag cleared, the equivalent of
    C's turn_see(TRUE) performed, and C's exact message text emitted.
  2. Behavior when not in wizard mode matches C (the password path is
    dropped — pressing + as a normal player must do whatever C's
    now-unreachable-for-us branch would sensibly reduce to; state the choice in
    a code comment).
  3. A test drives + through command dispatch in wizard mode and asserts the
    flag is cleared and previously-wizard-visible monsters are hidden again.
  4. ARCHITECTURE.md §9 updated if any part of '+' remains deliberately
    dropped.
  5. make check fully green.
  6. TODO.md updated in the same commit.
  7. Commit title ends with (closes #N).

Implementation requirements

  • Read git show origin/c-master:command.c (the case '+' arm) and the
    turn_see implementation before writing anything. Do NOT check out or
    modify origin/c-master.
  • Use C's exact message text, including any original typo. Message text is
    contract in this repo.
  • Keep the C breadcrumb doc-comment convention ((command.c ...)).
  • Preserve RNG call order.
  • Tests need t.Parallel() and the //nolint:testpackage header.
  • make targets only. Do NOT modify .golangci.yml.
  • Never mention Claude or Anthropic anywhere.
## Problem C `command.c:316-336` has a `case '+'` that toggles wizard mode: - **off** — sets wizard false, calls `turn_see(TRUE)`, prints "not wizard any more" - **on** — via `passwd()` Go's `commandHandlers` (`game/tables.go:697…`) has **no `'+'` entry**, and neither `wizardCommand` nor `wizardDebugCommand` (`game/command.go:395-446`) handles it. So in wizard mode, pressing `+` falls through to `illcom` and prints *"illegal command '+'"*. The password half was correctly and deliberately dropped (wizard mode is now gated on `ROGUE_WIZARD`, documented in ARCHITECTURE.md §9 and `game/wizard.go:5-6`). But the **toggle-off half was lost silently** — it is not mentioned in the dropped-functionality table, and it does not depend on the password machinery at all. The `turn_see(TRUE)` call is the substantive part: leaving wizard mode has to re-hide monsters that wizard sight revealed. Without it there is no way back to normal visibility once wizard mode is on. ## Definition of done 1. `'+'` is handled in wizard mode: wizard flag cleared, the equivalent of C's `turn_see(TRUE)` performed, and C's exact message text emitted. 2. Behavior when **not** in wizard mode matches C (the password path is dropped — pressing `+` as a normal player must do whatever C's now-unreachable-for-us branch would sensibly reduce to; state the choice in a code comment). 3. A test drives `+` through command dispatch in wizard mode and asserts the flag is cleared and previously-wizard-visible monsters are hidden again. 4. ARCHITECTURE.md §9 updated if any part of `'+'` remains deliberately dropped. 5. `make check` fully green. 6. `TODO.md` updated in the same commit. 7. Commit title ends with ` (closes #N)`. ## Implementation requirements - Read `git show origin/c-master:command.c` (the `case '+'` arm) and the `turn_see` implementation before writing anything. Do NOT check out or modify `origin/c-master`. - Use C's **exact** message text, including any original typo. Message text is contract in this repo. - Keep the C breadcrumb doc-comment convention (`(command.c ...)`). - Preserve RNG call order. - Tests need `t.Parallel()` and the `//nolint:testpackage` header. - `make` targets only. Do NOT modify `.golangci.yml`. - Never mention Claude or Anthropic anywhere.
Author
Collaborator

Premises verified against the C reference

Checked before writing anything; all substantive claims hold.

  • git show origin/c-master:command.c lines 317-338: the arm is spelled
    when '+': (the when macro is break; case), wrapped in
    #ifdef MASTER. The issue cites 316-336; the real range is 317-338
    (#ifdef MASTER 317, when '+': 318, #endif 338). Cosmetic drift only.

  • Both arms are exactly as described:

    when '+':
        after = FALSE;
        if (wizard)
        {
            wizard = FALSE;
            turn_see(TRUE);
            msg("not wizard any more");
        }
        else
        {
            wizard = passwd();
            if (wizard)
            {
                noscore = TRUE;
                turn_see(FALSE);
                msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
            }
            else
                msg("sorry");
        }
    
  • turn_see lives in potions.c (declared rogue.h:691). The turn_off
    arm redraws t_oldch at every monster the hero cannot see and clears
    SEEMONST; it consumes no random numbers (only the turn-on arm calls
    rnd). Go already has a faithful turnSee in game/potions.go:295,
    used by newlevel.go, potions.go and the wizard ^X command.

  • Go really has no '+': not in commandHandlers (game/tables.go), not
    in wizardCommand/wizardDebugCommand (game/command.go:402-454). The
    only '+' literals in non-test code are Door (types.go:48) and the
    blessing prompt in wizard.go. So '+' reaches dispatchKey's default
    and ends at illcom.

One correction to the framing, which changes where the code goes: '+' sits
in C's main command switch (just before otherwise:), not in the
if (wizard) switch (ch) sub-switch that wizardCommand ports. Under
MASTER C therefore reaches it whether or not wizard is set, so the Go
home is commandHandlers, not wizardCommand. That also means the
non-wizard behaviour is a divergence today too: C answers "sorry", Go
answers "illegal command '+'".

Plan

  1. game/command.go: new wizardToggleCommand, breadcrumbed
    (command.c command). Sets After = false; when g.Wizard, clears the
    flag, calls g.turnSee(true), and emits "not wizard any more"
    verbatim; otherwise emits "sorry".
  2. The not-in-wizard-mode choice, stated in a code comment: passwd() is
    dropped (wizard mode is ROGUE_WIZARD configuration, ARCHITECTURE.md
    §9), and a dropped password check is a password check that never
    succeeds, so the else arm reduces to exactly what C did on a wrong
    password — wizard stays off, message "sorry". No prompt is
    shown, since nothing typed into it could change the outcome. noscore
    and turn_see(FALSE) belong to the unreachable success branch and are
    not ported.
  3. game/tables.go: '+': (*RogueGame).wizardToggleCommand in
    commandHandlers.
  4. game/wizard_test.go: '+' driven through g.dispatch in wizard mode
    with a sensed-but-unseeable monster (an invisible phantom, so seeMonst
    is false) after turnSee(false). Asserts the precondition (monster glyph
    drawn in standout at its cell, SenseMonsters set), then after '+':
    Wizard false, SenseMonsters cleared, and the cell back to the
    monster's OldCh with standout off — the visibility half is the
    real assertion. Plus the message text and a second test for the
    not-in-wizard-mode "sorry" arm.
  5. ARCHITECTURE.md §9: the existing "DES crypt wizard password" row is
    amended to name the '+' enter arm as the dropped part and to record
    that the leave arm is ported and the else arm answers "sorry".
  6. TODO.md Completed Steps entry in the same commit; Next Step not
    rotated (out-of-band issue work).

RNG order is untouched: turnSee(true) makes no rnd call, and the new key
is additive to the dispatch map. TestSeedCompatItemTables stays green
against the untouched golden.

## Premises verified against the C reference Checked before writing anything; all substantive claims hold. - `git show origin/c-master:command.c` lines 317-338: the arm is spelled `when '+':` (the `when` macro is `break; case`), wrapped in `#ifdef MASTER`. The issue cites 316-336; the real range is 317-338 (`#ifdef MASTER` 317, `when '+':` 318, `#endif` 338). Cosmetic drift only. - Both arms are exactly as described: ``` when '+': after = FALSE; if (wizard) { wizard = FALSE; turn_see(TRUE); msg("not wizard any more"); } else { wizard = passwd(); if (wizard) { noscore = TRUE; turn_see(FALSE); msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum); } else msg("sorry"); } ``` - `turn_see` lives in `potions.c` (declared `rogue.h:691`). The `turn_off` arm redraws `t_oldch` at every monster the hero cannot see and clears `SEEMONST`; it consumes no random numbers (only the turn-on arm calls `rnd`). Go already has a faithful `turnSee` in `game/potions.go:295`, used by `newlevel.go`, `potions.go` and the wizard `^X` command. - Go really has no `'+'`: not in `commandHandlers` (`game/tables.go`), not in `wizardCommand`/`wizardDebugCommand` (`game/command.go:402-454`). The only `'+'` literals in non-test code are `Door` (`types.go:48`) and the blessing prompt in `wizard.go`. So `'+'` reaches `dispatchKey`'s default and ends at `illcom`. One correction to the framing, which changes where the code goes: `'+'` sits in C's **main** command switch (just before `otherwise:`), not in the `if (wizard) switch (ch)` sub-switch that `wizardCommand` ports. Under `MASTER` C therefore reaches it whether or not `wizard` is set, so the Go home is `commandHandlers`, not `wizardCommand`. That also means the non-wizard behaviour is a divergence today too: C answers "sorry", Go answers "illegal command '+'". ## Plan 1. `game/command.go`: new `wizardToggleCommand`, breadcrumbed `(command.c command)`. Sets `After = false`; when `g.Wizard`, clears the flag, calls `g.turnSee(true)`, and emits `"not wizard any more"` verbatim; otherwise emits `"sorry"`. 2. The not-in-wizard-mode choice, stated in a code comment: `passwd()` is dropped (wizard mode is `ROGUE_WIZARD` configuration, ARCHITECTURE.md §9), and a dropped password check is a password check that never succeeds, so the else arm reduces to exactly what C did on a wrong password — `wizard` stays off, message `"sorry"`. No prompt is shown, since nothing typed into it could change the outcome. `noscore` and `turn_see(FALSE)` belong to the unreachable success branch and are not ported. 3. `game/tables.go`: `'+': (*RogueGame).wizardToggleCommand` in `commandHandlers`. 4. `game/wizard_test.go`: `'+'` driven through `g.dispatch` in wizard mode with a sensed-but-unseeable monster (an invisible phantom, so `seeMonst` is false) after `turnSee(false)`. Asserts the precondition (monster glyph drawn in standout at its cell, `SenseMonsters` set), then after `'+'`: `Wizard` false, `SenseMonsters` cleared, and the cell back to the monster's `OldCh` with standout off — the visibility half is the real assertion. Plus the message text and a second test for the not-in-wizard-mode `"sorry"` arm. 5. ARCHITECTURE.md §9: the existing "DES crypt wizard password" row is amended to name the `'+'` enter arm as the dropped part and to record that the leave arm is ported and the else arm answers "sorry". 6. `TODO.md` Completed Steps entry in the same commit; `Next Step` not rotated (out-of-band issue work). RNG order is untouched: `turnSee(true)` makes no `rnd` call, and the new key is additive to the dispatch map. `TestSeedCompatItemTables` stays green against the untouched golden.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/rgoue#11