Esempio n. 1
0
bool
should_draw_door_grid (struct pos *p, struct frame *f)
{
  struct pos pl, pa, pmt, ptb;

  struct anim *a = (struct anim *) f->id;

  struct pos *hang_pos = &a->hang_pos;

  survey (_mt, pos, f, NULL, &pmt, NULL);
  survey (_tb, pos, f, NULL, &ptb, NULL);

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

  return
    (((peq (&ptb, p) || peq (&ptb, &pl)
       || peq (&ptb, &pa))
      && (peq (&pmt, p) || peq (&pmt, &pl)
          || peq (&pmt, &pa)))
     || is_kid_successfully_climbing_at_pos
     (f, hang_pos, p)
     || (is_kid_turn_run (f)
         && f->dir == LEFT))
    && ! is_kid_successfully_climbing_at_pos
    (f, hang_pos, &pa);
}
Esempio n. 2
0
static void
place_in_initial_fall (struct anim *g)
{
  struct coord nc;
  struct pos np, pmt, pmtf, pmtb;
  struct pos fall_pos;

  int dirf = (g->f.dir == LEFT) ? -1 : +1;
  int dirb = (g->f.dir == LEFT) ? +1 : -1;
  survey (_mt, pos, &g->f, &nc, &pmt, &np);
  prel (&pmt, &pmtf, +0, dirf);
  prel (&pmt, &pmtb, +0, dirb);

  fall_pos.room = -1;

  if (is_strictly_traversable (&pmt)) fall_pos = pmt;
  else if (is_strictly_traversable (&pmtf)) fall_pos = pmtf;
  else if (is_strictly_traversable (&pmtb)) fall_pos = pmtb;

  struct frameset *frameset = get_guard_fall_frameset (g->type);

  if (fall_pos.room != - 1)
    place_frame (&g->f, &g->f, frameset[0].frame,
                 &fall_pos,
                 (g->f.dir == LEFT) ? PLACE_WIDTH - 12 : +6,
                 (g->f.dir == LEFT) ? 23 : 27);
}
Esempio n. 3
0
bool
is_pos_seeing (struct pos *p0, struct anim *k1, enum dir dir)
{
  struct coord m0, m1, mt1, mb1; struct pos p, p1, pk, pke;
  con_m (p0, &m0);

  coord_f cf;
  if (is_kid_climb (&k1->f) || is_anim_fall (&k1->f)) {
    coord2room (_mt (&k1->f, &mt1), m0.room, &mt1);
    coord2room (_m (&k1->f, &m1), m0.room, &m1);
    coord2room (_mbo (&k1->f, &mb1), m0.room, &mb1);

    double dt, dm, db;
    dt = (mt1.room == m0.room) ? dist_coord (&m0, &mt1) : INFINITY;
    dm = (m1.room == m0.room) ? dist_coord (&m0, &m1) : INFINITY;
    db = (mb1.room == m0.room) ? dist_coord (&m0, &mb1) : INFINITY;

    if (dt <= dm && dt <= db)
      cf = (dir == LEFT) ? _tr : _tl;
    else if (db <= dt && db <= dm)
      cf = (dir == LEFT) ? _br : _bl;
    else cf = (dir == LEFT) ? _mr : _ml;
  } else cf = (dir == LEFT) ? _mr : _ml;

  surveyo (cf, -8, +0, pos, &k1->f, &m1, NULL, NULL);

  coord2room (&m0, p0->room, &m0);
  coord2room (&m1, p0->room, &m1);
  pos (&m1, &p1);

  if (dir == LEFT) {
    if (is_opaque_at_left (p0)) return false;
    if (is_opaque_at_right (&p1)) return false;
    if (peqr (&p1, p0, +0, -1)) return true;
    prel (p0, &pk, +0, -1);
    prel (&p1, &pke, +0, +1);
  } else {
    if (is_opaque_at_right (p0)) return false;
    if (is_opaque_at_left (&p1)) return false;
    if (peqr (&p1, p0, +0, +1)) return true;
    prel (p0, &pk, +0, +1);
    prel (&p1, &pke, +0, -1);
  }

  if (peq (p0, &p1)) return true;

  first_confg (&pk, &pke, opaque_cs, &p);

  return p0->room == p1.room
    && m1.room == m0.room
    && p1.floor == p0->floor
    && ! (dir == LEFT && m1.x > m0.x)
    && ! (dir == RIGHT && m1.x < m0.x)
    && p.room == -1;
}
Esempio n. 4
0
bool
should_spikes_raise_for_pos (struct pos *p, struct pos *pk)
{
  struct pos pb1, pb2, np;

  return peq (pk, p)
    || (peq (pk, prel (p, &pb1, -1, 0))
        && is_strictly_traversable (prel (p, &np, -1, +0)))
    || (peq (pk, prel (p, &pb2, -2, 0))
        && is_strictly_traversable (prel (p, &np, -1, +0))
        && is_strictly_traversable (prel (p, &np, -2, +0)));
}
Esempio n. 5
0
void
draw_floor_reflex (ALLEGRO_BITMAP *bitmap, struct pos *p,
                   enum em em, enum vm vm)
{
  ALLEGRO_BITMAP *floor_right = NULL;

  switch (em) {
  case DUNGEON:
    switch (vm) {
    case CGA: floor_right = dc_floor_right; break;
    case EGA: floor_right = de_floor_right; break;
    case VGA: floor_right = dv_floor_right; break;
    }
    break;
  case PALACE:
    switch (vm) {
    case CGA: floor_right = pc_floor_right; break;
    case EGA: floor_right = pe_floor_right; break;
    case VGA: floor_right = pv_floor_right; break;
    }
    break;
  }

  if (vm == VGA) floor_right = apply_hue_palette (floor_right);
  if (hgc) floor_right = apply_palette (floor_right, hgc_palette);
  if (peq (p, &mouse_pos))
    floor_right = apply_palette (floor_right, selection_palette);

