예제 #1
0
파일: room.c 프로젝트: oitofelix/mininim
void
redraw_drawn_rectangle (struct drawn_rectangle *dr, struct pos *p,
                        enum em em, enum vm vm)
{
  if (dr->w <= 0 || dr->h <= 0) return;

  push_clipping_rectangle (dr->bitmap, dr->x, dr->y, dr->w, dr->h);

  struct coord tl, br;
  new_coord (&tl, &global_level, room_view, dr->x, dr->y);
  new_coord (&br, &global_level, room_view, dr->x + dr->w - 1,
             dr->y + dr->h - 1);

  struct pos ptl, pbr;
  posf (&tl, &ptl);
  posf (&br, &pbr);

  pos2room (&ptl, room_view, &ptl);
  pos2room (&pbr, room_view, &pbr);
  struct pos p0 = ptl;
  for (p0.floor = pbr.floor; p0.floor >= ptl.floor; p0.floor--)
    for (p0.place = ptl.place; p0.place <= pbr.place; p0.place++)
      if (! peq (&p0, p)) draw_confg (dr->bitmap, &p0, em, vm);

  pop_clipping_rectangle ();
}
예제 #2
0
static bool
flow (struct anim *k)
{
  struct coord nc; struct pos np, pm, ptf;

  if (k->oaction != kid_jump)
    k->i = -1, k->misstep = k->hang = false;

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

  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 front */
  survey (_m, pos, &k->f, &nc, &pm, &np);
  survey (_tf, pos, &k->f, &nc, &ptf, &np);
  if (k->i >= 8 && k->i <= 10 && hang_front
      && (is_hangable_pos (&pm, k->f.dir)
          || is_hangable_pos (&ptf, k->f.dir))) {
    if (is_hangable_pos (&pm, k->f.dir)) k->hang_pos = pm;
    else if (is_hangable_pos (&ptf, k->f.dir)) k->hang_pos = ptf;
    pos2room (&k->hang_pos, k->f.c.room, &k->hang_pos);
    k->hang = true;
    play_sample (hang_on_fall_sample, k->f.c.room);
    kid_hang (k);
    return false;
  }

  /* hang back */
  survey (_tf, pos, &k->f, &nc, &ptf, &np);
  if (k->i >= 8 && k->i <= 10
      && hang_back && is_hangable_pos (&ptf, back_dir)) {
    k->hang_pos = ptf;
    pos2room (&k->hang_pos, k->f.c.room, &k->hang_pos);
    k->hang = true;
    play_sample (hang_on_fall_sample, k->f.c.room);
    kid_turn (k);
    return false;
  }

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

  select_frame (k, kid_jump_frameset, k->i + 1);

  if (k->f.b == kid_stabilize_frameset[0].frame) k->fo.dx = +2;
  if (k->f.b == kid_stabilize_frameset[1].frame) k->fo.dx = +6;
  if (k->f.b == kid_stabilize_frameset[2].frame) k->fo.dx = +4;
  if (k->f.b == kid_stabilize_frameset[3].frame) k->fo.dx = +0;

  return true;
}
예제 #3
0
파일: fight.c 프로젝트: oitofelix/mininim
bool
is_pos_on_back (struct anim *k, struct pos *p)
{
  struct pos pm, pv;
  survey (_m, pos, &k->f, NULL, &pm, NULL);

  pos2room (p, pm.room, &pv);

  return pm.room == pv.room
    && ((k->f.dir == LEFT && pv.place > pm.place)
        || (k->f.dir == RIGHT && pv.place < pm.place));
}
예제 #4
0
파일: pos.c 프로젝트: oitofelix/mininim
struct frame *
place_frame (struct frame *f, struct frame *nf, ALLEGRO_BITMAP *b,
             struct pos *p, int dx, int dy)
{
  struct pos pv;
  *nf = *f;
  pos2room (p, f->c.room, &pv);
  nf->b = b;
  new_coord (&nf->c, pv.l, pv.room,
             PLACE_WIDTH * pv.place + dx,
             PLACE_HEIGHT * pv.floor + dy);
  return nf;
}
예제 #5
0
파일: fight.c 프로젝트: oitofelix/mininim
bool
is_in_range (struct anim *k0, struct anim *k1, int r)
{
  struct coord m0, m1; struct pos p0, p1;
  survey (_m, pos, &k0->f, &m0, &p0, NULL);
  survey (_m, pos, &k1->f, &m1, &p1, NULL);
  coord2room (&m1, m0.room, &m1);
  pos2room (&p1, p0.room, &p1);

  return m1.room == m0.room
    && p1.floor == p0.floor
    && abs (m1.x - m0.x) < r;
}
예제 #6
0
파일: pos.c 프로젝트: oitofelix/mininim
struct pos *
get_new_rel_pos (struct pos *old_src, struct pos *old_dest,
                 struct pos *new_src, struct pos *new_dest)
{

