Пример #1
0
void
close_door (struct level *l, int e)
{
  struct pos *p;

  struct door *d;
  struct level_door *ld;

  do {
    p = &l->event[e].p;
    switch (con (p)->fg) {
    case DOOR:
      d = door_at_pos (p);
      if (! d) continue;
      d->action = ABRUPTLY_CLOSE_DOOR;
      break;
    case LEVEL_DOOR:
      ld = level_door_at_pos (p);
      if (! ld) continue;
      ld->action = CLOSE_LEVEL_DOOR;
      break;
    default:
      break;
    }
  } while (l->event[e++].next);
}
Пример #2
0
int
door_grid_tip_y (struct pos *p)
{
  struct coord c;
  int h = al_get_bitmap_height (dv_door_grid_tip);
  return door_grid_tip_coord (p, &c, door_at_pos (p)->i)->y + h - 1;
}
Пример #3
0
void
open_door (struct level *l, int e)
{
  struct pos *p;

  struct door *d;
  struct level_door *ld;

  do {
    p = &l->event[e].p;
    switch (con (p)->fg) {
    case DOOR:
      d = door_at_pos (p);
      if (! d) continue;
      d->action = OPEN_DOOR;
      d->wait = DOOR_WAIT;
      break;
    case LEVEL_DOOR:
      ld = level_door_at_pos (p);
      if (! ld) continue;
      ld->action = OPEN_LEVEL_DOOR;
      break;
    default:
      break;
    }
  } while (l->event[e++].next);
}
Пример #4
0
void
register_door (struct pos *p)
{
  assert (con (p)->fg == DOOR
          && door_at_pos (p) == NULL);

  struct door d;

  d.p = *p;
  d.i = con (p)->ext.step;
  d.action = NO_DOOR_ACTION;
  d.wait = DOOR_WAIT;
  d.noise = false;

  door =
    add_to_array (&d, 1, door, &door_nmemb, door_nmemb, sizeof (d));

  qsort (door, door_nmemb, sizeof (d), compare_doors);
}
Пример #5
0
void
draw_door_fg (ALLEGRO_BITMAP *bitmap, struct pos *p, struct frame *f,
              enum em em, enum vm vm)
{
  struct pos par, pr, pa;

  draw_floor_base (bitmap, p, em, vm);
  draw_door_pole (bitmap, p, em, vm);

  prel (p, &pr, +0, +1);
  prel (p, &pa, -1, +0);
  prel (p, &par, -1, +1);

  if (should_draw_door_grid (p, f)) {
    struct door *d = door_at_pos (p);
    draw_door_grid (bitmap, p, d->i, em, vm);
    draw_confg_right (bitmap, &pa, em, vm, true);
    draw_confg_base (bitmap, &par, em, vm);
    draw_confg_left (bitmap, &par, em, vm, true);
    draw_confg_fg (bitmap, &pr, em, vm, f);
  }
}
Пример #6
0
static bool
flow (struct anim *k)
{
  struct coord nc; struct pos np, ptf, pbf;
  enum confg ctf;

  if (k->oaction != kid_couch) {
    k->i = -1; k->fall = k->collision = k->misstep = false;
    k->wait = 0;
  }

  if (k->uncouch_slowly) {
    k->wait = 36;
    k->uncouch_slowly = false;
  }

  if (k->oaction == kid_climb)
    k->i = 10;

  if (k->oaction == kid_couch_collision)
    k->collision = true, k->inertia = k->cinertia = 0;

  if (k->oaction == kid_fall) {
    k->fall = true; k->inertia = k->cinertia = 0;
  }

  /* if (k->i > 2 && k->hit_by_loose_floor) */
  /*   k->i = -1; */

  /* unclimb */
  int dir = (k->f.dir == LEFT) ? +1 : -1;
  ctf = survey (_tf, pos, &k->f, &nc, &ptf, &np)->fg;
  survey (_bf, pos, &k->f, &nc, &pbf, &np);
  struct pos ph; prel (&pbf, &ph, +1, dir);
  if (k->i == -1
      && ! k->collision
      && ! k->fall
      && ! k->hit_by_loose_floor
      && k->item_pos.room == -1
      && is_hangable_pos (&ph, k->f.dir)
      && dist_next_place (&k->f, _tf, pos, 0, true) <= 27
      && ! (ctf == DOOR && k->f.dir == LEFT
            && door_at_pos (&ptf)->i > DOOR_CLIMB_LIMIT)) {
    pos2room (&ph, k->f.c.room, &k->hang_pos);
    kid_unclimb (k);
    return false;
  }

  if (k->i == 12) {
    k->hit_by_loose_floor = false;
    kid_normal (k);
    return false;
  }

  if (k->i == 2 && k->item_pos.room != -1
      && ! k->collision && ! k->fall) {
    if (is_potion (&k->item_pos)) kid_drink (k);
    else if (is_sword (&k->item_pos)) kid_raise_sword (k);
    else {
      k->item_pos.room = -1; goto no_item;
    }
    return false;
  }

 no_item:
  if (k->i == 2 && k->key.down
      && k->cinertia == 0
      && k->wait-- <= 0
      && ((k->f.dir == LEFT && k->key.left)
          || (k->f.dir == RIGHT && k->key.right))) {
    k->i = 0;
    select_frame (k, kid_couch_frameset, 0);
    return true;
  }

  if (k->i != 2 || (! k->key.down && k->wait-- <= 0))
    k->i++;

  if (k->i == 1 && k->wait > 0 &&
      ((k->fall == true && k->hurt)
       || k->hit_by_loose_floor))
    k->i = 2;

  select_frame (k, kid_couch_frameset, k->i);

  if (k->oaction == kid_climb) k->fo.dx += 7;
  if (k->i > 0 && k->i < 3) k->fo.dx -= k->cinertia;
  if (k->cinertia > 0) k->cinertia--;

  return true;
}
Пример #7
0
void
draw_door_right (ALLEGRO_BITMAP *bitmap, struct pos *p,
                 enum em em, enum vm vm)
{
  struct coord c;
  struct door *d = door_at_pos (p);
  if (! d) return;

