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); } }
/* 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. */ } }
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); */ }
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; } }