anchor.diff:              ctx.fillStyle = "black";
           }
           ctx.textAlign = "center";
  -        ctx.textBaseline = "middle";
  +        ctx.textBaseline = "bottom";
           ctx.font = "37pt Calibri";
           ctx.fillText("@", x, y);
       }
   
  -    void toString() { return "Character";}
  +    String toString() { return "Character";}
   }
   
   
   // a grid square
   class Square {
       Occupant occupant; // an occupant or NULL
  -
  -    Square() : occupant = null;
  +    CellMarker marker;
  +
  +
  +    Square() : occupant = null, marker = null;
   
       bool isOccupied() {
           return occupant != null;
       }
   
  +    bool isMarked() {
  +        return marker != null;
  +    }
  +
       bool isEmpty() {
           return !isOccupied();
       }
  
positive.code: abstract class Monster extends Occupant {
      Monster(DungeonState ds) : super(ds);
      Action takeTurn();
  }
  
  class Zombie extends Monster {
  
negative.code:     Hero hero;
      int turn;
      bool hero_turn;
      bool hero_is_dead;
      Random rng;
  
      DungeonState(this.dg)
      : monsters = [], turn=0, hero_turn=true {
          rng = new Random();
          dg.drawGrid();
          dg.status.updateStatus(dg.ctx, "Tiny dungeon started");
      }
  
      void start() {
          dg.drawGrid();
          spawnHero(new GridPoint(0,0));
          spawnMonster(new GridPoint(1,2), new Zombie(this, false));
      }
  
      void restart() {
          monsters = [];
          turn = 0;
          hero_turn = true;
          hero_is_dead = false;
          dg.grid.clearAll();
          start();
          dg.status.updateStatus(dg.ctx, "Tiny dungeon restarted");
      }
  
      void reportTurn() {
          dg.status.updateStatus(dg.ctx, "====> Turn: " + (1+turn).toString() + " (your move)");
      }
  
      void spawn(Occupant o, GridPoint p) {
  