============================================================
VOLT MAZE - PROGRAM BREAKDOWN
BASIC10 EXTREME-256 Category
============================================================
Author  : Jason Brooks
Website : www.muckypaws.com
System  : Amstrad CPC 464/664/6128 (Locomotive BASIC 1.0/1.1)
Date    : March 2026
============================================================

OVERVIEW
--------
Volt Maze is a maze exploration game written entirely in
10 lines of Locomotive BASIC for the Amstrad CPC. The game
is inspired by Maze Craze (Atari 2600, 1980).

A unique maze is procedurally generated each level using an
iterative depth-first search algorithm with a software stack.
The player navigates from the bottom-left to the exit in the
top-right corner, collecting score dots while avoiding
electrified walls. From Level 4 a hunter appears, consuming
dots and draining health on contact.

The game uses Locomotive BASIC features including hardware
INK animation for progressive difficulty, boolean arithmetic
for conditional logic without IF statements, character-cell
screen positioning via LOCATE/PRINT, and the CPC's built-in
animated walking figure characters CHR$(248)-CHR$(251).

============================================================
VARIABLE REFERENCE
============================================================

  SC      Current score. Incremented by dot collection (+5)
          and by remaining HP on level completion (HP*5).
          Reset to 0 on game over.

  HS      High score. Persists across all games. Updated
          each step using boolean arithmetic (no IF needed).

  LV      Current level. Incremented at line 2 each time
          a new level begins. Never reset on game over --
          only SC resets, so difficulty carries forward.
          (Note: reset SC=0:LV=0 on game over intentional.)

  HP      Hit points. Set to 5+LV*5 per level, capped at 25.
          Lost by touching electrified walls or the hunter.
          Remaining HP at level exit earns bonus score.

  M(38,20) The maze grid. 39 columns x 21 rows.
          M=0  open passage
          M=1  electrified wall
          M=2  score dot (CHR$(144))
          Indexed as M(x,y) where x=0..38, y=0..20.
          Odd x and odd y coordinates are room cells;
          even coordinates are wall or passage cells.

  V(18,9) Visited flags for the maze generator.
          V(x,y)=1 means room cell (x,y) has been visited
          by the DFS. Cleared to 0 at level start.

  SX(200) DFS stack -- X coordinates of visited cells.
  SY(200) DFS stack -- Y coordinates of visited cells.
  SP      DFS stack pointer. Starts at 1 (seed cell).

  A(4),B(4) Temporary arrays storing unvisited neighbour
          coordinates during DFS neighbour enumeration.

  NC      Neighbour count for current DFS cell.

  PX,PY   Player X and Y position in maze grid coordinates
          (not screen coordinates). Player displayed at
          LOCATE PX+1, PY+1 due to 1-based LOCATE.

  dx,dy   Movement delta. Set from INKEY$ each frame.
          O=left (dx=-1), P=right (dx=+1),
          E=up (dy=-1), D=down (dy=+1).

  k$      Current keypress from INKEY$ (non-blocking).

  CX,CY   Hunter X and Y position in maze coordinates.
          Active from Level 4 only. Initialised to 0 on
          Levels 1-3 using boolean arithmetic gate.

  HT      Hunter contact flag. Set to (LV>3)*(CX=PX)*(CY=PY)
          each step. In Locomotive BASIC TRUE=-1, so HT is
          0 (no contact) or -1 (contact). Used to drain HP
          and flash the border without an IF statement.

============================================================
LINE BY LINE BREAKDOWN
============================================================

