예제 #1
0
  private void jump() {
    timeToJump = JUMP_DELAY;

    for (int i = 0; i < 4; i++) {
      int trapPos;
      do {
        trapPos = Random.Int(Level.LENGTH);
      } while (!Level.fieldOfView[trapPos] || !Level.passable[trapPos]);

      if (Dungeon.level.map[trapPos] == Terrain.INACTIVE_TRAP) {
        Level.set(trapPos, Terrain.POISON_TRAP);
        GameScene.updateMap(trapPos);
        ScrollOfMagicMapping.discover(trapPos);
      }
    }

    int newPos;
    do {
      newPos = Random.Int(Level.LENGTH);
    } while (!Level.fieldOfView[newPos]
        || !Level.passable[newPos]
        || (enemy != null && Level.adjacent(newPos, enemy.pos))
        || Actor.findChar(newPos) != null);

    sprite.move(pos, newPos);
    move(newPos);

    if (Dungeon.visible[newPos]) {
      CellEmitter.get(newPos).burst(Speck.factory(Speck.WOOL), 6);
      Sample.INSTANCE.play(Assets.SND_PUFF);
    }

    spend(1 / speed());
  }
  public static void paint(Level level, Room room) {

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

    Room.Door entrance = room.entrance();

    Point pot = null;
    if (entrance.x == room.left) {
      pot = new Point(room.right - 1, Random.Int(2) == 0 ? room.top + 1 : room.bottom - 1);
    } else if (entrance.x == room.right) {
      pot = new Point(room.left + 1, Random.Int(2) == 0 ? room.top + 1 : room.bottom - 1);
    } else if (entrance.y == room.top) {
      pot = new Point(Random.Int(2) == 0 ? room.left + 1 : room.right - 1, room.bottom - 1);
    } else if (entrance.y == room.bottom) {
      pot = new Point(Random.Int(2) == 0 ? room.left + 1 : room.right - 1, room.top + 1);
    }
    set(level, pot, Terrain.ALCHEMY);

    Alchemy alchemy = new Alchemy();
    alchemy.seed(pot.x + level.getWidth() * pot.y, 1);
    level.blobs.put(Alchemy.class, alchemy);

    int n = Random.IntRange(2, 3);
    for (int i = 0; i < n; i++) {
      int pos;
      do {
        pos = room.random(level);
      } while (level.map[pos] != Terrain.EMPTY_SP || level.getHeap(pos) != null);
      level.drop(prize(level), pos);
    }

    entrance.set(Room.Door.Type.LOCKED);
    level.addItemToSpawn(new IronKey());
  }
  private static Item prize(Level level) {

    Item prize = level.itemToSpanAsPrize();
    if (prize instanceof Potion) {
      return prize;
    } else if (prize != null) {
      level.addItemToSpawn(prize);
    }

    return Generator.random(Generator.Category.POTION);
  }
예제 #4
0
  public static void paint(Level level, Room room) {

    Integer traps[] = {
      Terrain.TOXIC_TRAP,
      Terrain.TOXIC_TRAP,
      Terrain.TOXIC_TRAP,
      Terrain.PARALYTIC_TRAP,
      Terrain.PARALYTIC_TRAP,
      !Dungeon.bossLevel(Dungeon.depth + 1) ? Terrain.CHASM : Terrain.SUMMONING_TRAP
    };
    fill(level, room, Terrain.WALL);
    fill(level, room, 1, Random.element(traps));

    Room.Door door = room.entrance();
    door.set(Room.Door.Type.REGULAR);

    int lastRow =
        level.map[room.left + 1 + (room.top + 1) * Level.WIDTH] == Terrain.CHASM
            ? Terrain.CHASM
            : Terrain.EMPTY;

    int x = -1;
    int y = -1;
    if (door.x == room.left) {
      x = room.right - 1;
      y = room.top + room.height() / 2;
      fill(level, x, room.top + 1, 1, room.height() - 1, lastRow);
    } else if (door.x == room.right) {
      x = room.left + 1;
      y = room.top + room.height() / 2;
      fill(level, x, room.top + 1, 1, room.height() - 1, lastRow);
    } else if (door.y == room.top) {
      x = room.left + room.width() / 2;
      y = room.bottom - 1;
      fill(level, room.left + 1, y, room.width() - 1, 1, lastRow);
    } else if (door.y == room.bottom) {
      x = room.left + room.width() / 2;
      y = room.top + 1;
      fill(level, room.left + 1, y, room.width() - 1, 1, lastRow);
    }

    int pos = x + y * Level.WIDTH;
    if (Random.Int(3) == 0) {
      if (lastRow == Terrain.CHASM) {
        set(level, pos, Terrain.EMPTY);
      }
      level.drop(prize(level), pos).type = Heap.Type.CHEST;
    } else {
      set(level, pos, Terrain.PEDESTAL);
      level.drop(prize(level), pos);
    }

    level.addItemToSpawn(new PotionOfLevitation());
  }