  ALLEGRO_BITMAP *door_right = NULL,
    *door_top = NULL;

  switch (em) {
  case DUNGEON:
    switch (vm) {
    case CGA:
      door_right = dc_door_right;
      door_top = dc_door_top;
      break;
    case EGA:
      door_right = de_door_right;
      door_top = de_door_top;
      break;
    case VGA:
      door_right = dv_door_right;
      door_top = dv_door_top;
      break;
    }
    break;
  case PALACE:
    switch (vm) {
    case CGA:
      door_right = pc_door_right;
      door_top = pc_door_top;
      break;
    case EGA:
      door_right = pe_door_right;
      door_top = pe_door_top;
      break;
    case VGA:
      door_right = pv_door_right;
      door_top = pv_door_top;
      break;
    }
    break;
  }

  if (vm == VGA) {
    door_right = apply_hue_palette (door_right);
    door_top = apply_hue_palette (door_top);
  }

  if (hgc) {
    door_right = apply_palette (door_right, hgc_palette);
    door_top = apply_palette (door_top, hgc_palette);
  }

  if (peq (p, &mouse_pos)) {
    door_right = apply_palette (door_right, selection_palette);
    door_top = apply_palette (door_top, selection_palette);
  }

  draw_bitmapc (door_right, bitmap, door_right_coord (p, &c), 0);
  draw_bitmapc (door_top, bitmap, door_top_coord (p, &c), 0);
  draw_door_grid (bitmap, p, d->i, em, vm);
}
Пример #8
0
void
update_cache_pos (struct pos *p, enum changed_pos_reason reason,
                  enum em em, enum vm vm)
{
  static bool recursive = false, recursive_01 = false;

  int x, y;

  struct pos p0; p0 = *p;

  struct pos pbl; prel (p, &pbl, +1, -1);
  struct pos pb; prel (p, &pb, +1, +0);
  struct pos pbr; prel (p, &pbr, +1, +1);
  struct pos pl; prel (p, &pl, +0, -1);
  struct pos pr; prel (p, &pr, +0, +1);
  struct pos par; prel (p, &par, -1, +1);