LINE 1 - ONE TIME INITIALISATION
----------------------------------
1 CLS:MODE 1:BORDER 0:RANDOMIZE TIME:SPEED INK 250,12:INK 0,0:
  INK 1,2:INK 2,22:INK 3,2:DIM M(38,20),V(18,9),SX(200),
  SY(200),A(4),B(4):SC=0:HS=0:LV=0:HP=0

  CLS:MODE 1
    Clears screen and sets Mode 1: 40 columns x 25 rows,
    4 colour pens.

  BORDER 0
    Sets screen border to black.

  RANDOMIZE TIME
    Seeds the random number generator from the CPC hardware
    timer. Ensures a unique maze every game.

  SPEED INK 250,12
    Sets the global hardware INK flash rate. The CPC timer
    runs at 50Hz. 250 = 5 seconds on, 12 = 0.24 seconds off.
    This controls how all flashing INKs behave, set once
    here and never changed -- no per-frame cost.

  INK 0,0 / INK 1,2 / INK 2,22 / INK 3,2
    Maps four colour pens to hardware colours:
      Pen 0 = black (background)
      Pen 1 = blue (exit marker, screen edge)
      Pen 2 = bright green (player, dots, hunter, status)
      Pen 3 = blue (walls, initial -- updated per level)

  DIM M(38,20),V(18,9),SX(200),SY(200),A(4),B(4)
    Declares all arrays on line 1 so the DIM is never
    re-executed. The game restarts via GOTO 2, skipping
    line 1, avoiding Locomotive BASIC's "Array already
    dimensioned" error.

  SC=0:HS=0:LV=0:HP=0
    One-time initialisation of all game variables. HS is
    only zeroed here -- never on restart -- so the high
    score persists across all games.

LINE 2 - NEW LEVEL SETUP
--------------------------
2 LV=LV+1:HP=5+LV*5:CLS:LOCATE 12,12:PEN 2:?"GENERATING...":
  INK 3,2+(LV>1)*2,2:INK 1,2+(LV>3)*2,2:
  FOR y=0 TO 20:FOR x=0 TO 38:M(x,y)=1:NEXT:NEXT:
  FOR y=0 TO 9:FOR x=0 TO 18:M(2*x+1,2*y+1)=0:V(x,y)=0:
  NEXT:NEXT:SP=1:SX(1)=0:SY(1)=9:V(0,9)=1

  LV=LV+1:HP=5+LV*5
    Increments level and sets health. Level 1=10HP,
    Level 2=15HP, Level 3=20HP, Level 4+=25HP (capped
    on line 3).

  CLS:LOCATE 12,12:PEN 2:?"GENERATING..."
    Clears screen and shows a message while the maze is
    being built (maze generation takes several seconds
    in BASIC).

  INK 3,2+(LV>1)*2,2
    Sets the wall colour flash behaviour:
      Level 1:   (LV>1)=0  -> INK 3,2,2  solid blue
      Level 2+:  (LV>1)=-1 -> INK 3,2,0  flash blue/black
    In Locomotive BASIC TRUE=-1, so 2+(LV>1)*2 = 2+(-1)*2 = 0
    when above Level 1. The middle wall section flashes from
    Level 2 onwards.

  INK 1,2+(LV>3)*2,2
    Same technique for the full wall flash at Level 4+:
      Level 1-3: INK 1,2,2  solid blue
      Level 4+:  INK 1,2,0  flash blue/black
    Combined with INK 3, this makes the entire maze flash
    from Level 4.

  FOR y/x loops: M(x,y)=1
    Fills the entire maze grid with walls (M=1).

  FOR y/x loops: M(2*x+1,2*y+1)=0:V(x,y)=0
    Clears every odd,odd cell to open passage (M=0) and
    resets the visited flags. These are the 19x10 room
    cells. Even-coordinate cells remain as walls until
    the DFS carves passages between them.

  SP=1:SX(1)=0:SY(1)=9:V(0,9)=1
    Seeds the DFS stack with room cell (0,9) -- the
    bottom-left corner (player start area). Marks it
    visited.

LINE 3 - HP CAP AND MAZE FINALISATION OR DFS BACKTRACK
--------------------------------------------------------
3 HP=HP+(HP-25)*(HP>25):IF SP=0 THEN M(37,0)=0:
  FOR j=1 TO 19 STEP 2:FOR i=1 TO 37 STEP 2:M(i,j)=2:
  NEXT:NEXT:CX=-(LV>3)*(1+2*INT(RND*19)):
  CY=-(LV>3)*(1+2*INT(RND*10)):GOTO 6

  HP=HP+(HP-25)*(HP>25)
    Caps HP at 25 using boolean arithmetic.
    When HP>25: (HP>25)=-1, so HP=HP+(HP-25)*(-1)=25.
    When HP<=25: (HP>25)=0, so HP unchanged.

  IF SP=0 THEN ...
    When the DFS stack is empty (SP=0), maze generation
    is complete. Otherwise falls through to line 4 to
    continue DFS.

  M(37,0)=0
    Opens the exit cell at top-right of the maze.

  FOR j/i loops: M(i,j)=2
    Places score dots (M=2) in every odd,odd room cell.
    These are later consumed by the player (scoring +5)
    or the hunter (removed silently).

  CX=-(LV>3)*(1+2*INT(RND*19))
  CY=-(LV>3)*(1+2*INT(RND*10))
    Positions the hunter using a boolean level gate.
    On Levels 1-3: (LV>3)=0, so CX=CY=0 (inactive).
    On Level 4+:   (LV>3)=-1, so CX and CY are set to
    random odd coordinates in the valid room cell range.
    Odd coordinates always land on open room cells --
    no wall check needed.

  GOTO 6
    Jumps to maze rendering once generation is complete.