예제 #5
0
  public static void reallyDie(Object cause) {

    int length = Level.LENGTH;
    int[] map = Dungeon.level.map;
    boolean[] visited = Dungeon.level.visited;
    boolean[] discoverable = Level.discoverable;

    for (int i = 0; i < length; i++) {

      int terr = map[i];

      if (discoverable[i]) {

        visited[i] = true;
        if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
          Level.set(i, Terrain.discover(terr));
          GameScene.updateMap(i);
        }
      }
    }

    Bones.leave();

    Dungeon.observe();

    Dungeon.hero.belongings.identify();

    GameScene.gameOver();

    if (cause instanceof Hero.Doom) {
      ((Hero.Doom) cause).onDeath();
    }

    Dungeon.deleteGame(Dungeon.hero.heroClass, true);
  }
예제 #6
0
  @Override
  public void onOperateComplete() {

    if (curAction instanceof HeroAction.Unlock) {

      if (theKey != null) {
        theKey.detach(belongings.backpack);
        theKey = null;
      }

      int doorCell = ((HeroAction.Unlock) curAction).dst;
      int door = Dungeon.level.map[doorCell];

      Level.set(doorCell, door == Terrain.LOCKED_DOOR ? Terrain.DOOR : Terrain.UNLOCKED_EXIT);
      GameScene.updateMap(doorCell);

    } else if (curAction instanceof HeroAction.OpenChest) {

      if (theKey != null) {
        theKey.detach(belongings.backpack);
        theKey = null;
      }

      Heap heap = Dungeon.level.heaps.get(((HeroAction.OpenChest) curAction).dst);
      if (heap.type == Type.SKELETON) {
        Sample.INSTANCE.play(Assets.SND_BONES);
      }
      heap.open(this);
    }
    curAction = null;

    super.onOperateComplete();
  }
예제 #7
0
  public static void resetLevel() {

    Actor.clear();

    Arrays.fill(visible, false);

    level.reset();
    switchLevel(level, level.entrance);
  }
예제 #8
0
 @Override
 protected boolean doAttack(Char enemy) {
   timeToJump--;
   if (timeToJump <= 0 && Level.adjacent(pos, enemy.pos)) {
     jump();
     return true;
   } else {
     return super.doAttack(enemy);
   }
 }
예제 #9
0
  private boolean actOpenChest(HeroAction.OpenChest action) {
    int dst = action.dst;
    if (Level.adjacent(pos, dst) || pos == dst) {

      Heap heap = Dungeon.level.heaps.get(dst);
      if (heap != null
          && (heap.type == Type.CHEST
              || heap.type == Type.TOMB
              || heap.type == Type.SKELETON
              || heap.type == Type.LOCKED_CHEST
              || heap.type == Type.CRYSTAL_CHEST)) {

        theKey = null;

        if (heap.type == Type.LOCKED_CHEST || heap.type == Type.CRYSTAL_CHEST) {

          theKey = belongings.getKey(GoldenKey.class, Dungeon.depth);

          if (theKey == null) {
            GLog.w(TXT_LOCKED_CHEST);
            ready();
            return false;
          }
        }

        switch (heap.type) {
          case TOMB:
            Sample.INSTANCE.play(Assets.SND_TOMB);
            Camera.main.shake(1, 0.5f);
            break;
          case SKELETON:
            break;
          default:
            Sample.INSTANCE.play(Assets.SND_UNLOCK);
        }

        spend(Key.TIME_TO_UNLOCK);
        sprite.operate(dst);

      } else {
        ready();
      }

      return false;

    } else if (getCloser(dst)) {

      return true;

    } else {
      ready();
      return false;
    }
  }