  /* if (! recursive) */
  /*   printf ("%i,%i,%i,%i\n", p->room, p->floor, p->place, reason); */

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++)
      if (p->room && mr.cell[x][y].room == p->room) {
        room_view = p->room;
        mr.dx = x;
        mr.dy = y;
        con_caching = true;
        struct rect r;
        struct door *d;

        switch (reason) {
        case CHPOS_NONE: break;
        case CHPOS_UNHIDE_FLOOR:
        case CHPOS_MOUSE_SELECT:
        case CHPOS_MOUSE_DESELECT:
        case CHPOS_CLOSE_LEVEL_DOOR:
        case CHPOS_CARPET_DESIGN:
        case CHPOS_WALL:
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);
          break;
        case CHPOS_SHAKE_LOOSE_FLOOR:
        case CHPOS_RELEASE_LOOSE_FLOOR:
        case CHPOS_PRESS_OPENER_FLOOR:
        case CHPOS_UNPRESS_OPENER_FLOOR:
        case CHPOS_PRESS_CLOSER_FLOOR:
        case CHPOS_UNPRESS_CLOSER_FLOOR:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place,
                    PLACE_HEIGHT * p->floor + 49,
                    58, 17);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true);
          if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true);
          if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true);

          draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);

          break;
        case CHPOS_LOOSE_FLOOR_FALL:
        case CHPOS_CHAIN_RELEASE_LOOSE_FLOOR:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place,
                    PLACE_HEIGHT * p->floor + 49,
                    58, 17);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true);
          if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true);
          if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true);

          draw_confg_top (mr.cell[x][y].cache, &pbl, em, vm, true);
          draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);
          draw_confg_base (mr.cell[x][y].cache, &pr, em, vm);
          draw_confg_left (mr.cell[x][y].cache, &pr, em, vm, true);
          break;
        case CHPOS_BREAK_LOOSE_FLOOR:
        case CHPOS_BREAK_OPENER_FLOOR:
        case CHPOS_BREAK_CLOSER_FLOOR:
        case CHPOS_BREAK_LEVEL_DOOR:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place,
                    PLACE_HEIGHT * p->floor + 35,
                    57, 31);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          if (con (&pbl)->fg == LEVEL_DOOR || con (&pbl)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbl, em, vm, true);
          if (con (&pb)->fg == LEVEL_DOOR || con (&pb)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pb, em, vm, true);
          if (con (&pbr)->fg == LEVEL_DOOR || con (&pbr)->bg == BALCONY)
            draw_conbg (mr.cell[x][y].cache, &pbr, em, vm, true);

          draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);
          break;
        case CHPOS_OPEN_DOOR:
        case CHPOS_CLOSE_DOOR:
        case CHPOS_ABRUPTLY_CLOSE_DOOR:
          d = door_at_pos (p);

          int ch = 18 + d->i + 1;

          new_rect (&r, p->room,
                    PLACE_WIDTH * (p->place + 1),
                    PLACE_HEIGHT * p->floor - 6,
                    24, ch);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);

          if (ch > PLACE_HEIGHT - 3)
            draw_confg_top (mr.cell[x][y].cache, &pb, em, vm, true);

          break;
        case CHPOS_OPEN_LEVEL_DOOR:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place + 7,
                    PLACE_HEIGHT * p->floor - 1,
                    48, 51);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);

          break;
        case CHPOS_SPIKES:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place + 7,
                    PLACE_HEIGHT * p->floor + 34,
                    40, 24);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);

          break;
        case CHPOS_CHOPPER:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place,
                    PLACE_HEIGHT * p->floor + 3,
                    27, 60);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          draw_conbg (mr.cell[x][y].cache, &pl, em, vm, true);
          draw_conbg (mr.cell[x][y].cache, p, em, vm, true);

          break;
        default:
          new_rect (&r, p->room,
                    PLACE_WIDTH * p->place - 1,
                    PLACE_HEIGHT * p->floor - 17,
                    2 * PLACE_WIDTH + 1, PLACE_HEIGHT + 3 + 17);
          clear_rect_to_color (mr.cell[x][y].cache, &r, TRANSPARENT_COLOR);

          for (p0.floor = p->floor + 1; p0.floor >= p->floor - 1; p0.floor--)
            for (p0.place = p->place - 2; p0.place <= p->place + 1; p0.place++)
              draw_conbg (mr.cell[x][y].cache, &p0, em, vm, true);

          break;
        }

        con_caching = false;
        goto end;
      }

 end:;

  /* if (is_room_visible (p->room)) printf ("%i,%i,%i\n", p->room, p->floor, p->place); */

  bool depedv =
    ((em == DUNGEON && vm == VGA)
     || (em == DUNGEON && vm == EGA)
     || (em == PALACE && vm == EGA));

  if (! recursive_01 && depedv && con (&pl)->fg == WALL) {
    recursive_01 = true;
    update_cache_pos (&pl, CHPOS_WALL, em, vm);
    recursive_01 = false;
  }

  if (! recursive && p->place == -1) {
    p0.room = roomd (&global_level, p->room, LEFT);
    p0.floor = p->floor;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1) {
    p0.room = roomd (&global_level, p->room, ABOVE);
    p0.floor = FLOORS - 1;
    p0.place = p->place;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == 0) {
    p0.room = roomd (&global_level, p->room, ABOVE);
    p0.floor = FLOORS;
    p0.place = p->place;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->place == PLACES - 1) {
    p0.room = roomd (&global_level, p->room, RIGHT);
    p0.floor = p->floor;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1) {
    p0.room = roomd (&global_level, p->room, BELOW);
    p0.floor = -1;
    p0.place = p->place;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1 && p->place == -1) {
    p0.room = roomd (&global_level, p->room, ABOVE);
    p0.room = roomd (&global_level, p0.room, LEFT);
    p0.floor = FLOORS - 1;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == 0 && p->place == PLACES - 1) {
    p0.room = roomd (&global_level, p->room, ABOVE);
    p0.room = roomd (&global_level, p0.room, RIGHT);
    p0.floor = FLOORS;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == -1 && p->place == PLACES - 1) {
    p0.room = roomd (&global_level, p->room, ABOVE);
    p0.room = roomd (&global_level, p0.room, RIGHT);
    p0.floor = FLOORS - 1;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1 && p->place == -1) {
    p0.room = roomd (&global_level, p->room, LEFT);
    p0.room = roomd (&global_level, p0.room, BELOW);
    p0.floor = -1;
    p0.place = PLACES - 1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  if (! recursive && p->floor == FLOORS - 1 && p->place == PLACES - 1) {
    p0.room = roomd (&global_level, p->room, BELOW);
    p0.room = roomd (&global_level, p0.room, RIGHT);
    p0.floor = -1;
    p0.place = -1;
    recursive = true;
    update_cache_pos (&p0, reason, em, vm);
    recursive = false;
  }

  /* if (is_room_visible (p->room) && ! recursive) printf ("----------------------------\n"); */
}
Пример #9
0
bool
is_safe_to_follow (struct anim *k0, struct anim *k1, enum dir dir)
{
  /* not aware of enemy position */
  if (! is_valid_pos (&k0->enemy_pos)) return false;

  struct pos p0, p, p1, pke, pk;
  survey (_m, pos, &k0->f, NULL, &p0, NULL);
  survey ((k0->f.dir == LEFT) ? _mr : _ml,
          pos, &k1->f, NULL, &p1, NULL);

  pos2room (&p1, p0.room, &p1);

  /* not reachable, to start with */
  if (p0.room != p1.room) return false;
  if (p0.floor > p1.floor) return false;

  /* the character went down after the enemy */
  if (p0.floor != k0->enemy_pos.floor) {
    /* enum dir odir = (dir == LEFT) ? RIGHT : LEFT; */
    /* if (is_on_back (k0, k1) && is_seeing (k0, k1, odir) */
    /*     && p0.floor == p1.floor) return true; */
    if (is_anim_seeing (k0, k1, LEFT)
        || is_anim_seeing (k0, k1, RIGHT)) return true;
    return false;
  }

  /* if falling the chasing is inevitable (necessary to prevent
     leave_fight_logic from forgeting enemy based on the facing
     direction of the is_in_range check) */
  if (is_anim_fall (&k0->f)) return true;

  if (dir == LEFT) {
    if (! is_safe_at_left (&p0)) return false;
    if (! is_safe_at_right (&k0->enemy_pos, &k0->f)) return false;
    if (peqr (&k0->enemy_pos, &p0, +0, -1)) return true;
    prel (&p0, &pk, +0, -1);
    prel (&k0->enemy_pos, &pke, +0, +1);
    if (is_collidable_at_right (&pk, &k0->f))
      return false;
  } else {
    if (! is_safe_at_right (&p0, &k0->f)) return false;
    if (! is_safe_at_left (&k0->enemy_pos)) return false;
    if (peqr (&k0->enemy_pos, &p0, +0, +1)) return true;
    prel (&p0, &pk, +0, +1);
    prel (&k0->enemy_pos, &pke, +0, -1);
    if (is_collidable_at_right (&p0, &k0->f))
      return false;
  }

  /* enemy went down */
  if (is_traversable (&k0->enemy_pos)) {
    prel (&k0->enemy_pos, &pke, +1, +0);
    if (is_traversable (&pke) || fg (&pke) == SPIKES_FLOOR)
      return false;
    int d = (dir == LEFT) ? -1 : +1;
    if (peq (&pk, &k0->enemy_pos)) return true;
    prel (&k0->enemy_pos, &pke, +0, -1 * d);
  } else if (peq (&p0, &k0->enemy_pos)
             && ! (is_anim_seeing (k0, k1, LEFT)
                   || is_anim_seeing (k0, k1, RIGHT)))
    return false;

  first_confg (&pk, &pke, dangerous_cs, &p);
  if (is_valid_pos (&p)) return false;

  first_confg (&pk, &pke, door_cs, &p);
  if (! is_valid_pos (&p)) return true;
  else return door_at_pos (&p)->action == OPEN_DOOR
         || ! is_collidable_at_right (&p, &k0->f);
}
Пример #10
0
bool
is_safe_at_right (struct pos *p, struct frame *f)
{
  return ! is_collidable_at_right (p, f)
    || (fg (p) == DOOR && door_at_pos (p)->action == OPEN_DOOR);
}