LINE 4 - DFS: READ CURRENT CELL AND FIND NEIGHBOURS
-----------------------------------------------------
4 cx=SX(SP):cy=SY(SP):NC=0:FOR d=1 TO 4:
  dx=-(d=4)+(d=3):dy=-(d=2)+(d=1):nx=cx+dx:ny=cy+dy:
  IF nx>=0 THEN IF nx<=18 THEN IF ny>=0 THEN IF ny<=9
  THEN IF V(nx,ny)=0 THEN NC=NC+1:A(NC)=nx:B(NC)=ny

  cx=SX(SP):cy=SY(SP)
    Reads the current cell from the top of the DFS stack.

  NC=0
    Resets the neighbour count for this cell.

  FOR d=1 TO 4
    Loops over four directions: up, down, left, right.

  dx=-(d=4)+(d=3):dy=-(d=2)+(d=1)
    Computes direction deltas using boolean arithmetic:
      d=1: dx=0, dy=+1  (down)
      d=2: dx=0, dy=-1  (up)
      d=3: dx=+1, dy=0  (right)
      d=4: dx=-1, dy=0  (left)

  Nested IF guards
    Locomotive BASIC evaluates both sides of AND even when
    the left is false, causing out-of-bounds array access.
    Nested IF statements are used instead to short-circuit
    safely: bounds are checked before V(nx,ny) is accessed.

  IF V(nx,ny)=0 THEN NC=NC+1:A(NC)=nx:B(NC)=ny
    If the neighbour is unvisited, adds it to the candidate
    list A/B and increments the count.

LINE 5 - DFS: BACKTRACK OR CARVE PASSAGE
-----------------------------------------
5 NEXT d:IF NC=0 THEN SP=SP-1:GOTO 3
  ELSE ri=INT(RND*NC)+1:nx=A(ri):ny=B(ri):
  M(cx+nx+1,cy+ny+1)=0:V(nx,ny)=1:
  SP=SP+1:SX(SP)=nx:SY(SP)=ny:GOTO 4

  NEXT d
    Completes the direction loop from line 4.

  IF NC=0 THEN SP=SP-1:GOTO 3
    No unvisited neighbours: backtrack by popping the stack.
    GOTO 3 checks if SP=0 (generation complete) or loops
    back to line 4 to try the new top-of-stack cell.

  ri=INT(RND*NC)+1
    Picks a random unvisited neighbour from the candidates.

  M(cx+nx+1,cy+ny+1)=0
    Carves the wall between the current cell and the chosen
    neighbour. The wall cell sits at the midpoint between
    the two room cells: (cx+nx+1, cy+ny+1) in grid coords
    maps to the correct wall position.

  V(nx,ny)=1:SP=SP+1:SX(SP)=nx:SY(SP)=ny:GOTO 4
    Marks the neighbour visited, pushes it onto the stack,
    and loops back to process it next.