예제 #10
0
  @SuppressWarnings("deprecation")
  public static void switchLevel(final Level level, int pos) {

    nightMode = new Date().getHours() < 7;

    Dungeon.level = level;
    Actor.init();

    Actor respawner = level.respawner();
    if (respawner != null) {
      Actor.add(level.respawner());
    }

    hero.pos = pos != -1 ? pos : level.exit;

    Light light = hero.buff(Light.class);
    hero.viewDistance =
        light == null ? level.viewDistance : Math.max(Light.DISTANCE, level.viewDistance);

    observe();
  }
예제 #11
0
  public static void paint(Level level, Room room) {

    fill(level, room, Terrain.WALL);
    fill(level, room, 1, Terrain.EMPTY);

    Room.Door entrance = room.entrance();
    entrance.set(Room.Door.Type.LOCKED);

    Point well = null;
    if (entrance.x == room.left) {
      well = new Point(room.right - 1, Random.Int(2) == 0 ? room.top + 1 : room.bottom - 1);
    } else if (entrance.x == room.right) {
      well = new Point(room.left + 1, Random.Int(2) == 0 ? room.top + 1 : room.bottom - 1);
    } else if (entrance.y == room.top) {
      well = new Point(Random.Int(2) == 0 ? room.left + 1 : room.right - 1, room.bottom - 1);
    } else if (entrance.y == room.bottom) {
      well = new Point(Random.Int(2) == 0 ? room.left + 1 : room.right - 1, room.top + 1);
    }
    set(level, well, Terrain.EMPTY_WELL);

    int remains = room.random();
    while (level.map[remains] == Terrain.EMPTY_WELL) {
      remains = room.random();
    }

    level.drop(new IronKey(), remains).type = Type.SKELETON;

    if (Random.Int(5) == 0) {
      level.drop(Generator.random(Generator.Category.RING), remains);
    } else {
      level.drop(
          Generator.random(Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR)),
          remains);
    }

    int n = Random.IntRange(1, 2);
    for (int i = 0; i < n; i++) {
      level.drop(prize(level), remains);
    }
  }
예제 #12
0
  public static void observe() {

    if (level == null) {
      return;
    }

    level.updateFieldOfView(hero);
    System.arraycopy(Level.fieldOfView, 0, visible, 0, visible.length);

    BArray.or(level.visited, visible, level.visited);

    GameScene.afterObserve();
  }
예제 #13
0
  private static Item prize(Level level) {

    Item prize = level.itemToSpanAsPrize();
    if (prize != null) {
      return prize;
    }

    return Generator.random(
        Random.oneOf(
            Generator.Category.POTION,
            Generator.Category.SCROLL,
            Generator.Category.FOOD,
            Generator.Category.GOLD));
  }
예제 #14
0
  private boolean getCloser(final int target) {

    if (rooted) {
      return false;
    }

    int step = -1;

    if (Level.adjacent(pos, target)) {

      if (Actor.findChar(target) == null) {
        if (Level.pit[target] && !flying && !Chasm.jumpConfirmed) {
          Chasm.heroJump(this);
          interrupt();
          return false;
        }
        if (Level.passable[target] || Level.avoid[target]) {
          step = target;
        }
      }

    } else {

      int len = Level.LENGTH;
      boolean[] p = Level.passable;
      boolean[] v = Dungeon.level.visited;
      boolean[] m = Dungeon.level.mapped;
      boolean[] passable = new boolean[len];
      for (int i = 0; i < len; i++) {
        passable[i] = p[i] && (v[i] || m[i]);
      }

      step = Dungeon.findPath(this, pos, target, passable, Level.fieldOfView);
    }

    if (step != -1) {

      int oldPos = pos;
      move(step);
      sprite.move(oldPos, pos);
      spend(1 / speed());

      return true;

    } else {

      return false;
    }
  }