  struct pos nold_src; npos (old_src, &nold_src);
  struct pos nold_dest; npos (old_dest, &nold_dest);
  struct pos nnew_src; npos (new_src, &nnew_src);

  pos2room (&nold_dest, nold_src.room, &nold_dest);
  if (nold_dest.room != nold_src.room)
    return invalid_pos (new_dest);

  new_pos (new_dest, nnew_src.l, nnew_src.room,
           nnew_src.floor + (nold_dest.floor - nold_src.floor),
           nnew_src.place + (nold_dest.place - nold_src.place));

  return npos (new_dest, new_dest);
}
예제 #7
0
void
loose_floor_fall_debug (void)
{
  int i;
  for (i = 0; i < loose_floor_nmemb; i++) {
    struct loose_floor *l = &loose_floor[i];
    if (l->action != FALL_LOOSE_FLOOR) continue;
    struct pos pv; pos2room (&l->p, room_view, &pv);
    struct coord cv; coord2room (&l->f.c, room_view, &cv);
    printf ("(%i,%i,%i) == (%i,%i,%i) <%i,%i,%i> <%i,%i,%i> ? %i ? %i\n",
            l->p.room, l->p.floor, l->p.place,
            pv.room, pv.floor, pv.place,
            l->f.c.room, l->f.c.x, l->f.c.y,
            cv.room, cv.x, cv.y,
            peq (&l->p, &pv),
            cpos (&l->p, &pv));
    draw_falling_loose_floor (screen, &loose_floor[i].p, em, vm);
  }
}
예제 #8
0
파일: fight.c 프로젝트: oitofelix/mininim
void
fight_turn_controllable (struct anim *k)
{
  int d = INT_MAX;
  int t; /* threshold */
  struct anim *ke = NULL;
  struct anim *ke0 = get_anim_by_id (k->enemy_id);

  /* make the kid target the nearest enemy targeting him */
  int i;
  for (i = 0; i < anima_nmemb; i++) {
    struct anim *a = &anima[i];
    if (a->enemy_id != k->id || ! is_fightable_anim (a))
      continue;
    int de = dist_enemy (a);
    if (de < d) {
      d = de;
      ke = a;
    }
  }

  if (ke && ke0 && ke->f.dir != ke0->f.dir) t = 20;
  else t = -1;

  if (ke && abs (dist_enemy (k) - d) > t)
    consider_enemy (k, ke);

  ke = get_anim_by_id (k->enemy_id);
  if (ke) {
    struct pos p, pe;
    survey (_m, pos, &k->f, NULL, &p, NULL);
    survey (_m, pos, &ke->f, NULL, &pe, NULL);
    pos2room (&pe, p.room, &pe);
    if (is_on_back (k, ke)
        && ! is_in_range (k, ke, INVERSION_RANGE)
        && is_in_fight_mode (k)
        && is_in_fight_mode (ke)
        && p.room == pe.room
        && p.floor == pe.floor)
      fight_turn (k);
  }
}
예제 #9
0
파일: fight.c 프로젝트: oitofelix/mininim
bool
is_hearing (struct anim *k0, struct anim *k1)
{
  struct pos p0, p1;
  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);

  return p1.room == p0.room
    && (is_kid_run (&k1->f)
        || is_kid_stop_run (&k1->f)
        || is_kid_jump_landing (&k1->f)
        || is_kid_run_jump_running (&k1->f)
        || is_kid_run_jump_landing (&k1->f)
        || (is_kid_couch (&k1->f)
            && k1->fall)
        || k1->action == kid_take_sword);
}
예제 #10
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;
}
예제 #11
0
void
compute_choppers (void)
{
  size_t i, j;

  for (i = 0; i < chopper_nmemb; i++) {
    struct chopper *c = &chopper[i];

    if (c->inactive) continue;

    switch (c->i) {
    case 0:
      if (! c->alert) c->alert = ! should_chomp (&c->p);
      if ((c->wait-- <= 0 && should_chomp (&c->p)
           && (anim_cycle % CHOPPER_WAIT) ==
           prandom_pos (&c->p, CHOPPER_WAIT - 1))
          || c->activate) {
        c->i++;
        register_changed_pos (&c->p, CHPOS_CHOPPER);
      }
      break;
    case 1: c->i++;
      if (c->alert) {
        alert_guards (&c->p);
        c->alert = false;
      }
      play_sample (chopper_sample, &c->p, -1);
      register_changed_pos (&c->p, CHPOS_CHOPPER);
      break;
    case 2:
      c->i++;
      register_changed_pos (&c->p, CHPOS_CHOPPER);
      break;
    case 3:
      c->i++;
      register_changed_pos (&c->p, CHPOS_CHOPPER);
      break;
    case 4: c->i = 0; c->wait = CHOPPER_WAIT; c->activate = false;
      register_changed_pos (&c->p, CHPOS_CHOPPER);
      break;
    }

    if (c->i != 1 && c->i != 2 ) continue;

    /* chomp kid */
    for (j = 0; j < anima_nmemb; j++) {
      struct anim *a = &anima[j];
      if (a->type == MOUSE
          || is_anim_fall (&a->f)
          || a->immortal
          || a->chopper_immune
          || (a->action == kid_walk && a->walk != -1))
        continue;
      struct pos pbf, pbb;
      survey (_bf, pos, &a->f, NULL, &pbf, NULL);
      survey (_bb, pos, &a->f, NULL, &pbb, NULL);
      pos2room (&pbf, c->p.room, &pbf);
      pos2room (&pbb, c->p.room, &pbb);
      if ((((pbf.room == c->p.room
             && pbf.floor == c->p.floor)
            || (pbb.room == c->p.room
                && pbb.floor == c->p.floor))
           && ((a->f.dir == LEFT && pbf.place < c->p.place
                && pbb.place >= c->p.place)
               || (a->f.dir == RIGHT && pbf.place >= c->p.place
                   && pbb.place < c->p.place)))
          && (! is_anim_dead (&a->f) || ! is_anim_chopped (&a->f))) {
        if (a->type != SKELETON) c->blood = true;
        a->splash = true;
        a->p = c->p;
        a->death_reason = CHOPPER_DEATH;
        if (a->id == current_kid_id) {
          mr.flicker = 2;
          mr.color = get_flicker_blood_color ();
        }
        if (a->type == SKELETON)
          play_sample (skeleton_sample, &c->p, -1);
        else play_sample (chopped_sample, &c->p, -1);
        anim_die_chopped (a);
      }
    }
  }
}
예제 #12
0
파일: fight.c 프로젝트: oitofelix/mininim
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);
}
예제 #13
0
파일: fight.c 프로젝트: oitofelix/mininim
void
leave_fight_logic (struct anim *k)
{
  /* dead character doesn't fight */
  if (k->current_lives <= 0) {
    k->enemy_refraction = 0;
    forget_enemy (k);
    return;
  }

  /* non-fightable characters don't fight */
  if (! is_fightable_anim (k)) return;

  /* no enemy, no need to forget */
  if (k->enemy_id == -1) return;

  /* non-fighter doesn't fight */
  if (! k->fight) return;

  /* character that went upstairs doesn't fight */
  if (is_kid_stairs (&k->f)) {
    k->enemy_refraction = 0;
    forget_enemy (k);
    return;
  }

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

  /* if the enemy doesn't exist, forget about it */
  if (! ke) {
    k->enemy_refraction = 0;
    forget_enemy (k);
    return;
  }

  /* if the enemy is dead no need to worry about him */
  if (ke->current_lives <= 0) {
    k->enemy_refraction = 0;
    forget_enemy (k);
    return;
  }

  /* if the enemy went up stairs, forget about him */
  if (is_kid_stairs (&ke->f)) {
    k->enemy_refraction = 0;
    forget_enemy (k);
    return;
  }

  /* if the enemy is not reachable, forget about him */
  enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT;
  struct pos p, pe;
  survey (_m, pos, &k->f, NULL, &p, NULL);
  survey (_m, pos, &ke->f, NULL, &pe, NULL);
  pos2room (&pe, p.room, &pe);
  if (! is_anim_seeing (k, ke, k->f.dir)
      && ! is_near (k, ke)
      && ! is_safe_to_follow (k, ke, k->f.dir)
      && ! (is_on_back (k, ke) && is_anim_seeing (k, ke, odir)
            && p.floor == pe.floor)) {
    forget_enemy (k);
    return;
  }
}
예제 #14
0
파일: fight.c 프로젝트: oitofelix/mininim
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;
  }
}
예제 #15
0
파일: room.c 프로젝트: oitofelix/mininim
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);
  }
}
예제 #16
0
파일: room.c 프로젝트: oitofelix/mininim
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 ();
}