LINE 6 - RENDER MAZE AND INITIAL STATUS BAR
--------------------------------------------
6 CLS:FOR y=0 TO 20:FOR x=0 TO 38:
  PAPER -(M(x,y)=1)*(3-(LV<4)*2*(y<6 OR y>12)):
  LOCATE x+1,y+1:? CHR$(32-112*(M(x,y)=2));:
  NEXT x:NEXT y:PX=1:PY=19:PAPER 0:
  LOCATE 40,1:PEN 1:?"<";:
  LOCATE 1,23:PEN 2:?"SC:";SC;"  HI:";HS;"  LV:";LV;"  HP:";HP

  PAPER -(M(x,y)=1)*(3-(LV<4)*2*(y<6 OR y>12))
    Sets background colour for each cell:
    - Non-wall cells: -(0)*... = PAPER 0 (black)
    - Wall cells (M=1): -(−1)*... = expression value
      The expression (3-(LV<4)*2*(y<6 OR y>12)):
        Levels 1-3, outer rows (y<6 or y>12): PAPER 3 (blue)
        Levels 1-3, middle rows 6-12:          PAPER 1 (blue)
        Level 4+: (LV<4)=0, all walls:         PAPER 3
      This gives the middle section a different pen so
      INK 3 (which flashes from Level 2) only affects
      the middle rows, creating a visual depth effect.

  CHR$(32-112*(M(x,y)=2))
    Prints the correct character per cell:
      M=2 (dot): 32-(112*-1) = 32+112 = CHR$(144) -- dot
      Other:     32-(112*0)  = CHR$(32) -- space

  PX=1:PY=19
    Places player at bottom-left room cell (maze coords).

  LOCATE 40,1:PEN 1:?"<"
    Draws the exit marker at column 40, row 1 -- the
    top-right corner.

  Status bar
    Prints score, high score, level and HP at row 23.

LINE 7 - DRAW PLAYER AND READ INPUT
-------------------------------------
7 LOCATE PX+1,PY+1:PEN 2:PAPER 0:
  ? CHR$(248+((PX+PY)AND 3));:
  k$=INKEY$:dx=-(k$="p")+(k$="o"):dy=-(k$="d")+(k$="e"):
  IF dx=0 AND dy=0 THEN 7

  CHR$(248+((PX+PY)AND 3))
    Animates the player sprite without a frame counter.
    (PX+PY) changes by 1 with every step. AND 3 masks to
    0-3, cycling through CHR$(248)-CHR$(251) -- the four
    built-in CPC walking figure frames.

  dx/dy from INKEY$
    Boolean arithmetic sets movement direction:
      (k$="p")=-1 when P held -> dx=0-(-1)=+1 (right)
      (k$="o")=-1 when O held -> dx=(-1)+0=-1 (left)
      Similarly E=up (dy=-1), D=down (dy=+1).

  IF dx=0 AND dy=0 THEN 7
    No key pressed: loop back and wait.

LINE 8 - WALL COLLISION CHECK
-------------------------------
8 IF M(PX+dx,PY+dy)=1 THEN HP=HP-1:BORDER 24:
  FOR t=1 TO 50:NEXT:BORDER 0:
  IF HP<1 THEN PEN 2:LOCATE 12,12:?"*** GAME OVER ***":
  FOR t=1 TO 2000:NEXT:SC=0:LV=0:GOTO 2 ELSE GOTO 10

  IF M(PX+dx,PY+dy)=1
    Checks the cell the player is trying to enter.
    M=1 means electrified wall.

  HP=HP-1:BORDER 24:FOR t=1 TO 50:NEXT:BORDER 0
    Costs 1 HP and flashes the border yellow briefly.
    BORDER 24 = yellow. The delay loop provides visible flash
    duration. BORDER 0 restores black.

  IF HP<1 THEN ... GAME OVER
    No HP remaining: prints GAME OVER at screen centre
    (no CLS so the maze remains visible behind the message),
    pauses, resets SC and LV, restarts at line 2.

  ELSE GOTO 10
    Wall hit but still alive: routes through line 10 to
    redraw the player and update the status bar without
    moving. The player stays in place.

LINE 9 - MOVE PLAYER, SCORE DOTS, MOVE HUNTER
-----------------------------------------------
9 LOCATE PX+1,PY+1:PAPER 0:?" ";:
  PX=PX+dx:PY=PY+dy:
  SC=SC-5*(M(PX,PY)=2):M(PX,PY)=0:
  HS=HS+(HS-SC)*(SC>HS):
  IF LV>3 THEN LOCATE CX+1,CY+1:PAPER 0:?" ";:
  M(CX,CY)=0:CX=1+2*INT(RND*19):CY=1+2*INT(RND*10):
  LOCATE CX+1,CY+1:PEN 2:? CHR$(225);

  LOCATE PX+1,PY+1:PAPER 0:?" "
    Erases the player sprite at the old position before
    updating PX/PY.

  PX=PX+dx:PY=PY+dy
    Moves the player. Safe because line 8 has already
    confirmed the destination is not a wall.

  SC=SC-5*(M(PX,PY)=2)
    Awards dot bonus using boolean arithmetic.
    (M(PX,PY)=2) = -1 when a dot is present.
    SC = SC - 5*(-1) = SC+5. A double negative = addition.

  M(PX,PY)=0
    Clears the cell. Since line 8 guarantees M<>1 here,
    this safely zeroes dots (M=2) and open cells (M=0)
    without needing a conditional check.

  HS=HS+(HS-SC)*(SC>HS)
    Updates high score without IF.
    (SC>HS)=-1 when score exceeds high score.
    HS = HS+(HS-SC)*(-1) = HS-(HS-SC) = SC.
    When SC<=HS: (SC>HS)=0, HS unchanged.

  IF LV>3 THEN ... hunter movement
    Hunter is only active from Level 4.
    Erases old hunter position and clears M(CX,CY)=0
    (consuming any dot underneath).
    Teleports to a new random odd,odd cell. Odd coordinates
    always map to open room cells -- no wall check needed.
    Redraws hunter as CHR$(225) in PEN 2.