예제 #15
0
  @Override
  public int attackSkill(Char target) {

    int bonus = 0;
    for (Buff buff : buffs(RingOfAccuracy.Accuracy.class)) {
      bonus += ((RingOfAccuracy.Accuracy) buff).level;
    }
    float accuracy = (bonus == 0) ? 1 : (float) Math.pow(1.4, bonus);
    if (rangedWeapon != null && Level.distance(pos, target.pos) == 1) {
      accuracy *= 0.5f;
    }

    KindOfWeapon wep = rangedWeapon != null ? rangedWeapon : belongings.weapon;
    if (wep != null) {
      return (int) (attackSkill * accuracy * wep.acuracyFactor(this));
    } else {
      return (int) (attackSkill * accuracy);
    }
  }
예제 #16
0
  private static Item prize(Level level) {

    Item prize = level.itemToSpanAsPrize();
    if (prize != null) {
      return prize;
    }

    prize = Generator.random(Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR));

    for (int i = 0; i < 3; i++) {
      Item another =
          Generator.random(Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR));
      if (another.level > prize.level) {
        prize = another;
      }
    }

    return prize;
  }
예제 #17
0
  private boolean actUnlock(HeroAction.Unlock action) {
    int doorCell = action.dst;
    if (Level.adjacent(pos, doorCell)) {

      theKey = null;
      int door = Dungeon.level.map[doorCell];

      if (door == Terrain.LOCKED_DOOR) {

        theKey = belongings.getKey(IronKey.class, Dungeon.depth);

      } else if (door == Terrain.LOCKED_EXIT) {

        theKey = belongings.getKey(SkeletonKey.class, Dungeon.depth);
      }

      if (theKey != null) {

        spend(Key.TIME_TO_UNLOCK);
        sprite.operate(doorCell);

        Sample.INSTANCE.play(Assets.SND_UNLOCK);

      } else {
        GLog.w(TXT_LOCKED_DOOR);
        ready();
      }

      return false;

    } else if (getCloser(doorCell)) {

      return true;

    } else {
      ready();
      return false;
    }
  }
예제 #18
0
  private boolean actBuy(HeroAction.Buy action) {
    int dst = action.dst;
    if (pos == dst || Level.adjacent(pos, dst)) {

      ready();

      Heap heap = Dungeon.level.heaps.get(dst);
      if (heap != null && heap.type == Type.FOR_SALE && heap.size() == 1) {
        GameScene.show(new WndTradeItem(heap, true));
      }

      return false;

    } else if (getCloser(dst)) {

      return true;

    } else {
      ready();
      return false;
    }
  }
예제 #19
0
  public static int findPath(Char ch, int from, int to, boolean pass[], boolean[] visible) {

    if (Level.adjacent(from, to)) {
      return Actor.findChar(to) == null && (pass[to] || Level.avoid[to]) ? to : -1;
    }

    if (ch.flying || ch.buff(Amok.class) != null) {
      BArray.or(pass, Level.avoid, passable);
    } else {
      System.arraycopy(pass, 0, passable, 0, Level.LENGTH);
    }

    for (Actor actor : Actor.all()) {
      if (actor instanceof Char) {
        int pos = ((Char) actor).pos;
        if (visible[pos]) {
          passable[pos] = false;
        }
      }
    }

    return PathFinder.getStep(from, to, passable);
  }
예제 #20
0
  private boolean actAttack(HeroAction.Attack action) {

    enemy = action.target;

    if (Level.adjacent(pos, enemy.pos) && enemy.isAlive() && !pacified) {

      spend(attackDelay());
      sprite.attack(enemy.pos);

      return false;

    } else {

      if (Level.fieldOfView[enemy.pos] && getCloser(enemy.pos)) {

        return true;

      } else {
        ready();
        return false;
      }
    }
  }
예제 #21
0
  private boolean actInteract(HeroAction.Interact action) {

    NPC npc = action.npc;

    if (Level.adjacent(pos, npc.pos)) {

      ready();
      sprite.turnTo(pos, npc.pos);
      npc.interact();
      return false;

    } else {

      if (Level.fieldOfView[npc.pos] && getCloser(npc.pos)) {

        return true;

      } else {
        ready();
        return false;
      }
    }
  }
