From 0a9fa59365687805713e0ea70ad56e5fb95fae1c Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 15 Sep 2024 04:19:52 -0400 Subject: [PATCH] The game engine now has two bonuses for long build streaks. +10% max hp or 1 free death. I'll be adding more but that's enough to work on the real UI. --- game_engine.cpp | 43 +++++++++++++++++++++++++++++++++++-------- game_engine.hpp | 8 ++++++++ tests/game_engine.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/game_engine.cpp b/game_engine.cpp index 309ab5a..d5faec4 100644 --- a/game_engine.cpp +++ b/game_engine.cpp @@ -12,7 +12,7 @@ using namespace fmt; using namespace std; GameEngine::GameEngine(int hp) : starting_hp(hp) { - hit_points = starting_hp; + hit_points = max_hp(); }; int GameEngine::determine_damage(string &type) { @@ -25,8 +25,17 @@ int GameEngine::determine_damage(string &type) { } void GameEngine::reset() { - streak = 0; - hit_points = starting_hp; + 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) { @@ -37,12 +46,12 @@ bool GameEngine::hit(string &type) { } void GameEngine::heal() { - hit_points = hit_points * 1.10; - if(hit_points > 100) hit_points = 100; + hit_points = hit_points * 1.10f; + if(hit_points > max_hp()) hit_points = max_hp(); } bool GameEngine::is_dead() { - return hit_points <= 0; + return free_death ? false : hit_points <= 0; } void GameEngine::start(GameEvent ev) { @@ -63,7 +72,9 @@ void GameEngine::in_round(GameEvent ev, string &hit_type) { switch(ev) { case GameEvent::HIT: hit(hit_type); - if(is_dead()) { + + // NOTE: don't use is_dead to avoid free_death + if(hit_points <= 0) { state(GameState::DEAD); } else { state(GameState::IN_ROUND); @@ -103,6 +114,22 @@ void GameEngine::success(GameEvent ev) { void GameEngine::failure(GameEvent ev) { assert(ev == GameEvent::BUILD_DONE && "failure state expected BUILD_DONE"); ++rounds; - streak = 0; + // 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; + } +} diff --git a/game_engine.hpp b/game_engine.hpp index e02a534..0b0990f 100644 --- a/game_engine.hpp +++ b/game_engine.hpp @@ -19,6 +19,10 @@ enum class GameEvent { BUILD_DONE, BUILD_FAILED, HIT }; +enum class GameBonus { + MORE_HP, FREE_DEATH +}; + class GameEngine : DeadSimpleFSM { std::map damage_types{ @@ -33,6 +37,8 @@ class GameEngine : DeadSimpleFSM { int hits_taken = 0; int rounds = 0; int streak = 0; + float hp_bonus = 1.0f; + bool free_death = false; GameEngine(int hp); @@ -82,4 +88,6 @@ class GameEngine : DeadSimpleFSM { void heal(); bool hit(string &type); void reset(); + void add_bonus(GameBonus bonus); + int max_hp(); }; diff --git a/tests/game_engine.cpp b/tests/game_engine.cpp index bd9b7ec..320cbf0 100644 --- a/tests/game_engine.cpp +++ b/tests/game_engine.cpp @@ -36,7 +36,44 @@ TEST_CASE("game engine death cycle", "[game_engine]") { } TEST_CASE("game can do success build", "[game_engine]") { + GameEngine game{10}; + // test fails on purpose right now - GameEngine game{100}; + for(int i = 0; i < 10; i++) { + game.event(GameEvent::BUILD_START); + game.event(GameEvent::BUILD_SUCCESS); + REQUIRE(game.hits_taken == 0); + REQUIRE(game.hit_points == game.starting_hp); + // confirm streaks, hit_taken, rounds are maintained + REQUIRE(game.streak == i); + REQUIRE(game.rounds == i); + REQUIRE(game.is_dead() == false); + game.event(GameEvent::BUILD_DONE); + } + + // if you hit a streak of 10 then you get one of two bonuses + // 1. 10% more hp + // 2. 1 free death + + game.add_bonus(GameBonus::MORE_HP); + REQUIRE(game.max_hp() > game.starting_hp); + REQUIRE(game.hit_points == game.starting_hp * game.hp_bonus); + REQUIRE(game.hit_points == game.max_hp()); + + game.add_bonus(GameBonus::FREE_DEATH); + REQUIRE(game.free_death == true); + + game.event(GameEvent::BUILD_START); + game.event(GameEvent::HIT, "error"); + game.event(GameEvent::HIT, "error"); + game.event(GameEvent::HIT, "error"); + REQUIRE(game.is_dead() == false); + REQUIRE(game.streak == 10); + game.event(GameEvent::BUILD_FAILED); + game.event(GameEvent::BUILD_DONE); + + REQUIRE(game.streak == 10); + REQUIRE(game.free_death == false); + REQUIRE(game.hit_points == int(game.max_hp() * 0.5f)); }