@Override
  protected void onZap(int cell) {

    int reach = Math.min(Ballistica.distance, power() + 4);

    boolean mapUpdated = false;
    for (int i = 1; i < reach; i++) {

      int c = Ballistica.trace[i];

      int before = Dungeon.level.map[c];

      Char ch = Actor.findChar(c);
      if (ch != null) {
        Actor.addDelayed(new Swap(curUser, ch), -1);
        break;
      }

      Heap heap = Dungeon.level.heaps.get(c);
      if (heap != null) {
        switch (heap.type) {
          case HEAP:
            transport(heap);
            break;
          case CHEST:
          case MIMIC:
          case TOMB:
          case SKELETON:
            heap.open(curUser);
            break;
          default:
        }

        break;
      }

      Dungeon.level.press(c, null);
      if (before == Terrain.OPEN_DOOR) {
        Level.set(c, Terrain.DOOR);
        GameScene.updateMap(c);
      } else if (Level.water[c]) {
        GameScene.ripple(c);
      }

      mapUpdated = mapUpdated || Dungeon.level.map[c] != before;
    }

    if (mapUpdated) {
      Dungeon.observe();
    }
  }
  public static void paint(Level level, Room room) {

    fill(level, room, Terrain.WALL);
    fill(level, room, 1, Terrain.FIRE_TRAP);
    fill(level, room, 2, Terrain.EMPTY_SP);

    for (int i = 0; i < 2; i++) {
      int pos;
      do {
        pos = room.random();
      } while (level.map[pos] != Terrain.EMPTY_SP);
      level.drop(
          Generator.random(Random.oneOf(Generator.Category.ARMOR, Generator.Category.WEAPON)), pos);
    }

    for (Room.Door door : room.connected.values()) {
      door.set(Room.Door.Type.UNLOCKED);
      drawInside(level, room, door, 1, Terrain.EMPTY);
    }

    Blacksmith npc = new Blacksmith();
    do {
      npc.pos = room.random(1);
    } while (level.heaps.get(npc.pos) != null);
    level.mobs.add(npc);
    Actor.occupyCell(npc);
  }
  @Override
  protected void evolve() {
    super.evolve();

    if (volume > 0) {

      boolean mapUpdated = false;

      for (int i = 0; i < LENGTH; i++) {
        if (off[i] > 0) {
          int c = Dungeon.level.map[i];
          int c1 = c;
          if (c == Terrain.EMPTY || c == Terrain.EMBERS || c == Terrain.EMPTY_DECO) {
            c1 = cur[i] > 9 ? Terrain.HIGH_GRASS : Terrain.GRASS;
          } else if (c == Terrain.GRASS && cur[i] > 9) {
            c1 = Terrain.HIGH_GRASS;
          }

          if (c1 != c) {
            Level.set(i, Terrain.HIGH_GRASS);
            mapUpdated = true;

            GameScene.updateMap(i);
            if (Dungeon.visible[i]) {
              GameScene.discoverTile(i, c);
            }
          }

          Char ch = Actor.findChar(i);
          if (ch != null) {
            Buff.prolong(ch, Roots.class, TICK);
          }
        }
      }

      if (mapUpdated) {
        Dungeon.observe();
      }
    }
  }