예제 #22
0
  public boolean search(boolean intentional) {

    boolean smthFound = false;

    int positive = 0;
    int negative = 0;
    for (Buff buff : buffs(RingOfDetection.Detection.class)) {
      int bonus = ((RingOfDetection.Detection) buff).level;
      if (bonus > positive) {
        positive = bonus;
      } else if (bonus < 0) {
        negative += bonus;
      }
    }
    int distance = 1 + positive + negative;

    float level = intentional ? (2 * awareness - awareness * awareness) : awareness;
    if (distance <= 0) {
      level /= 2 - distance;
      distance = 1;
    }

    int cx = pos % Level.WIDTH;
    int cy = pos / Level.WIDTH;
    int ax = cx - distance;
    if (ax < 0) {
      ax = 0;
    }
    int bx = cx + distance;
    if (bx >= Level.WIDTH) {
      bx = Level.WIDTH - 1;
    }
    int ay = cy - distance;
    if (ay < 0) {
      ay = 0;
    }
    int by = cy + distance;
    if (by >= Level.HEIGHT) {
      by = Level.HEIGHT - 1;
    }

    for (int y = ay; y <= by; y++) {
      for (int x = ax, p = ax + y * Level.WIDTH; x <= bx; x++, p++) {

        if (Dungeon.visible[p]) {

          if (intentional) {
            sprite.parent.addToBack(new CheckedCell(p));
          }

          if (Level.secret[p] && (intentional || Random.Float() < level)) {

            int oldValue = Dungeon.level.map[p];

            GameScene.discoverTile(p, oldValue);

            Level.set(p, Terrain.discover(oldValue));

            GameScene.updateMap(p);

            ScrollOfMagicMapping.discover(p);

            smthFound = true;
          }
        }
      }
    }

    if (intentional) {
      sprite.showStatus(CharSprite.DEFAULT, TXT_SEARCH);
      sprite.operate(pos);
      if (smthFound) {
        spendAndNext(Random.Float() < level ? TIME_TO_SEARCH : TIME_TO_SEARCH * 2);
      } else {
        spendAndNext(TIME_TO_SEARCH);
      }
    }

    if (smthFound) {
      GLog.w(TXT_NOTICED_SMTH);
      Sample.INSTANCE.play(Assets.SND_SECRET);
      interrupt();
    }

    return smthFound;
  }
예제 #23
0
  public static Level newLevel() {

    Dungeon.level = null;
    Actor.clear();

    depth++;
    if (depth > Statistics.deepestFloor) {
      Statistics.deepestFloor = depth;

      if (Statistics.qualifiedForNoKilling) {
        Statistics.completedWithNoKilling = true;
      } else {
        Statistics.completedWithNoKilling = false;
      }
    }

    Arrays.fill(visible, false);

    Level level;
    switch (depth) {
      case 1:
      case 2:
      case 3:
      case 4:
        level = new SewerLevel();
        break;
      case 5:
        level = new SewerBossLevel();
        break;
      case 6:
      case 7:
      case 8:
      case 9:
        level = new PrisonLevel();
        break;
      case 10:
        level = new PrisonBossLevel();
        break;
      case 11:
      case 12:
      case 13:
      case 14:
        level = new CavesLevel();
        break;
      case 15:
        level = new CavesBossLevel();
        break;
      case 16:
      case 17:
      case 18:
      case 19:
        level = new CityLevel();
        break;
      case 20:
        level = new CityBossLevel();
        break;
      case 21:
        level = new LastShopLevel();
        break;
      case 22:
      case 23:
      case 24:
        level = new HallsLevel();
        break;
      case 25:
        level = new HallsBossLevel();
        break;
      case 26:
        level = new LastLevel();
        break;
      default:
        level = new DeadEndLevel();
        Statistics.deepestFloor--;
    }

    level.create();

    Statistics.qualifiedForNoKilling = !bossLevel();

    return level;
  }