LINE 10 - REDRAW PLAYER, UPDATE STATUS, CHECK EXIT/HUNTER
-----------------------------------------------------------
10 LOCATE PX+1,PY+1:PEN 2:PAPER 0:
   ? CHR$(248+((PX+PY)AND 3));:
   LOCATE 1,23:?"SC:";SC;"  HI:";HS;"  LV:";LV;"  HP:";HP:
   HT=(LV>3)*(CX=PX)*(CY=PY):HP=HP+HT:BORDER-HT*24:
   IF PX=37 AND PY=0 THEN ?"LEVEL UP!":SC=SC+HP*5:
   FOR t=1 TO 9:NEXT:GOTO 2 ELSE GOTO 7

  Redraws player sprite at new position with animation.

  Status bar update
    Refreshes SC, HS, LV and HP at row 23.

  HT=(LV>3)*(CX=PX)*(CY=PY)
    Hunter contact: HT=0 normally, HT=-1 on contact.
    Triple boolean product:
      (LV>3)      = -1 when Level 4+
      (CX=PX)     = -1 when same column
      (CY=PY)     = -1 when same row
    Product of three -1s = -1 (contact confirmed).

  HP=HP+HT
    HP = HP+(-1) = HP-1 on contact. Drains 1 HP silently.

  BORDER-HT*24
    -(-1)*24 = BORDER 24 (white flash) on contact.
    -(0)*24  = BORDER 0  (black, normal) otherwise.
    Resets automatically every player step.

  IF PX=37 AND PY=0 THEN ... LEVEL UP
    Player reached exit. Adds HP*5 bonus to score,
    brief flash of "LEVEL UP!", then GOTO 2 for next level.

  ELSE GOTO 7
    Not at exit: loop back to wait for next keypress.

============================================================
MAZE GENERATION: DEPTH-FIRST SEARCH EXPLAINED
============================================================

Volt Maze generates a perfect maze (no loops, every cell
reachable) using a algorithm called Depth-First Search (DFS),
also known as the Recursive Backtracker.

WHAT IS DEPTH-FIRST SEARCH?
  DFS is a graph traversal algorithm that explores as far
  as possible down one path before backtracking to try
  another. Applied to maze generation, it carves passages
  through a grid of rooms by always pushing deeper into
  unvisited territory until it gets stuck, then retreating
  to find a new direction.

  The result is a maze with long, winding corridors and
  relatively few dead ends -- a style that feels organic
  and hand-crafted rather than mechanical.

HOW IT WORKS STEP BY STEP:
  1. Start with a grid where every cell is a wall.
  2. Mark a starting cell as visited and push it onto
     a stack.
  3. Look at the cell on top of the stack. Find all its
     unvisited neighbours.
  4. If there are unvisited neighbours:
       - Pick one at random.
       - Carve a passage (remove the wall) between the
         current cell and the chosen neighbour.
       - Mark the neighbour as visited.
       - Push the neighbour onto the stack.
       - Repeat from step 3.
  5. If there are NO unvisited neighbours:
       - Backtrack: pop the current cell off the stack.
       - Repeat from step 3 with the new top of stack.
  6. When the stack is empty, every cell has been visited
     and the maze is complete.

