#include #include #include #include #include #include "game_engine.hpp" #include const auto ERROR = fmt::emphasis::bold | fg(fmt::color::red); using namespace fmt; using namespace std; GameEngine::GameEngine(int hp) : starting_hp(hp) { hit_points = max_hp(); }; int GameEngine::determine_damage(string &type) { try { return damage_types.at(type); } catch(std::out_of_range &err) { print(ERROR, "BAD DAMAGE TYPE {}\n", type); return 0; } } void GameEngine::reset() { println("!!!!!!! RESET hit_points={}, max={}", hit_points, max_hp()); if(free_death) { hit_points = max_hp() * 0.5f; } else { streak = 0; hit_points = max_hp(); } println("!!!!!!!! AFTER RESET hit_points={}, max={}", hit_points, max_hp()); free_death = false; } bool GameEngine::hit(string &type) { int damage = determine_damage(type); hit_points -= damage; ++hits_taken; return is_dead(); } void GameEngine::heal() { hit_points = hit_points * 1.10f; if(hit_points > max_hp()) hit_points = max_hp(); } bool GameEngine::is_dead() { return free_death ? false : hit_points <= 0; } void GameEngine::START(GameEvent ev) { state(GameState::IDLE); IDLE(ev); } void GameEngine::IDLE(GameEvent ev) { if(ev == GameEvent::BUILD_START) { hits_taken = 0; state(GameState::IN_ROUND); } else { state(GameState::IDLE); } } void GameEngine::IN_ROUND(GameEvent ev, string &hit_type) { switch(ev) { case GameEvent::HIT: hit(hit_type); // NOTE: don't use is_dead to avoid free_death if(hit_points <= 0) { state(GameState::DEAD); } else { state(GameState::IN_ROUND); } break; case GameEvent::BUILD_SUCCESS: state(GameState::SUCCESS); break; case GameEvent::BUILD_FAILED: state(GameState::FAILURE); break; default: state(GameState::IN_ROUND); } } void GameEngine::DEAD(GameEvent ev) { if(ev == GameEvent::BUILD_DONE) { reset(); state(GameState::FAILURE); FAILURE(ev); } else if(ev == GameEvent::HIT) { ++hits_taken; } else { state(GameState::DEAD); } } void GameEngine::SUCCESS(GameEvent ev) { assert(ev == GameEvent::BUILD_DONE && "success state expected BUILD_DONE"); ++rounds; ++streak; heal(); state(GameState::IDLE); } void GameEngine::FAILURE(GameEvent ev) { assert(ev == GameEvent::BUILD_DONE && "failure state expected BUILD_DONE"); ++rounds; // streak is handled by reset() state(GameState::IDLE); } int GameEngine::max_hp() { return starting_hp * hp_bonus; } void GameEngine::add_bonus(GameBonus bonus) { switch(bonus) { case GameBonus::MORE_HP: hp_bonus += 0.10f; hit_points = max_hp(); break; case GameBonus::FREE_DEATH: free_death = true; break; } }