#include "game.h" #include "constants.h" #include "pc.h" game::game(const enum race starting_race, const feature enabled_features, input *new_in, output *new_out, RNG *new_rng): enabled_features{enabled_features}, in{new_in}, out{new_out}, rng{new_rng}, curr_turn{0} { const position nil{0, 0}; the_world = false; // TODO: add the other races player = init_player(rng, enabled_features, starting_race); if (enabled_features & FEATURE_EXTRA_LEVELS) max_level = rng->rand_between(MIN_LEVEL_CNT, MAX_LEVEL_CNT + 1); else max_level = DEFAULT_MAX_LEVEL; levels.reserve(max_level); curr_level = 0; hostile_merchants = false; new_level(); msg += "Player character has spawned. "; print(); } void game::new_level() { if (enabled_features & FEATURE_RAND_MAP) levels.push_back(std::make_unique(player.get(), rng, enabled_features)); else levels.push_back(std::make_unique(default_map, player.get(), rng, enabled_features)); } enemy_list game::sort_enemies(const enemy_list &elist) { enemy_list result; result.reserve(elist.size()); for (auto enemy : elist) { result.push_back(enemy); for (int i = result.size() - 1; i > 0 && enemy->get_pos() < result[i - 1]->get_pos(); --i) std::swap(result[i], result[i - 1]); } return result; } character *game::move_enemies() { auto enemies = sort_enemies(levels[curr_level]->get_elist()); for (auto ch : enemies) { ch->start_turn(); ch->calc_effects(); if (ch->is_dead()) { int g = ch->dies(levels[curr_level].get()); if (g) levels[curr_level]->add_gold(gold{ch->get_pos(), g}); msg += ch->get_abbrev() + " was killed by a potion. "; } } if (the_world) return nullptr; for (auto ch : enemies) { if (ch->is_dead()) { levels[curr_level]->erase_enemy(ch); continue; } bool hostile = ch->get_race() == rmerchant ? hostile_merchants : true; auto res = ch->act(levels[curr_level].get(), player.get(), hostile); if (player->is_dead()) return ch; msg += res.msg; } return nullptr; } game_result game::run() { auto res = player->interpret_command(levels[curr_level].get(), in->get_command()); msg = res.msg; if (!hostile_merchants && res.msg.find(" M") != std::string::npos) { hostile_merchants = true; msg += "PC has angered the merchants. "; } switch (res.res) { case result::terminate: return {terminated, ""}; case result::died: return {dead, "You died: killed by your own stupidity!"}; case result::go_down: { if (curr_level == max_level - 1) return {won, "You won! You collected " + std::to_string(player->get_gold()) + " pieces of gold after " + std::to_string(curr_turn + 1) + " turns!"}; player->start_turn(); player->discard_level_effects(); ++curr_level; if (curr_level == levels.size()) new_level(); if (enabled_features & FEATURE_REVISIT) player->set_pos(levels[curr_level]->get_up_stairs()); break; } case result::go_up: { if (curr_level == 0) return {escaped, "You escaped the dungeon with " + std::to_string(player->get_gold()) + " pieces of gold after " + std::to_string(curr_turn + 1) + " turns! Coward!"}; player->start_turn(); player->discard_level_effects(); --curr_level; player->set_pos(levels[curr_level]->get_down_stairs()); break; } case toggle_the_world: the_world = !the_world; player->start_turn(); break; case restart_game: return {restart, ""}; case unknown: case fine: case applied_nothing: case inventory: return {in_game, ""}; default: player->start_turn(); break; } ++curr_turn; player->calc_effects(); if (player->is_dead()) return {dead, "You died: killed by your own stupidity!"}; auto killer = move_enemies(); if (player->is_dead()) { if (killer == nullptr) return {dead, "You died: killed by your own stupidity!"}; return {dead, std::string{"You died: killed by a(n) "} + killer->get_race_name()}; } return {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 std::string BLANK(DISPLAY_BUFFER_SIZE, ' '); 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 += "..."; } out->print_str({0, 0}, BLANK); levels[curr_level]->print(out); player->print(out); std::string tmp = "Race: "; tmp += player->get_race_name(); tmp += " Gold: " + std::to_string(player->get_gold()); out->print_str(STATUS_RACE, tmp); out->print_str(STATUS_FLOOR, "Floor " + std::to_string(curr_level + 1)); out->print_str(STATUS_HP, "HP: " + std::to_string(player->get_HP())); out->print_str(STATUS_ATK, "Atk: " + std::to_string(player->get_ATK())); out->print_str(STATUS_DEF, "Def: " + std::to_string(player->get_DEF())); out->print_str(STATUS_ACTION, "Action: " + msg); }