Пример #1
0
void
fight_inversion_mechanics (struct anim *k, struct anim *ke)
{
  if (is_in_range (k, ke, INVERSION_RANGE)
      && is_in_fight_mode (k)
      && is_in_fight_mode (ke)
      && ! is_sword_hit (k)
      && ! is_sword_hit (ke)
      && (! is_attacking (k) || k->i > 4)
      && (! is_attacking (ke) || k->i > 4)) {
    struct coord c;
    c = k->f.c;
    k->f.c = ke->f.c;
    ke->f.c = c;

    place_on_the_ground (&k->f, &k->f.c);
    place_on_the_ground (&ke->f, &ke->f.c);

    fight_turn (k);
    fight_turn (ke);

    backoff_from_range (ke, k, INVERSION_RANGE + 4, false, false);
  }
}
Пример #2
0
/* Try to find ALL the solutions, so we check every possible combination. */
void
next_queen (int (*board)[COL_MAX + 1], int row, List* list)
{
    int col;
    /* printf ("next_q board=%d\n", &board[0][0]);  */
    for (col = 0; col < COL_MAX + 1; col++) {
        /* printf ("row=%d,col=%d\n", row, col);  */
        if (!is_attacking(board, row, col)) {
            board[row][col] = occupied;
            if (row == ROW_MAX) {
                if (new_solution (board, list)) {
                    print_solution (board);
                }
            }
            else {
                next_queen (board, ++row, list);
                row--;
            }
        }
        board[row][col] = empty; /* Remove the queen to try the next col. */
    }
}
Пример #3
0
void
fight_mechanics (struct anim *k)
{
  if (k->sword_immune > 0) k->sword_immune--;

  /* 'ke' is the attacking part */
  struct anim *ke = get_anim_by_id (k->enemy_id);

  if (! ke || ke->enemy_id != k->id) return;

  fight_inversion_mechanics (k, ke);

  if (! is_attacking (ke) || is_sword_hit (k)) return;

  if (! ke->attack_range_far)
    ke->attack_range_far =
      (is_in_range (k, ke, ATTACK_RANGE + 16) && ke->i == 0);

  if (! ke->attack_range_near)
    ke->attack_range_near =
      (is_in_range (k, ke, ATTACK_RANGE) && ke->i == 0);

  if (! ke->enemy_defended_my_attack)
    ke->enemy_defended_my_attack =
      (ke->i < 4 && k->key.up && ke->attack_range_far)
      || (ke->attack_range_far && ! ke->attack_range_near);

  if (is_walkingf (k) || is_attacking (k) || ! is_in_fight_mode (k))
    ke->enemy_defended_my_attack = 0;

  bool walkb = ((k->f.dir == RIGHT) && k->key.left)
    || ((k->f.dir == LEFT) && k->key.right);

  if (! ke->enemy_counter_attacked_myself)
    ke->enemy_counter_attacked_myself =
      (ke->enemy_defended_my_attack && k->key.shift
       && prandom (99) <= k->skill.counter_attack_prob
       && (ke->attack_range_near || k->attack_range_near)
       && ! walkb);

  if (! ke->i_counter_defended)
    ke->i_counter_defended =
      (ke->enemy_counter_attacked_myself && ke->key.up
       && prandom (99) <= ke->skill.counter_defense_prob);

  if (! k->hurt_enemy_in_counter_attack)
    k->hurt_enemy_in_counter_attack =
      (ke->enemy_counter_attacked_myself && ! ke->i_counter_defended);

  /* printf ("ke->attack_range_near: %i\n", ke->attack_range_near); */

  /* printf ("ke->enemy_defended_my_attack = %i, ke->i = %i, k->key.up = %i\n", */
  /*         ke->enemy_defended_my_attack, ke->i, k->key.up); */

  if (! ke->enemy_defended_my_attack && is_at_hit_frame (ke)
      && ! is_on_back (ke, k)
      && (ke->attack_range_far || ! is_in_fight_mode (k))
      && ((is_in_range (k, ke, HIT_RANGE + 4) && is_in_fight_mode (k))
          || (is_in_range (k, ke, ATTACK_RANGE) && ! is_in_fight_mode (k))))
    fight_hit (k, ke);
  else if (ke->hurt_enemy_in_counter_attack
           && is_at_hit_frame (ke)
           && ! is_on_back (ke, k)) fight_hit (k, ke);
  else if (ke->enemy_defended_my_attack == 1
           && is_at_defendable_attack_frame (ke)) {
    if (is_in_range (k, ke, HIT_RANGE + 8)
        || is_defending (k)) {
      backoff_from_range (ke, k, ATTACK_RANGE - 20, false, false);
      get_in_range (ke, k, ATTACK_RANGE - 6, false, false);
      put_at_attack_frame (ke);
      put_at_defense_frame (k);
    } else ke->enemy_defended_my_attack = false;
  }

/*   printf ("id: %i, ad: %i, ca: %i, cd: %i, i: %i, hurt: %i\n\ */
/* id: %i, ad: %i, ca: %i, cd: %i, i: %i, hurt: %i\n\ */
/* -------------------------------\n", */
/*           k->id, k->enemy_defended_my_attack, k->enemy_counter_attacked_myself, k->i_counter_defended, k->i, k->hurt, */
/*           ke->id, ke->enemy_defended_my_attack, ke->enemy_counter_attacked_myself, ke->i_counter_defended, ke->i, ke->hurt); */
}
Пример #4
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;
  }
}