  struct pos pl; prel (p, &pl, +0, -1);
  struct coord c;
  int h = al_get_bitmap_height (floor_right);
  draw_bitmap_regionc (floor_right, bitmap, 0, 2, 17, h - 9,
                       floor_reflex_coord (&pl, &c), 0);
}
Esempio n. 6
0
void
draw_arch_bottom_fg (ALLEGRO_BITMAP *bitmap, struct pos *p,
                     enum em em, enum vm vm)
{
  struct pos pa; prel (p, &pa, -1, +0);
  draw_arch_bottom (bitmap, p, em, vm);
  draw_confg_base (bitmap, &pa, em, vm);
}
Esempio n. 7
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);
  }
}
Esempio n. 8
0
struct pos *
get_mouse_pos (struct pos *p)
{
  struct mouse_coord m;
  get_mouse_coord (&m);

  if (! is_valid_coord (&m.c)) {
    invalid_pos (p);
    return p;
  }

  int ry = (m.c.y - 3) % PLACE_HEIGHT;

  pos_gen (&m.c, p, 0, 3);

  if (edit == EDIT_NONE) {
    invalid_pos (p);
    return p;
  }

  struct pos p0;

  switch (fake (p)) {
  case MIRROR: case CHOPPER:
  case WALL: case PILLAR: case BIG_PILLAR_TOP:
  case BIG_PILLAR_BOTTOM: case ARCH_BOTTOM:
  case ARCH_TOP_MID: case ARCH_TOP_SMALL:
  case ARCH_TOP_LEFT: case ARCH_TOP_RIGHT: break;
  default:
    if (is_arch_top (prel (p, &p0, +0, -1)))
      break;
    if (ry >= 60) pos_gen (&m.c, p, 0, 3);
    else if (ry >= 50) pos_gen (&m.c, p, 23 - 2.5 * (ry - 50), 3);
    else pos_gen (&m.c, p, 23, 3);
    break;
  }

  struct pos np; npos (p, &np);
  if (! np.room) {
    invalid_pos (p);
    return p;
  }

  return p;
}
Esempio n. 9
0
void
fight_hit (struct anim *k, struct anim *ke)
{
  if (k->immortal || k->sword_immune) return;
  if (k->current_lives <= 0) return;
  if (is_anim_fall (&k->f) || is_kid_stairs (&k->f))
    return;

  place_on_the_ground (&k->f, &k->f.c);
  k->xf.b = NULL;

  if (! is_in_fight_mode (k)) k->current_lives = 0;
  else k->current_lives--;

  if (! is_guard (ke))
    upgrade_skill (&ke->skill, &k->skill, k->total_lives);

  int d = (k->f.dir == LEFT) ? +1 : -1;
  struct pos pb;
  survey (_m, pos, &k->f, NULL, &k->p, NULL);
  prel (&k->p, &pb, 0, d);

  if (k->current_lives <= 0 && ! is_strictly_traversable (&pb)) {
    k->current_lives = 0;
    k->death_reason = FIGHT_DEATH;
    ke->alert_cycle = anim_cycle;
    anim_die (k);
  } else anim_sword_hit (k);

  if (is_in_fight_mode (k)) {
    backoff_from_range (ke, k, ATTACK_RANGE - 20, true, false);
    get_in_range (ke, k, ATTACK_RANGE - 10, false, false);
  }

  k->splash = true;

  if (k->id == current_kid_id) {
    mr.flicker = 2;
    mr.color = get_flicker_blood_color ();
    play_audio (&harm_audio, NULL, k->id);
  } else play_audio (&guard_hit_audio, NULL, k->id);
}
Esempio n. 10
0
static bool
physics_in (struct anim *k)
{
  struct coord nc; struct pos np, pm;
  enum confg cm;

  /* collision */
  if (is_colliding (&k->f, &k->fo, +0, false, &k->ci)
      && k->ci.t != MIRROR) {
    if (k->i <= 2 && k->fall)
      uncollide (&k->f, &k->fo, &k->fo, +0, false, &k->ci);
    else {
      kid_stabilize_collision (k);
      return false;
    }
  } else if (is_colliding (&k->f, &k->fo, +2, false, &k->ci)
             && k->ci.t == MIRROR) {
    if (k->i <= 2)
      k->f.c.x += (k->f.dir == LEFT) ? +4 : -4;
    else {
      kid_stabilize_collision (k);
      return false;
    }
  }

  if (! k->fall && kid_door_split_collision (k)) return false;


  /* fall */
  cm = survey (_m, pos, &k->f, &nc, &pm, &np)->fg;
  struct loose_floor *l =
    loose_floor_at_pos (prel (&pm, &np, -1, +0));
  if ((is_strictly_traversable (&pm)
       || (l && l->action == FALL_LOOSE_FLOOR && cm == LOOSE_FLOOR))
      && ! (k->fall && k->i == 0)) {
    kid_fall (k);
    return false;
  }

  return true;
}
Esempio n. 11
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;
}
Esempio n. 12
0
void
draw_room_frame_fg (ALLEGRO_BITMAP *bitmap, enum em em, enum vm vm,
                    struct frame *f)
{
  struct pos ptl, pbr, ptl2, pbr2;

  survey (_tl, posf, f, NULL, &ptl, NULL);
  survey (_br, posf, f, NULL, &pbr, NULL);
  pos2room (&ptl, room_view, &ptl);
  pos2room (&pbr, room_view, &pbr);

  survey (_tl, pos, f, NULL, &ptl2, NULL);
  survey (_br, pos, f, NULL, &pbr2, NULL);
  pos2room (&ptl2, room_view, &ptl2);
  pos2room (&pbr2, room_view, &pbr2);

  struct coord c; frame2room (f, room_view, &c);

  int w = al_get_bitmap_width (f->b);
  int h = al_get_bitmap_height (f->b);

  push_clipping_rectangle (bitmap, c.x, c.y, w, h);

  /* FALLING LOOSE FLOOR */
  struct pos ptr, ptra;
  survey (_tr, posf, f, NULL, &ptr, NULL);
  prel (&ptr, &ptra, -1, +0);
  draw_falling_loose_floor (bitmap, &ptr, em, vm);
  draw_falling_loose_floor (bitmap, &ptra, em, vm);