IN VOLT MAZE:
  The maze grid is 19 columns x 10 rows of room cells,
  stored at odd,odd coordinates in the M() array. The
  walls between rooms sit at the even coordinates in
  between. Carving a passage means setting the wall cell
  between two rooms to M=0 (open).

  The DFS stack is implemented using arrays SX() and SY()
  with pointer SP, since Locomotive BASIC does not support
  true recursion reliably for deep stacks. Lines 4 and 5
  implement the core loop: line 4 enumerates unvisited
  neighbours, line 5 either backtracks (SP=SP-1) or carves
  a passage and pushes the next cell.

  The seed cell is the bottom-left room (0,9) -- directly
  behind the player start position -- so the maze always
  begins generating from the player's corner outward.

WHY DFS FOR A MAZE?
  DFS mazes have a distinctive character: long winding
  passages that reward memory and spatial reasoning. You
  can often sense the "spine" of the maze as you explore.
  This makes them well suited to a game where remembering
  where you have been is part of the challenge -- the very
  quality that inspired the original Maze Craze on the
  Atari 2600 in 1980.

============================================================
DESIGN NOTES
============================================================

CPC BASIC QUIRK: BORDER RESETS THE SPEED INK TIMER
  Locomotive BASIC has an undocumented behaviour: issuing
  any BORDER command resets the SPEED INK flash timer back
  to the start of the primary colour phase. This means that
  if BORDER is called frequently -- such as every player
  step -- the INK flash cycle is continuously restarted and
  the walls never complete a full flash cycle.

  In Volt Maze, BORDER 0 is issued on line 10 every time
  the player moves (via BORDER-HT*24, which evaluates to
  BORDER 0 when there is no hunter contact). This
  effectively kept resetting the timer to the primary colour
  phase on every keypress, making the walls appear static.

  The fix was to deliberately exploit this behaviour rather
  than fight it. By setting the primary colour to black
  (INK 3,2+(LV>1)*2,2 from Level 2 -- primary=0/black,
  secondary=2/blue) and SPEED INK 250,12 (long black phase,
  brief blue flash), the constant BORDER reset now holds the
  walls in their dominant black state. The brief blue flash
  only occurs when the timer completes naturally between
  player steps, giving the intended threatening flicker
  effect without the timer reset causing visible problems.

  This quirk may be a bug in Locomotive BASIC's firmware,
  or an undocumented side effect of the way the hardware
  colour registers and the SPEED INK counter share state.
  Either way, it is worth noting for anyone building
  programs that combine BORDER colour changes with flashing
  INK animations.

WHY ITERATIVE DFS INSTEAD OF RECURSIVE?
  Locomotive BASIC does not support recursive subroutines
  reliably for deep stacks. A software stack using arrays
  SX/SY with pointer SP replicates recursive DFS without
  any risk of stack overflow, regardless of maze size.

WHY NESTED IF INSTEAD OF AND?
  In Locomotive BASIC, both sides of AND are always
  evaluated even if the left side is false. For array
  bounds checks this causes an out-of-bounds error before
  the condition can prevent it. Nested IF statements
  provide true short-circuit evaluation.

WHY (PX+PY) AND 3 FOR ANIMATION?
  This avoids a separate frame counter variable. Each step
  changes PX or PY by 1, so PX+PY changes by exactly 1,
  cycling CHR$(248)-CHR$(251) in sequence. AND 3 masks to
  the range 0-3 without any IF or MOD required.

WHY ? INSTEAD OF PRINT?
  In Locomotive BASIC, ? is a valid one-character
  abbreviation for PRINT. Every substitution saves 4
  characters -- critical for fitting all logic within the
  256-character-per-line limit of the EXTREME-256 category.

WHY BOOLEAN ARITHMETIC THROUGHOUT?
  Locomotive BASIC returns -1 for TRUE and 0 for FALSE.
  This allows arithmetic to replace IF statements in many
  places, saving significant characters per line:
    SC=SC-5*(M(PX,PY)=2)      (dot scoring)
    HS=HS+(HS-SC)*(SC>HS)     (high score update)
    HP=HP+(HP-25)*(HP>25)     (HP cap at 25)
    HT=(LV>3)*(CX=PX)*(CY=PY) (hunter contact)
    BORDER-HT*24              (border flash on contact)
    INK 3,2+(LV>1)*2,2        (wall flash from Level 2)
    CX=-(LV>3)*(...)           (hunter position gating)

============================================================
END OF DOCUMENT
============================================================
