#include "enemy.h" #include "constants.h" #include "player.h" #include "level.h" enemy_base::enemy_base(RNG *rng, const feature enabled_features, const enum race &nrace, const position &pos, const int gen_room_num, std::string abbrev): character{rng, enabled_features, nrace, pos}, room_num{gen_room_num}, abbrev{abbrev} {} int enemy_base::get_room_num() const { return room_num; } long_result enemy_base::act(level *lvl, character *pc, bool hostile) { if (is_adjacent(pos, pc->get_pos()) && hostile) return attack(pc); if (enabled_features & FEATURE_ENEMIES_CHASE && hostile && distance_sqr(pos, pc->get_pos()) <= DIST_THRESHOLD_SQR) { position tmp; position target = {BIG_NUMBER, BIG_NUMBER}; for (int i = 0; i < DIRECTION_CNT; ++i) { tmp = pos + MOVE[i]; if (((enabled_features & FEATURE_DOORS) ? true : lvl->get_room(tmp) == room_num) && lvl->is_available(tmp) && distance_sqr(tmp, pc->get_pos()) < distance_sqr(target, pc->get_pos())) target = tmp; } if (target.x != BIG_NUMBER) pos = target; return {NOTHING, ""}; } int choices_cnt = 0; position choices[DIRECTION_CNT]; for (int i = 0; i < DIRECTION_CNT; ++i) if (((enabled_features & FEATURE_DOORS) ? true : lvl->get_room(pos + MOVE[i]) == room_num ) && lvl->is_available(pos + MOVE[i])) { choices[choices_cnt] = pos + MOVE[i]; ++choices_cnt; } if (choices_cnt) pos = choices[rng->rand_under(choices_cnt)]; return {NOTHING, ""}; } long_result enemy_base::attack(character *ch) { return ch->get_hit(this, ATK, base_hit_rate); } std::string enemy_base::get_abbrev() const { return abbrev; } long_result enemy_base::get_hit(character *ch, const int tATK, const fraction &hit_rate) { if (rng->trial(hit_rate)) { int tmp = calc_dmg(tATK, DEF); tmp = tmp > HP ? HP : tmp; HP -= tmp; if (HP == 0) return {result::HIT, "PC deals " + std::to_string(tmp) + " damage to " + abbrev + " (" + std::to_string(HP) + " HP). " + abbrev + " is slain by PC. "}; return {result::HIT, "PC deals " + std::to_string(tmp) + " damage to " + abbrev + " (" + std::to_string(HP) + " HP). "}; } return {MISS, "PC tried to hit " + abbrev + " but missed. "}; } int enemy_base::dies(level *lvl) { return rand_gold_drop(rng); } enemy_base *get_enemy_at(const position &pos, const enemy_list &elist) { for (auto e : elist) if (e->get_pos() == pos) return e; return nullptr; } void enemy_base::print(output *out) { out->print_char(pos, CHAR_REP[race], COLOR_PAIR(COLOR_RED)); }