  struct pos p = ptl;
  for (p.floor = pbr.floor; p.floor >= ptl.floor; p.floor--)
    for (p.place = ptl.place; p.place <= pbr.place; p.place++)
      switch (fake (&p)) {
      case SPIKES_FLOOR: draw_spikes_fg (bitmap, &p, em, vm); break;
      case BROKEN_FLOOR: draw_broken_floor_fg (bitmap, &p, em, vm); break;
      case OPENER_FLOOR: draw_opener_floor_fg (bitmap, &p, em, vm); break;
      case CLOSER_FLOOR: draw_closer_floor_fg (bitmap, &p, em, vm); break;
      case PILLAR: draw_pillar_fg (bitmap, &p, em, vm); break;
      case BIG_PILLAR_BOTTOM:
        draw_big_pillar_bottom_fg (bitmap, &p, em, vm); break;
      case BIG_PILLAR_TOP:
        draw_big_pillar_top_left (bitmap, &p, em, vm); break;
      case ARCH_BOTTOM: draw_arch_bottom_fg (bitmap, &p, em, vm); break;
      case WALL: draw_wall_fg (bitmap, &p, f, em, vm); break;
      case CHOPPER: draw_chopper_fg (bitmap, &p, em, vm); break;
      case MIRROR: draw_mirror_fg (bitmap, &p, f, em, vm); break;
      case ARCH_TOP_MID: draw_arch_top_mid (bitmap, &p, em, vm); break;
      case ARCH_TOP_SMALL: draw_arch_top_small (bitmap, &p, em, vm); break;
      case ARCH_TOP_LEFT: draw_arch_top_left (bitmap, &p, em, vm); break;
      case ARCH_TOP_RIGHT: draw_arch_top_right (bitmap, &p, em, vm); break;
      default: break;
      }

  p = ptl2;
  for (p.floor = pbr2.floor; p.floor >= ptl2.floor; p.floor--)
    for (p.place = ptl2.place; p.place <= pbr2.place; p.place++)
      switch (fake (&p)) {
      case WALL: draw_wall_fg (bitmap, &p, f, em, vm); break;
      case DOOR: draw_door_fg (bitmap, &p, f, em, vm); break;
      case CARPET: draw_carpet_fg (bitmap, &p, f, em, vm); break;
      case TCARPET: draw_carpet_fg (bitmap, &p, f, em, vm); break;
      default: break;
      }

