@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();
    }
  }
  private void transport(Heap heap) {
    Item item = heap.pickUp();
    if (item.doPickUp(curUser)) {

      if (item instanceof Dewdrop) {
        // Do nothing
      } else {
        if (((item instanceof ScrollOfUpgrade || item instanceof ScrollOfEnchantment)
                && ((Scroll) item).isKnown())
            || ((item instanceof PotionOfStrength || item instanceof PotionOfMight)
                && ((Potion) item).isKnown())) {
          GLog.p(TXT_YOU_NOW_HAVE, item.name());
        } else {
          GLog.i(TXT_YOU_NOW_HAVE, item.name());
        }
      }

    } else {
      Dungeon.level.drop(item, curUser.pos).sprite.drop();
    }
  }