HALTED: major overhaul for character

This commit is contained in:
2024-07-13 22:05:17 -04:00
parent 39d3447593
commit f0aa564e08
10 changed files with 298 additions and 172 deletions

View File

@ -9,7 +9,8 @@ game::game(const enum race starting_race,
logger *new_log,
RNG *new_rng):
enabled_features{enabled_features},
in{new_in}, out{new_out}, log{new_log}, rng{new_rng} {
in{new_in}, out{new_out}, log{new_log}, rng{new_rng},
curr_turn{0} {
const position nil{0, 0};
the_world = false;
@ -28,7 +29,11 @@ game::game(const enum race starting_race,
levels.reserve(max_level);
curr_level = 0;
hostile_merchants = false;
new_level();
msg += "Player character has spawned. ";
print();
}
void game::new_level() {
@ -41,84 +46,116 @@ void game::new_level() {
}
result game::player_moves(game_command cmd) {
switch (cmd) {
case game_command_terminate:
if (cmd == game_command_terminate) {
return result::terminate;
case move_east: {
} else if (cmd >= move_north && cmd <= move_southwest) { // Tried to move
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(east);
return player_move_or_attack((direction)(cmd - move_north));
return player->move(east, levels[curr_level]->get_available_around(
player->get_position()));
}
case move_west: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(west);
return player->move(west, levels[curr_level]->get_available_around(
player->get_position()));
}
case move_north: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(north);
return player->move(north, levels[curr_level]->get_available_around(
player->get_position()));
}
case move_south: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(south);
return player->move(south, levels[curr_level]->get_available_around(
player->get_position()));
}
case move_northeast: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(northeast);
return player->move(northeast,
return player->move((direction)(cmd - move_north),
levels[curr_level]->get_available_around(
player->get_position()));
} else if (cmd >= apply_north && cmd <= apply_southwest) {
auto res = player->apply((direction)(cmd - apply_north),
levels[curr_level]->get_plist());
if (res.res == applied) {
msg += "PC used potion ";
msg += POTION_REAL_NAME[res.which->get_type()];
msg += ". ";
} else {
msg += "PC tried to drink thin air. ";
}
return res.res;
} else if (cmd == apply_panic) {
msg += "PC tried to use in some non-existent direction. ";
return fine;
} else if (cmd >= attack_north && cmd <= attack_southwest) {
auto res = player->attack((direction)(cmd - attack_north),
levels[curr_level]->get_chlist());
if (res.res == hit) {
msg += "PC deals " + std::to_string(res.dmg_dealt) +
" damage to " +
CHARACTER_REP[res.which->get_race()] +
" (" + std::to_string(res.remaining_HP) +
" HP). ";
} else if (res.res == miss) {
msg += "PC missed ";
msg += CHARACTER_REP[res.which->get_race()];
msg += ". ";
} else {
msg += "PC tried to attack thin air. ";
}
if (res.which->get_race() == rmerchant)
hostile_merchants = true;
return res.res;
} else if (cmd == up_stairs) {
if (player->get_position() ==
levels[curr_level]->get_up_stairs())
return go_up;
msg += "PC tried to fly through the ceiling. ";
return fine;
} else if (cmd == down_stairs) {
if (player->get_position() ==
levels[curr_level]->get_down_stairs())
return go_down;
msg += "PC tried to dig through the floor. ";
return fine;
} else if (cmd == the_world) {
msg += "PC toggled Stand: The World! ";
return toggle_the_world;
} else if (cmd == game_restart) {
return restart_game;
} else if (cmd == game_command_pass) {
return fine;
} else if (cmd == game_command_panic) {
msg += "PC tried to produce some undefined behaviour. ";
return unknown;
}
case move_northwest: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(northwest);
msg += "PC tried to produce some undefined behaviour. ";
return unknown;
}
return player->move(northwest,
levels[curr_level]->get_available_around(
player->get_position()));
}
#include <algorithm>
bool compare_characters(character *&a, character *&b) {
return a->get_position() < b->get_position();
}
case move_southeast: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(southeast);
void game::move_enemies() {
if (the_world)
return;
return player->move(southeast,
levels[curr_level]->get_available_around(
player->get_position()));
}
character_list enemies = levels[curr_level]->get_chlist();
std::sort(enemies.begin(), enemies.end(), &game::compare_characters);
case move_southwest: {
if (enabled_features & FEATURE_NCURSES)
return player_move_or_attack(southwest);
for (auto ch : enemies) {
return player->move(southwest,
levels[curr_level]->get_available_around(
player->get_position()));
}
}
}
game_status game::run() {
player->start_turn();
msg = "";
auto res = player_moves(in->get_command());
if (!(enabled_features & FEATURE_NCURSES) &&
res == result::moved &&
(player->get_position() ==
levels[curr_level]->get_down_stairs()))
res = go_down;
if (!(enabled_features & FEATURE_NCURSES) &&
res == result::moved &&
(player->get_position() ==
levels[curr_level]->get_up_stairs()))
res = go_up;
switch (res) {
case result::terminate:
return terminated;
@ -133,6 +170,7 @@ game_status game::run() {
player->discard_level_effects();
++curr_level;
new_level();
msg += "PC went down a floor. ";
break;
}
@ -140,19 +178,120 @@ game_status game::run() {
if (curr_level == 0)
return game_status::escaped;
player->discard_level_effects();
--curr_level;
player->set_position(levels[curr_level]->get_down_stairs());
msg += "PC went up a floor. ";
break;
}
case toggle_the_world:
the_world = !the_world;
break;
case restart_game:
return restart;
case unknown:
case fine:
case applied_nothing:
++curr_turn;
return game_status::in_game;
default:
break;
}
player->start_turn();
player->apply_effects();
if (player->get_HP() <= 0)
return game_status::dead;
move_enemies();
if (player->get_HP() <= 0)
return game_status::dead;
++curr_turn;
return game_status::in_game;
}
const position STATUS_RACE{0, 25};
const position STATUS_FLOOR{69, 25};
const position STATUS_HP{0, 26};
const position STATUS_ATK{0, 27};
const position STATUS_DEF{0, 28};
const position STATUS_ACTION{0, 29};
const char *ASK_ATK_MERCHANT =
"Action: Do you really want to attack the peaceful merchant? [Y/N]";
size_t game::get_curr_turn() const {
return curr_turn;
}
void game::print() {
if (msg.length() > MAX_MSG_LENGTH) {
msg.resize(MAX_MSG_LENGTH);
msg += "...";
}
levels[curr_level]->print(out);
player->print(out, true);
std::string tmp = "Race: ";
tmp += RACE_NAME[player->get_race()];
tmp += " Gold: " + std::to_string(player->get_gold());
out->print_str(STATUS_RACE, tmp);
tmp = "Floor " + std::to_string(curr_level + 1);
out->print_str(STATUS_FLOOR, tmp);
tmp = "Atk: " + std::to_string(player->get_ATK());
out->print_str(STATUS_ATK, tmp);
tmp = "Def: " + std::to_string(player->get_DEF());
out->print_str(STATUS_DEF, tmp);
tmp = "Action: " + msg;
out->print_str(STATUS_ACTION, tmp);
}
result game::player_move_or_attack(const direction &dir) {
auto avlbl = levels[curr_level]->get_available_around(
player->get_position());
if (find(avlbl, player->get_position() + MOVE[dir])
!= avlbl.size()) {
player->set_position(player->get_position() + MOVE[dir]);
return result::moved;
}
auto tmp = player->get_position() + MOVE[dir];
character *target;
for (auto ch : levels[curr_level]->get_chlist())
if (tmp == ch->get_position()) {
target = ch;
}
auto res = player->attack(dir, target);
if (target->get_race() == rmerchant)
hostile_merchants = true;
if (res.res == hit) {
msg += "PC deals " +
std::to_string(res.dmg_dealt) + " damage to " +
CHARACTER_REP[res.which->get_race()] + " (" +
std::to_string(res.remaining_HP) + " HP). ";
} else if (res.res == miss) {
msg += "PC missed ";
msg += CHARACTER_REP[res.which->get_race()];
msg += ". ";
} else {
msg += "PC tried to attack thin air. ";
}
return res.res;
}