  pop_clipping_rectangle ();
}
Esempio n. 13
0
void
draw_multi_rooms (void)
{
  int x, y;

  mr_set_origin (mr.room, mr.x, mr.y);

  bool mr_full_update = has_mr_view_changed ()
    || mr.full_update;

  if (mr_full_update) {
    mr_busy ();
    force_full_redraw = true;
  }

  if (anim_cycle == 0) {
    generate_wall_colors_for_room (0, room0_wall_color);
  }

  if (em == PALACE && vm == VGA
      && (mr_full_update
          || em != mr.last.em
          || vm != mr.last.vm))
    generate_wall_colors ();

  if (mouse_pos.room != mr.last.mouse_pos.room
      || mouse_pos.floor != mr.last.mouse_pos.floor
      || mouse_pos.place != mr.last.mouse_pos.place) {
    if (is_valid_pos (&mouse_pos))
      register_changed_pos (&mouse_pos);

    if (is_valid_pos (&mr.last.mouse_pos))
      register_changed_pos (&mr.last.mouse_pos);
  }

  if (anim_cycle == 0
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue) {
    update_room0_cache (em, vm);
    force_full_redraw = true;
  }

  size_t i;

  if (anim_cycle == 0
      || mr_full_update
      || em != mr.last.em
      || vm != mr.last.vm
      || hgc != mr.last.hgc
      || hue != mr.last.hue
      || global_level.n != mr.last.level) {
    update_cache (em, vm);
  } else {
    bool depedv =
      ((em == DUNGEON && vm == VGA)
       || (em == DUNGEON && vm == EGA)
       || (em == PALACE && vm == EGA));

    /* optmize changed pos list */
    optimize_changed_pos ();

    /* update cache pos */
    for (i = 0; i < changed_pos_nmemb; i++) {
      update_cache_pos (&changed_pos[i], em, vm);
      struct pos pl; prel (&changed_pos[i], &pl, +0, -1);
      if (depedv && fake (&pl) == WALL)
        update_cache_pos (&pl, em, vm);
    }

    /* update cache room */
    for (i = 0; i < changed_room_nmemb; i++)
      update_cache_room (changed_room[i], em, vm);

    /* kept together so update_cache_pos and update_cache_room can
       access each other's arrays */
    destroy_array ((void **) &changed_pos, &changed_pos_nmemb);
    destroy_array ((void **) &changed_room, &changed_room_nmemb);
  }

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      clear_bitmap (mr.cell[x][y].screen, (mr.flicker > 0 && mr.flicker % 2)
                    ? mr.color : BLACK);

      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_background (mr.cell[x][y].screen,
                                mr.cell[x][y].room);
    }

  if (mr.flicker > 0) mr.flicker--;

  struct mr_room_list l;
  mr_get_room_list (&l);

  int xm, ym;
  if (! no_room_drawing)
    for (i = 0; i < l.nmemb; i++) {
      mr_coord (l.room[i], -1, &xm, &ym);
      for (y = mr.h - 1; y >= 0; y--)
        for (x = 0; x < mr.w; x++)
          if (mr.cell[x][y].room == l.room[i])
            draw_bitmap (mr.cell[xm][ym].cache,
                         mr.cell[x][y].screen, 0, 0, 0);
    }

  mr_destroy_room_list (&l);

  for (y = mr.h - 1; y >= 0; y--)
    for (x = 0; x < mr.w; x++) {
      if (! mr.cell[x][y].room) continue;
      mr.dx = x;
      mr.dy = y;
      draw_animated_foreground (mr.cell[x][y].screen, mr.cell[x][y].room);
    }

  mr_update_last_settings ();
}
Esempio n. 14
0
void
update_cache_pos (struct pos *p, enum em em, enum vm vm)
{
  static bool recursive = false;

  int x, y;

  int room_view_bkp = room_view;

  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 pa; prel (p, &pa, -1, +0);
  struct pos pal; prel (p, &pal, -1, -1);
  struct pos par; prel (p, &par, -1, +1);

  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;

        int cx, cy, cw, ch;
        switch (con (p)->fg) {
        default:
          cx = PLACE_WIDTH * p->place;
          cy = PLACE_HEIGHT * p->floor - 10;
          cw = 2 * PLACE_WIDTH;
          ch = PLACE_HEIGHT + 3 + 10;
          break;
        }

        set_target_bitmap (mr.cell[x][y].cache);
        al_set_clipping_rectangle (cx, cy, cw, ch);
        al_clear_to_color (TRANSPARENT_COLOR);

        con_caching = true;

        draw_conbg (mr.cell[x][y].cache, &pbl, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pb, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pbr, em, vm);

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

        draw_conbg (mr.cell[x][y].cache, &pal, em, vm);
        draw_conbg (mr.cell[x][y].cache, &pa, em, vm);
        draw_conbg (mr.cell[x][y].cache, &par, em, vm);

        draw_confg_right (mr.cell[x][y].cache, &pbl, em, vm, true);
        draw_confg_right (mr.cell[x][y].cache, &pb, em, vm, true);
        draw_confg_right (mr.cell[x][y].cache, &pl, em, vm, false);

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

        draw_confg_right (mr.cell[x][y].cache, &pal, em, vm, true);
        draw_confg (mr.cell[x][y].cache, &pa, em, vm, true);
        draw_confg_base (mr.cell[x][y].cache, &par, em, vm);
        draw_confg_left (mr.cell[x][y].cache, &par, em, vm, false);

        al_reset_clipping_rectangle ();
        al_hold_bitmap_drawing (false);
        con_caching = false;
      }

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

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

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

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

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

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

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

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

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

  /* if (! recursive) printf ("----------------------------\n"); */

  room_view = room_view_bkp;
}
Esempio n. 15
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);
}
Esempio n. 16
0
void
fight_ai (struct anim *k)
{
  /* non-fightable characters don't fight */
  if (! is_fightable_anim (k)) return;

  /* controllables and non-fighters doesn't need AI to fight */
  if (k->controllable || ! k->fight) return;

  /* if forgetting about an enemy, no need to fight */
  if (k->enemy_refraction > 0) return;

  /* without an enemy or awareness, no need to fight */
  if (k->enemy_id == -1) {
    if (is_in_fight_mode (k)) leave_fight_mode (k);
    return;
  }

  /* first thing, enter in fight mode */
  if (! is_in_fight_mode (k)) {
    enter_fight_mode (k);
    return;
  }

  /* who's the enemy? */
  struct anim *ke = get_anim_by_id (k->enemy_id);

  /* what's the facing opposite direction? */
  enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT;

  /* get positions */
  struct pos p, pe;
  survey (_m, pos, &k->f, NULL, &p, NULL);
  survey ((k->f.dir != ke->f.dir) ? _m : _mba,
          pos, &ke->f, NULL, &pe, NULL);
  pos2room (&pe, p.room, &pe);

  /* remember the place the enemy was last seen */
  if (pe.room == p.room && pe.floor == p.floor)
    k->enemy_pos = pe;
  else if (pe.floor > p.floor && is_valid_pos (&k->enemy_pos)
           && ! is_strictly_traversable (&k->enemy_pos))
    k->enemy_pos.place = pe.place;

  if (is_valid_pos (&k->enemy_pos)
      && is_strictly_traversable (&k->enemy_pos)) {
    struct pos pp;
    int d = (p.place < k->enemy_pos.place) ? -1 : +1;
    while (is_strictly_traversable (prel (&k->enemy_pos, &pp, +0, d)))
      k->enemy_pos = pp;
  }

  /* prevent enemy from passing through */
  if (ke->type == KID
      && is_in_range (k, ke, ATTACK_RANGE)
      && ! is_in_fight_mode (ke)
      && ! ke->immortal
      && ! (is_kid_climb (&ke->f) && ke->i <= 7)
      && ke->f.dir != k->f.dir
      && ke->current_lives > 0
      && ke->has_sword
      && ! is_kid_fall (&ke->f)
      && ! is_kid_hang (&ke->f)
      && ! is_kid_jump_air (&ke->f)
      && ! is_kid_run_jump_air (&ke->f)
      && is_safe_to_attack (ke)) {
    place_on_the_ground (&ke->f, &ke->f.c);
    kid_take_sword (ke);
    ke->auto_taken_sword = true;
  }

  /* prevent enemy from hiding near */
  if (ke->type == KID
      && is_in_range (k, ke, INVERSION_RANGE)
      && ! is_in_fight_mode (ke)
      && ke->current_lives > 0) {
    if (is_safe_to_walkb (k)) fight_walkb (k);
    else if (is_safe_to_turn (k)) fight_turn (k);
    return;
  }

  /* if the enemy is on the back, turn */
  if (is_on_back (k, ke) && is_anim_seeing (k, ke, odir)
      && p.floor == pe.floor
      && ! is_in_range (k, ke, INVERSION_RANGE)) {
    if (is_safe_to_turn (k)) fight_turn (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* if too near to a wall, back off to have room for an attack */
  if (fight_crel (k, +0, +1) == WALL
      && is_safe_to_walkb (k)) {
    fight_walkb (k);
    return;
  }

  /* /\* if the enemy can be followed in the opposite direction, turn *\/ */
  /* if (! is_safe_to_follow (k, ke, k->f.dir) */
  /*     && is_safe_to_follow (k, ke, odir)) { */
  /*   fight_turn (k); */
  /*   return; */
  /* } */

  /* if the enemy is trying to bypass, attack him */
  if (! is_in_fight_mode (ke)
      && ! ke->has_sword
      && ! is_kid_stairs (&ke->f)
      && ke->f.dir != k->f.dir
      && ke->current_lives > 0
      && ! is_on_back (k, ke)
      && ((is_kid_run (&ke->f)
           && is_in_range (k, ke, 3 * PLACE_WIDTH - 4))
          || (is_kid_run_jump (&ke->f)
              && is_in_range (k, ke, 4 * PLACE_WIDTH - 4))
          || (is_kid_jump_air (&ke->f) && ke->i < 9
              && is_in_range (k, ke, 4 * PLACE_WIDTH)))) {
    if (is_safe_to_attack (k)) fight_attack (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* stays at least in the fight range.  Advance, unless the enemy is
     not running towards you */
  if (! is_in_range (k, ke, FIGHT_RANGE + 10)
      && ! is_kid_stairs (&ke->f)
      && (ke->f.dir == k->f.dir
          || p.room != pe.room
          || p.floor != pe.floor
          || ! (is_kid_run (&ke->f)
                || is_kid_run_jump (&ke->f)
                || is_kid_jump (&ke->f)))
      && is_safe_to_follow (k, ke, k->f.dir)) {
    fight_walkf (k);
    return;
  }

  /* if the enemy is not targeting you, do nothing more */
  if (ke->enemy_id != -1 && ke->enemy_id != k->id) return;

  /* in fight range, if the enemy is not attacking, go towards attack
     range (with probability, unless the enemy is not in fight mode,
     then go immediately) */
  if (is_in_range (k, ke, FIGHT_RANGE + 10)
      && ! is_in_range (k, ke, ATTACK_RANGE)
      && ! is_kid_stairs (&ke->f)
      && is_safe_to_follow (k, ke, k->f.dir)
      && (prandom (99) <= k->skill.advance_prob
          || ! is_in_fight_mode (ke))
      && ! is_attacking (ke)
      && (! is_in_fight_mode (ke)
          || is_walking (ke)
          || ke->i >= 6 + prandom (24))) {
    fight_walkf (k);
    return;
  }

  /* in attack range, if being attacked, defend yourself (with
     probability) and counter attack (with probability handled
     elsewhere) */
  if (is_in_range (k, ke, ATTACK_RANGE + 16)
      && ! is_on_back (k, ke)
      && (is_attacking (ke) && ke->i == 0)
      && (prandom (99) <= k->skill.defense_prob
          || k->refraction > 0)
      && ke->current_lives > 0) {
    fight_defense (k);
    fight_attack (k);
    return;
  }

  /* if attacking, counter defend
     (with probability handled elsewhere) */
  if (is_in_range (k, ke, ATTACK_RANGE + 16)
      && is_attacking (k)) {
    fight_defense (k);
    fight_attack (k);
    return;
  }

  /* in attack range, if not being attacked, attack (with probability,
     unless the enemy is not in fight mode, then attack immediately) */
  if (is_in_range (k, ke, ATTACK_RANGE)
      && ! is_attacking (ke)
      && ! is_on_back (k, ke)
      && ! is_kid_stairs (&ke->f)
      && ! ((is_kid_climb (&ke->f)
             || is_kid_successfully_climbing (&ke->f))
            && ke->i >= 1)
      && ke->current_lives > 0
      && (prandom (99) <= k->skill.attack_prob
          || ! is_in_fight_mode (ke))) {
    if (is_safe_to_attack (k)) fight_attack (k);
    else if (is_safe_to_walkb (k)) fight_walkb (k);
    return;
  }

  /* in hit range, back off (with probability) */
  if (is_in_range (k, ke, HIT_RANGE - 10)
      && is_safe_to_walkb (k)
      && ! k->refraction
      && ! is_walkingb (ke)
      && prandom (99) <= k->skill.return_prob) {
    fight_walkb (k);
    return;
  }
}
Esempio n. 17
0
bool
peqr (struct pos *p0, struct pos *p1, int floor, int place)
{
  struct pos np;
  return peq (p0, prel (p1, &np, floor, place));
}
Esempio n. 18
0
static bool
flow (struct anim *k)
{
  struct pos np;

  if (k->oaction != kid_hang_free)
    k->i = 5, k->j = -1, k->wait = 3, k->reverse = true;

  bool hang_back = ((k->f.dir == LEFT) ? k->key.right : k->key.left)
    && ! k->key.up && k->key.shift;

  int back_dir = (k->f.dir == LEFT) ? RIGHT : LEFT;

    /* hang back */
  if (k->i >= 7
      && hang_back && is_hangable_pos (&k->hang_pos, back_dir)) {
    play_audio (&hang_on_fall_audio, NULL, k->id);
    kid_turn (k);
    return false;
  }

  /* climb */
  if ((k->i < 5 || k->j > -1
       || k->hang_caller != kid_unclimb)
      && k->key.up
      && ! ((k->key.left || k->key.right)
            && k->hang_caller == kid_unclimb)
      && ! k->hang_limit) {
    kid_climb (k);
    return false;
  }

  /* release */
  if ((! k->key.shift || k->hang_limit
       || get_hanged_con (&k->hang_pos, k->f.dir) == NO_FLOOR)
      && (k->i < 5 || k->j > -1)) {
    int dir = (k->f.dir == LEFT) ? -1 : +1;
    k->hang_limit = false;
    if (! is_strictly_traversable (&k->hang_pos)
        && k->i >= 4) {
      place_frame (&k->f, &k->f, kid_vjump_frameset[13].frame,
                   &k->hang_pos, (k->f.dir == LEFT) ? +7 : PLACE_WIDTH + 9, -8);
      kid_vjump (k);
      return false;
    }
    if (! is_strictly_traversable (prel (&k->hang_pos, &np, +0, dir))
        && k->i <= 4) {
      place_frame (&k->f, &k->f, kid_vjump_frameset[13].frame,
                   &k->hang_pos, (k->f.dir == LEFT) ? +7 : PLACE_WIDTH + 5, -8);
      kid_vjump (k);
      return false;
    }
    if (is_strictly_traversable (&k->hang_pos)
        && k->i >= 4) {
      place_frame (&k->f, &k->f, kid_fall_frameset[0].frame,
                   &k->hang_pos, (k->f.dir == LEFT) ? +10 : +22, +4);
      kid_fall (k);
      return false;
    }
    if (is_strictly_traversable (prel (&k->hang_pos, &np, +0, dir))
        && k->i <= 4) {
      place_frame (&k->f, &k->f, kid_fall_frameset[0].frame,
                   &k->hang_pos, (k->f.dir == LEFT)
                   ? -10 : PLACE_WIDTH + 10, +12);
      kid_fall (k);
      return false;
    }
  }

  if (k->reverse && k->i > 0) {
    if (k->i == 4  && k->j++ > 0) k->hang_limit = true;
    k->i--;
  } else if (k->reverse && k->i == 0) {
    if (k->wait == 0) {
      k->reverse = false; k->i++;
    } else k->wait--;
  } else if (! k->reverse
             && ((k->j == 0 && k->i < 12)
                 || (k->j > 0 && k->i < 9))) k->i++;
  else if (! k->reverse
           && ((k->j == 0 && k->i == 12)
               || (k->j > 0 && k->i == 9))) {
    k->reverse = true; k->i--;
  }

  k->fo.b = kid_hang_frameset[k->i].frame;
  k->fo.dx = (k->reverse) ? -kid_hang_frameset[k->i + 1].dx
    : kid_hang_frameset[k->i].dx;
  k->fo.dy = (k->reverse) ? -kid_hang_frameset[k->i + 1].dy
    : kid_hang_frameset[k->i].dy;

  if (k->f.b == kid_hang_13) k->fo.dx = +0, k->fo.dy = +1;

  if (k->reverse && k->j == 0 && k->i == 0
      && k->wait < 3) k->fo.dy = 0;

  return true;
}
Esempio n. 19
0
void
compute_loose_floor_fall (struct loose_floor *l)
{
  int speed = 3 * ++l->i;
  if (speed > 29) speed = 29;

  struct frame nf;
  struct frame_offset fo;
  fo.b = l->f.b;
  fo.dx = 0;
  fo.dy = speed;
  next_frame (&l->f, &nf, &fo);
  struct coord mbo_f, mbo_nf;
  struct pos fpmbo_f, nfpmbo_f, fpmbo_nf, nfpmbo_nf;
  enum confg fcmbo_f;
  fcmbo_f = survey (_mbo, posf, &l->f, &mbo_f, &fpmbo_f, &nfpmbo_f)->fg;
  survey (_mbo, posf, &nf, &mbo_nf, &fpmbo_nf, &nfpmbo_nf);

  struct pos p;

  /* hit kid */
  int i;
  for (i = 0; i < anima_nmemb; i++) {
    struct coord kmt, ambo_f, ambo_nf; struct pos np, kpmt;
    struct anim *a = &anima[i];
    if (is_anim_dead (&a->f)
        || a->immortal
        || a->loose_floor_immune)
      continue;
    survey (_mt, pos, &a->f, &kmt, &kpmt, &np);
    coord2room (&mbo_f, kpmt.room, &ambo_f);
    coord2room (&mbo_nf, kpmt.room, &ambo_nf);
    if (peq (&nfpmbo_f, &kpmt)
        && ambo_f.y <= kmt.y
        && ambo_nf.y >= kmt.y
        && ! a->hit_by_loose_floor
        && ! is_kid_hang_or_climb (&a->f)
        && ! is_kid_fall (&a->f)) {
      a->hit_by_loose_floor = true;
      a->splash = true;
      a->current_lives--;
      a->uncouch_slowly = true;
      /* ensure kid doesn't couch in thin air (might occur when hit
         while jumping, for example) */
      place_on_the_ground (&a->f, &a->f.c);
      play_sample (hit_wall_sample, kpmt.room);
      alert_guards (&kpmt);
      if (a->id == current_kid_id) {
        video_effect.color = get_flicker_blood_color ();
        start_video_effect (VIDEO_FLICKERING, SECS_TO_VCYCLES (0.1));
      }
      if (a->current_lives <= 0) {
        a->p = kpmt;
        anim_die_suddenly (a);
        a->death_reason = LOOSE_FLOOR_DEATH;
      }
      else if (a->type == KID) kid_couch (a);
    }
  }

  /* fall */
  if (is_strictly_traversable (&fpmbo_f)
      || peq (&fpmbo_f, &fpmbo_nf)) {
    /* the floor hit a rigid structure */
    if (is_rigid_con (&fpmbo_nf)) prel (&fpmbo_nf, &p, -1, 0);
    /* the floor continue to fall */
    else {
      l->f = nf;
      if (is_strictly_traversable (&fpmbo_nf)) l->p = fpmbo_nf;
      must_sort = true;
      return;
    }
    /* the floor hit the ground */
  } else {
    struct loose_floor *m;
    p = fpmbo_f;
    switch (fcmbo_f) {
    case LOOSE_FLOOR: /* loose floor isn't ground */
      m = loose_floor_at_pos (&fpmbo_f);
      if (m) m->p.room = -1;
      must_remove = true;
      l->f = nf;
      l->f.b = get_correct_falling_loose_floor_bitmap (dv_broken_floor);
      l->p = fpmbo_f;
      l->i = 0;
      con (&fpmbo_f)->fg = NO_FLOOR;
      must_sort = true;
      play_sample (broken_floor_sample, p.room);
      alert_guards (&p);
      return;
    case OPENER_FLOOR: break_opener_floor (&fpmbo_f); break;
    case CLOSER_FLOOR: break_closer_floor (&fpmbo_f); break;
    case SPIKES_FLOOR: break_spikes_floor (&fpmbo_f); break;
    case LEVEL_DOOR: break_level_door (&fpmbo_f); break;
    default: break;
    }
  }

  /* reach here only if the floor hit a rigid structure or the
     ground */
  if (con (&p)->fg != LEVEL_DOOR) con (&p)->fg = BROKEN_FLOOR;
  shake_loose_floor_row (&p);
  l->p.room = -1;
  must_remove = true;
  must_sort = true;
  play_sample (broken_floor_sample, p.room);
  alert_guards (&p);
}
Esempio n. 20
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"); */
}
Esempio n. 21
0
void
draw_pressed_closer_floor_right (ALLEGRO_BITMAP *bitmap, struct pos *p,
                                 enum em em, enum vm vm)
{
  ALLEGRO_BITMAP *floor_right = NULL,
    *pressed_closer_floor_right = NULL;

  switch (em) {
  case DUNGEON:
    switch (vm) {
    case CGA:
      floor_right = dc_floor_right;
      pressed_closer_floor_right = dc_pressed_closer_floor_right;
      break;
    case EGA:
      floor_right = de_floor_right;
      pressed_closer_floor_right = de_pressed_closer_floor_right;
      break;
    case VGA:
      floor_right = dv_floor_right;
      pressed_closer_floor_right = dv_pressed_closer_floor_right;
      break;
    }
    break;
  case PALACE:
    switch (vm) {
    case CGA:
      floor_right = pc_floor_right;
      pressed_closer_floor_right = pc_pressed_closer_floor_right;
      break;
    case EGA:
      floor_right = pe_floor_right;
      pressed_closer_floor_right = pe_pressed_closer_floor_right;
      break;
    case VGA:
      floor_right = pv_floor_right;
      pressed_closer_floor_right = pv_pressed_closer_floor_right;
      break;
    }
    break;
  }

  if (vm == VGA) {
    floor_right = apply_hue_palette (floor_right);
    pressed_closer_floor_right = apply_hue_palette (pressed_closer_floor_right);
  }

  if (hgc) {
    floor_right = apply_palette (floor_right, hgc_palette);
    pressed_closer_floor_right = apply_palette (pressed_closer_floor_right, hgc_palette);
  }

  if (peq (p, &mouse_pos)) {
    floor_right = apply_palette (floor_right, selection_palette);
    pressed_closer_floor_right = apply_palette (pressed_closer_floor_right, selection_palette);
  }

  struct coord c; struct pos np;
  draw_bitmapc (floor_right, bitmap,
                pressed_closer_floor_right_coord (p, &c), 0);
  if (! is_strictly_traversable (prel (p, &np, 0, +1)))
    draw_bitmapc (pressed_closer_floor_right, bitmap,
                  floor_right_coord (p, &c), 0);
}
Esempio n. 22
0
void
draw_room_anim_fg_sub (ALLEGRO_BITMAP *bitmap,
                       enum em em, enum vm vm, struct anim *a)
{
  struct pos pm, ptl, ptr, ptl2, ptr2;

  struct frame *f = &a->f;
  struct coord c; frame2room (f, room_view, &c);

  int w = al_get_bitmap_width (f->b);
  int h = al_get_bitmap_height (f->b);

  survey (_m, posf, f, NULL, &pm, NULL);
  survey (_tl, posf, f, NULL, &ptl, NULL);
  survey (_tr, posf, f, NULL, &ptr, NULL);

  pos2room (&pm, room_view, &pm);
  pos2room (&ptl, room_view, &ptl);
  pos2room (&ptr, room_view, &ptr);

  survey (_tl, pos, f, NULL, &ptl2, NULL);
  survey (_tr, pos, f, NULL, &ptr2, NULL);

  pos2room (&ptl2, room_view, &ptl2);
  pos2room (&ptr2, room_view, &ptr2);

  push_clipping_rectangle (bitmap, c.x, c.y, w, h);

  /* SWORD */
  if (fake (&pm) == CARPET
      && a->f.dir == RIGHT
      && a->xf.b) {
    struct coord c2;
    int w2 = al_get_bitmap_width (a->xf.b);
    int h2 = al_get_bitmap_height (a->xf.b);
    xframe_coord (&a->f, &a->xf, &c2);
    ignore_clipping_rectangle_intersection = true;
    push_clipping_rectangle (bitmap, c2.x, c2.y, w2, h2);
    push_drawn_rectangle (bitmap);
    draw_confg_right (bitmap, &pm, em, vm);
    redraw_drawn_rectangle (pop_drawn_rectangle (), &pm, em, vm);
    pop_clipping_rectangle ();
    ignore_clipping_rectangle_intersection = false;
  }

  /* CLIMBING STAIRS */
  if (is_kid_stairs (f)) draw_level_door_fg (bitmap, &a->p, f, em, vm);

  /* FALLING */
  if (is_anim_fall (f)) {
    push_clipping_rectangle (bitmap,
                             PLACE_WIDTH * ptr2.place,
                             PLACE_HEIGHT * ptr2.floor + 56,
                             PLACE_WIDTH + 12,
                             PLACE_HEIGHT - 53);

    push_drawn_rectangle (bitmap);

    if (! is_strictly_traversable_fake (&ptr2))
      draw_confg (bitmap, &ptr2, em, vm);
    if (! is_strictly_traversable_fake (&ptr))
      draw_confg (bitmap, &ptr, em, vm);

    redraw_drawn_rectangle (pop_drawn_rectangle (), &ptr2, em, vm);

    pop_clipping_rectangle ();
  }

  /* VERTICAL JUMP */
  if (is_kid_vjump_touching_above (f)) {
    push_clipping_rectangle (bitmap,
                             PLACE_WIDTH * ptl2.place,
                             PLACE_HEIGHT * ptl2.floor + 56,
                             2 * PLACE_WIDTH,
                             PLACE_HEIGHT - 56 + 3);

    push_drawn_rectangle (bitmap);

    draw_confg (bitmap, &ptl2, em, vm);
    draw_confg (bitmap, &ptr, em, vm);

    redraw_drawn_rectangle (pop_drawn_rectangle (), &ptl2, em, vm);

    pop_clipping_rectangle ();
  }

  /* HANGING */
  if (is_kid_hang (f)) {
    struct pos p; get_hanged_pos (&a->hang_pos, f->dir, &p);
    struct pos pb; prel (&p, &pb, +0, f->dir == LEFT ? +1 : -1);
    pos2room (&p, room_view, &p);
    pos2room (&pb, room_view, &pb);

    if (f->dir == RIGHT) {
      push_clipping_rectangle (bitmap,
                               PLACE_WIDTH * p.place,
                               PLACE_HEIGHT * p.floor + 56,
                               PLACE_WIDTH,
                               PLACE_HEIGHT - 53);
      push_drawn_rectangle (bitmap);
      draw_confg (bitmap, &p, em, vm);
      redraw_drawn_rectangle (pop_drawn_rectangle (), &p, em, vm);
    } else {
      push_clipping_rectangle (bitmap,
                               PLACE_WIDTH * pb.place,
                               PLACE_HEIGHT * pb.floor + 56,
                               PLACE_WIDTH,
                               PLACE_HEIGHT - 53);
      push_drawn_rectangle (bitmap);
      draw_confg (bitmap, &pb, em, vm);
      redraw_drawn_rectangle (pop_drawn_rectangle (), &pb, em, vm);
    }

    pop_clipping_rectangle ();
  }

  /* CLIMBING FLOOR */
  if (is_kid_climb (f)) {
    struct pos p; get_hanged_pos (&a->hang_pos, f->dir, &p);
    struct pos pb; prel (&p, &pb, +0, f->dir == LEFT ? +1 : -1);
    pos2room (&p, room_view, &p);
    pos2room (&pb, room_view, &pb);

    if (f->dir == RIGHT) {
      int dy, w;

      if (f->b == kid_climb_00
          || f->b == kid_climb_01
          || f->b == kid_climb_02
          || f->b == kid_climb_08
          || f->b == kid_climb_09) {
        dy = 55;
        w = 18;
      } else if (f->b == kid_climb_05
                 || f->b == kid_climb_06) {
        dy = 53;
        w = 22;
      } else if (f->b == kid_climb_03
                 || f->b == kid_climb_07
                 || f->b == kid_climb_04) {
        dy = 53;
        w = 21;
      }

      push_clipping_rectangle (bitmap,
                               PLACE_WIDTH * p.place,
                               PLACE_HEIGHT * p.floor + dy,
                               w,
                               PLACE_HEIGHT - dy + 3);
      push_drawn_rectangle (bitmap);
      draw_confg (bitmap, &p, em, vm);
      redraw_drawn_rectangle (pop_drawn_rectangle (), &p, em, vm);
    } else {
      push_clipping_rectangle (bitmap,
                               PLACE_WIDTH * pb.place,
                               PLACE_HEIGHT * pb.floor + 54,
                               PLACE_WIDTH,
                               PLACE_HEIGHT - 54 + 3);
      push_drawn_rectangle (bitmap);
      draw_confg (bitmap, &pb, em, vm);
      redraw_drawn_rectangle (pop_drawn_rectangle (), &pb, em, vm);
    }

    pop_clipping_rectangle ();
  }

  pop_clipping_rectangle ();

  draw_room_frame_fg (bitmap, em, vm, f);

  /* xframe */
  if (a->xf.b) {
    struct frame xf; xframe_frame (&a->f, &a->xf, &xf);
    draw_room_frame_fg (bitmap, em, vm, &xf);
  }

  /* splash */
  if (a->splash) {
    struct frame sf; splash_frame (&a->f, &sf);
    draw_room_frame_fg (bitmap, em, vm, &sf);
  }
}
Esempio n. 23
0
static bool
physics_in (struct anim *g)
{
  struct coord nc;
  struct pos np, pbf, pmt, pmtf, pmtb,
    npmbo, npmbo_nf;
  struct frame nf;
  struct frame_offset fo;

  if (g->i == 0) {
    next_frame (&g->f, &g->f, &g->fo);

    int dirf = (g->f.dir == LEFT) ? -1 : +1;
    int dirb = (g->f.dir == LEFT) ? +1 : -1;
    survey (_mt, pos, &g->f, &nc, &pmt, &np);
    prel (&pmt, &pmtf, +0, dirf);
    prel (&pmt, &pmtb, +0, dirb);

    if (! is_strictly_traversable (&pmt)
        || ! is_strictly_traversable (&pmtf)
        || ! is_strictly_traversable (&pmtb))
      place_in_initial_fall (g);
  }

  /* fall speed */
  if (g->i > 0)
    g->fo.dx = -g->inertia;
  if (g->i > 4) {
    int speed = +21 + 3 * (g->i - 5);
    g->fo.dy = (speed > 33) ? 33 : speed;
  }

  /* land on ground */
  struct frameset *frameset = get_guard_fall_frameset (g->type);
  fo.b = frameset[g->i > 2 ? 2 : g->i].frame;
  fo.dx = frameset[g->i > 2 ? 2 : g->i].dx;
  fo.dy = frameset[g->i > 2 ? 2 : g->i].dy;

  if (g->i > 0) g->fo.dx = -g->inertia;
  if (g->i > 2) {
    int speed = +21 + 3 * (g->i - 5);
    fo.dy = (speed > 33) ? 33 : speed;
  }
  fo.dy += 8;

  survey (_mbo, pos, &g->f, &nc, &np, &npmbo);
  next_frame (&g->f, &nf, &fo);
  survey (_mbo, pos, &nf, &nc, &np, &npmbo_nf);

  if (g->i > 2
      && ! is_strictly_traversable (&npmbo)
      && npmbo.floor != npmbo_nf.floor) {
    g->inertia = g->cinertia = 0;

    if (is_colliding (&g->f, &g->fo, +16, false, &g->ci)) {
      if (g->ci.t != WALL)
        g->f.c.x += (g->f.dir == LEFT) ? +16 : -16;
      else
        g->f.c.x += (g->f.dir == LEFT) ? +8 : -8;
    }

    survey (_bf, pos, &g->f, &nc, &pbf, &np);
    /* pos2view (&pbf, &pbf); */
    frameset = get_guard_vigilant_frameset (g->type);
    g->f.b = frameset[0].frame;
    place_on_the_ground (&g->f, &g->f.c);

    shake_loose_floor_row (&pbf);

    if (g->i >= 8 && ! g->immortal
        && ! g->fall_immune) {
      g->hurt = true;
      g->splash = true;
      g->current_lives--;

      if (g->i >= 10) g->current_lives = 0;

      if (g->current_lives > 0) g->uncouch_slowly = true;
    } else if (g->i > 3) {
      play_sample (hit_ground_sample, g->f.c.room);
      g->hurt = false;
    } else g->hurt = false;

    stop_sample (g->sample, scream_sample);

    survey (_mt, pos, &g->f, &nc, &pmt, &np);
    g->p = pmt;

    if (con (&pmt)->fg == SPIKES_FLOOR
        && ! spikes_floor_at_pos (&pmt)->inactive)
      guard_die_spiked (g);
    else if (g->current_lives <= 0) {
      play_sample (hit_ground_fatal_sample, g->f.c.room);
      guard_die_suddenly (g);
      g->death_reason = FALL_DEATH;
    } else {
      place_on_the_ground (&g->f, &g->f.c);
      g->f.c.y++;
      guard_vigilant (g);
    }

    return false;
  }

  return true;
}