176 lines
5.8 KiB
C++
176 lines
5.8 KiB
C++
#include "player.h"
|
|
|
|
#include "constants.h"
|
|
#include "enemy.h"
|
|
#include "level.h"
|
|
|
|
player_base::player_base(RNG *rng, const feature enabled_features,
|
|
const enum race &nrace):
|
|
character{rng, enabled_features, nrace, {0, 0}}, gold_cnt(0) {}
|
|
|
|
void player_base::print(output *out) {
|
|
out->print_char(pos, '@', COLOR_PAIR(COLOR_BLUE));
|
|
}
|
|
|
|
std::string player_base::get_abbrev() const {
|
|
return "PC";
|
|
}
|
|
|
|
int player_base::get_gold() const {
|
|
return this->gold_cnt;
|
|
}
|
|
|
|
int player_base::get_ATK() const {
|
|
return this->ATK;
|
|
}
|
|
|
|
int player_base::get_DEF() const {
|
|
return this->DEF;
|
|
}
|
|
|
|
int player_base::get_HP() const {
|
|
return this->HP;
|
|
}
|
|
|
|
long_result player_base::apply(potion *p) {
|
|
if (p == nullptr)
|
|
return {result::applied_nothing,
|
|
"PC tried to breathe the magic in the air. "};
|
|
|
|
apply_effect(p);
|
|
|
|
if (race == rt_800)
|
|
return {result::applied,
|
|
"PC gets rusty joints (-5 HP). "};
|
|
|
|
return {result::applied,
|
|
(std::string)"PC applied potion of " + p->get_name() + ". "};
|
|
}
|
|
|
|
long_result player_base::attack(character *ch) {
|
|
if (ch == nullptr)
|
|
return {result::fine,
|
|
"PC tried to attack thin air. "};
|
|
|
|
return ch->get_hit(this, ATK, base_hit_rate);
|
|
}
|
|
|
|
long_result player_base::move(level *lvl,
|
|
const position &p) {
|
|
if (enabled_features & FEATURE_NCURSES) {
|
|
enemy_base *tmp = nullptr;
|
|
|
|
if (lvl->is_available(p, true)) {
|
|
pos = p;
|
|
return {result::moved, ""};
|
|
} else if ((tmp = get_enemy_at(p, lvl->get_elist())) != nullptr) {
|
|
auto res = attack((character *)tmp);
|
|
|
|
if (tmp->is_dead())
|
|
tmp->dies(lvl, this);
|
|
|
|
return res;
|
|
}
|
|
} else if (lvl->get_up_stairs() == p &&
|
|
enabled_features & FEATURE_REVISIT) {
|
|
return {result::go_up, "PC went up the stairs. "};
|
|
} else if (lvl->get_down_stairs() == p) {
|
|
return {result::go_down, "PC went down the stairs. "};
|
|
} else if (lvl->is_available(p, true)) {
|
|
pos = p;
|
|
return {result::moved, ""};
|
|
}
|
|
|
|
return {result::fine, "PC tried to move into non-existent space. "};
|
|
}
|
|
|
|
long_result player_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::died,
|
|
ch->get_abbrev() + " deals " +
|
|
std::to_string(tmp) +
|
|
" damage to PC. PC is slain by " +
|
|
ch->get_abbrev() + ". "};
|
|
|
|
return {result::hit, ch->get_abbrev() + " deals " +
|
|
std::to_string(tmp) +
|
|
" damage to PC. "};
|
|
}
|
|
|
|
return {result::miss, ch->get_abbrev() + " tried to hit PC but missed. "};
|
|
}
|
|
|
|
void player_base::add_gold(int amount) {
|
|
gold_cnt += amount;
|
|
}
|
|
|
|
long_result player_base::interpret_command(level *lvl, game_command cmd) {
|
|
if (cmd == game_command_terminate) {
|
|
return {result::terminate, ""};
|
|
} else if (cmd >= move_north && cmd <= move_southwest) {
|
|
auto res = move(lvl, pos + MOVE[cmd - move_north]);
|
|
|
|
if (res.res == result::moved)
|
|
start_turn();
|
|
|
|
gold g = get_gold_at(pos, lvl->get_glist());
|
|
gold_cnt += g.amount;
|
|
return res;
|
|
} else if (cmd >= apply_north && cmd <= apply_southwest) {
|
|
auto res = apply(get_potion_at(pos + MOVE[cmd - apply_north],
|
|
lvl->get_plist()));
|
|
|
|
if (res.res == result::applied)
|
|
start_turn();
|
|
|
|
return res;
|
|
} else if (cmd == apply_panic) {
|
|
return {result::fine,
|
|
"PC tried to use in some non-existent direction. "};
|
|
} else if (cmd >= attack_north && cmd <= attack_southwest) {
|
|
enemy_base *tmp = get_enemy_at(pos + MOVE[cmd - attack_north],
|
|
lvl->get_elist());
|
|
|
|
if (tmp != nullptr)
|
|
start_turn();
|
|
|
|
auto res = attack((character *)tmp);
|
|
|
|
if (tmp != nullptr && tmp->is_dead())
|
|
tmp->dies(lvl, this);
|
|
|
|
return res;
|
|
} else if (cmd == up_stairs) {
|
|
if (lvl->get_up_stairs() == pos &&
|
|
enabled_features & FEATURE_REVISIT) {
|
|
start_turn();
|
|
return {go_up, "PC went up the stairs. "};
|
|
}
|
|
|
|
return {result::fine,
|
|
"PC tried to fly through the ceiling. "};
|
|
} else if (cmd == down_stairs) {
|
|
if (lvl->get_down_stairs() == pos) {
|
|
start_turn();
|
|
return {go_down, "PC went down the stairs. "};
|
|
}
|
|
|
|
return {result::fine,
|
|
"PC tried to dig through the floor. "};
|
|
} else if (cmd == the_world) {
|
|
return{toggle_the_world, "PC toggled Stand: The World! "};
|
|
} else if (cmd == game_restart) {
|
|
return {restart_game, ""};
|
|
} else if (cmd == game_command_pass) {
|
|
return {result::fine, ""};
|
|
}
|
|
|
|
return {unknown, "PC tried to produce some undefined behaviour. "};
|
|
}
|