From 3ae82841f4bcc69dae9ccd8e910058b1708d5e1f Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Sat, 13 Jul 2024 14:22:06 -0400 Subject: [PATCH 1/3] removed room.* (unused) --- src/gold.h | 17 +---------------- src/level.h | 2 +- src/rng.cc | 19 ------------------- src/rng.h | 19 +++++++++++++++++-- src/room.cc | 1 - src/room.h | 6 ------ 6 files changed, 19 insertions(+), 45 deletions(-) delete mode 100644 src/room.cc delete mode 100644 src/room.h diff --git a/src/gold.h b/src/gold.h index 92bc7c8..6ada545 100644 --- a/src/gold.h +++ b/src/gold.h @@ -13,21 +13,6 @@ struct gold { typedef std::vector gold_list; -int rand_gold_pile(RNG *rng) { - const int denominator = 8; - const int normal = 5; - const int dragon = 6; - - int tmp = rng->rand_under(denominator); - - if (tmp < normal) - return GOLD_NORMAL; - else if (tmp < dragon) - return GOLD_DRAGON; - else - return GOLD_SMALL; - - return 0; -} +int rand_gold_pile(RNG *rng); #endif diff --git a/src/level.h b/src/level.h index 3174861..1ec91bf 100644 --- a/src/level.h +++ b/src/level.h @@ -5,10 +5,10 @@ #include #include #include "display.h" +#include "gold.h" #include "enemies.h" #include "potions.h" #include "constants.h" -#include "gold.h" #include "map.h" class level { diff --git a/src/rng.cc b/src/rng.cc index 6a65f35..8c612dd 100644 --- a/src/rng.cc +++ b/src/rng.cc @@ -47,22 +47,3 @@ int RNG::exclude_middle(const int lower_bound, const int upper_bound, int tmp = (curr_rand_num % (upper_bound - lower_bound - 1)); return tmp >= excluded ? tmp + 1 : tmp; } - -template T RNG::rand_exclude(std::vector &vec, T &target) { - std::size_t idx = 0; - - for (; idx < vec.size(); ++idx) - if (vec[idx] == target) - break; - - return vec[exclude_middle(0, vec.size(), idx)]; -} - -template T RNG::get_rand_in_vector(std::vector &vec) { - if (!vec.size()) - return T{}; - - curr_rand_num = rand(); - - return vec[curr_rand_num % vec.size()]; -} diff --git a/src/rng.h b/src/rng.h index aba6324..0abd2c2 100644 --- a/src/rng.h +++ b/src/rng.h @@ -33,9 +33,24 @@ public: int exclude_middle(const int lower_bound, const int upper_bound, const int excluded); - template T rand_exclude(std::vector &vec, T &target); + template T rand_exclude(std::vector &vec, T &target) { + std::size_t idx = 0; - template T get_rand_in_vector(std::vector &vec); + for (; idx < vec.size(); ++idx) + if (vec[idx] == target) + break; + + return vec[exclude_middle(0, vec.size(), idx)]; + } + + template T get_rand_in_vector(std::vector &vec) { + if (!vec.size()) + return T{}; + + curr_rand_num = rand(); + + return vec[curr_rand_num % vec.size()]; + } }; #endif diff --git a/src/room.cc b/src/room.cc deleted file mode 100644 index fe6026a..0000000 --- a/src/room.cc +++ /dev/null @@ -1 +0,0 @@ -#include "room.h" diff --git a/src/room.h b/src/room.h deleted file mode 100644 index f0a7b58..0000000 --- a/src/room.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ROOM_H__ -#define __ROOM_H__ - - - -#endif From ccf6dd058216e5db5e2994bd3adaeda81d59dcb6 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Sat, 13 Jul 2024 15:43:21 -0400 Subject: [PATCH 2/3] corrected colors --- src/characters.cc | 4 ++-- src/characters.h | 2 +- src/game.h | 2 -- src/map.h | 5 ----- src/potion.cc | 4 ++-- src/potion.h | 2 +- src/vampire.h | 3 +-- 7 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/characters.cc b/src/characters.cc index b3473b6..af80e33 100644 --- a/src/characters.cc +++ b/src/characters.cc @@ -13,9 +13,9 @@ void character::start_turn() { base_hit_rate = {1, 1}; } -void character::print(display *out, bool color, bool player) { +void character::print(display *out, bool player) { out->print_char(pos, player ? '@' : CHARACTER_REP[race], - COLOR_PAIR(COLOR_BLACK_ON_WHITE)); + player ? COLOR_PAIR(COLOR_BLUE) : COLOR_PAIR(COLOR_RED)); } enum race character::get_race() const { diff --git a/src/characters.h b/src/characters.h index 5393126..db75525 100644 --- a/src/characters.h +++ b/src/characters.h @@ -40,7 +40,7 @@ public: const fraction hitrate) = 0; // overload for different races - virtual void print(display *out, bool color = false, bool player = false); + virtual void print(display *out, bool player = false); result apply_effects(); void discard_level_effects(); diff --git a/src/game.h b/src/game.h index 27198ab..fd83ece 100644 --- a/src/game.h +++ b/src/game.h @@ -18,7 +18,6 @@ private: logger *log; RNG *rng; - // IMPORTANT: during player generation, std::unique_ptr player; public: game(const feature enabled_features, @@ -28,7 +27,6 @@ public: RNG *new_rng); game_status run(); private: - int getcmd() const; }; #endif diff --git a/src/map.h b/src/map.h index 1e348ab..675a490 100644 --- a/src/map.h +++ b/src/map.h @@ -96,11 +96,6 @@ private: room &room2); bool overlap_y(room &room1, room &room2); - // has anything between the two - bool between_x(room &room1, - room &room2); - bool between_y(room &room1, - room &room2); void jitter(RNG *rng, std::vector &rooms); diff --git a/src/potion.cc b/src/potion.cc index 38bf023..2026021 100644 --- a/src/potion.cc +++ b/src/potion.cc @@ -41,6 +41,6 @@ potion &potion::operator=(potion &&p) { return *this; } -void potion::print(display *out, bool color) { - out->print_char(pos, 'P'); +void potion::print(display *out) { + out->print_char(pos, 'P', COLOR_PAIR(COLOR_GREEN)); } diff --git a/src/potion.h b/src/potion.h index 9dcc92e..1ad618f 100644 --- a/src/potion.h +++ b/src/potion.h @@ -33,7 +33,7 @@ public: position get_pos() const; void set_pos(const position &npos); - virtual void print(display *out, bool color = false); + virtual void print(display *out); }; typedef std::vector potion_list; diff --git a/src/vampire.h b/src/vampire.h index 7a68922..acb1a01 100644 --- a/src/vampire.h +++ b/src/vampire.h @@ -2,9 +2,8 @@ #define __VAMPIRE_H__ #include "characters.h" -const int GAIN_HP = 5; - class vampire final: public character { + static const int GAIN_HP = 5; public: vampire(RNG *rng, const position &pos); virtual result attack(const direction dir, From 5f3565fa86b4046fe60299299ed82ebe1d670fbe Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Sat, 13 Jul 2024 16:13:20 -0400 Subject: [PATCH 3/3] work in progress, can be branched/merged --- src/dragon.cc | 34 +++++++++++ src/dragon.h | 17 ++++++ src/enemies.cc | 20 +++++++ src/enemies.h | 14 +++++ src/gold.cc | 18 ++++++ src/level.cc | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ src/potions.cc | 13 ++++ src/potions.h | 13 ++++ 8 files changed, 289 insertions(+) create mode 100644 src/dragon.cc create mode 100644 src/dragon.h create mode 100644 src/enemies.cc create mode 100644 src/enemies.h create mode 100644 src/gold.cc create mode 100644 src/level.cc create mode 100644 src/potions.cc create mode 100644 src/potions.h diff --git a/src/dragon.cc b/src/dragon.cc new file mode 100644 index 0000000..7c99396 --- /dev/null +++ b/src/dragon.cc @@ -0,0 +1,34 @@ +#include "dragon.h" + +dragon::dragon(RNG *rng, const position &pos): + character{rng, race::rdragon, pos} { + gold = 0; + hostile = true; +} + +result dragon::attack(const direction dir, character_list &chlist) { + position tmp{pos + MOVE[dir]}; + + for (auto &ch : chlist) + if (tmp == ch->get_position()) { + return ch->get_hit(race, ATK, base_hit_rate); + } + + return result::fine; +} + +result dragon::get_hit(const enum race &race, const int atk, + const fraction hitrate) { + if (rng->trial(hitrate)) // This is a hit! + HP = std::max(HP - calc_dmg(atk, DEF), 0); + + if (HP == 0) + return result::died; + + return result::hit; +} + +result dragon::move(const direction dir, + const position_list &available_positions) { + return result::fine; +} diff --git a/src/dragon.h b/src/dragon.h new file mode 100644 index 0000000..f6b34b9 --- /dev/null +++ b/src/dragon.h @@ -0,0 +1,17 @@ +#ifndef __DRAGON_H__ +#define __DRAGON_H__ + +#include "characters.h" + +class dragon final: public character { +public: + dragon(RNG *rng, const position &pos); + virtual result attack(const direction dir, + character_list &chlist) override; + virtual result get_hit(const enum race &race, const int atk, + const fraction hit_rate) override; + virtual result move(const direction dir, + const position_list &avilable_positions) override; +}; + +#endif diff --git a/src/enemies.cc b/src/enemies.cc new file mode 100644 index 0000000..1f3ac4f --- /dev/null +++ b/src/enemies.cc @@ -0,0 +1,20 @@ +#include "enemies.h" + +// TODO: implement after characters +void new_enemy(RNG *rng, std::unique_ptr &pch, const position &pos, + bool extras) { + if (extras) { + + } else { + } +} + +void new_dragon(RNG *rng, std::unique_ptr &pch, const position &pos, + const position &fallback) { + const position nil{0, 0}; + + if (pos != nil) + pch = std::make_unique(rng, pos); + else + pch = std::make_unique(rng, fallback); +} diff --git a/src/enemies.h b/src/enemies.h new file mode 100644 index 0000000..5c3ac92 --- /dev/null +++ b/src/enemies.h @@ -0,0 +1,14 @@ +#ifndef __ENEMIES_H__ +#define __ENEMIES_H__ + +#include +#include "characters.h" +#include "races.h" + +void new_enemy(RNG *rng, std::unique_ptr &pch, const position &pos, + bool extras); + +void new_dragon(RNG *rng, std::unique_ptr &pch, const position &pos, + const position &fallback); + +#endif diff --git a/src/gold.cc b/src/gold.cc new file mode 100644 index 0000000..bad64a2 --- /dev/null +++ b/src/gold.cc @@ -0,0 +1,18 @@ +#include "gold.h" + +int rand_gold_pile(RNG *rng) { + const int denominator = 8; + const int normal = 5; + const int dragon = 6; + + int tmp = rng->rand_under(denominator); + + if (tmp < normal) + return GOLD_NORMAL; + else if (tmp < dragon) + return GOLD_DRAGON; + else + return GOLD_SMALL; + + return 0; +} diff --git a/src/level.cc b/src/level.cc new file mode 100644 index 0000000..655fa28 --- /dev/null +++ b/src/level.cc @@ -0,0 +1,160 @@ +#include "level.h" + +level::level(character *player, RNG *rng, const feature enabled_features): + enabled_features{enabled_features}, map{player, rng, enabled_features}, + player{player} { + auto tiles = map.get_room_list(); + gen_potions(rng, tiles); + gen_gold(rng, tiles); + gen_enemies(rng, tiles); +} + +level::level(const std::string &map_data, character *player, RNG *rng, + const feature enabled_features): + enabled_features{enabled_features}, + map{player, map_data, rng, enabled_features}, player{player} { + auto tiles = map.get_room_list(); + gen_potions(rng, tiles); + gen_gold(rng, tiles); + gen_enemies(rng, tiles); +} + +gold_list level::dragon_hoard() { + gold_list result; + + for (auto g : glist) + if (g.amount == GOLD_DRAGON) + result.push_back({g.amount, g.pos}); + return result; +} + +void level::gen_enemies(RNG *rng, std::vector &tiles) { + auto dhoard = dragon_hoard(); + int cnt = enabled_features & FEATURE_EXTRA_STUFF ? + rng->rand_between(MIN_ENEMIE_CNT, MAX_ENEMIE_CNT + 1) : + MIN_ENEMIE_CNT + dhoard.size(); + + chlist.reserve(cnt); + pchlist.reserve(cnt); + + for (size_t i = 0; i < dhoard.size(); ++i) { + auto spots = get_available_around(dhoard[i].pos); + pchlist.push_back(nullptr); + new_dragon(rng, pchlist[i], rng->get_rand_in_vector(spots), + dhoard[i].pos); + chlist.push_back(pchlist[i].get()); + } + + + for (int i = dhoard.size(); i < cnt; ++i) { + pchlist.push_back(nullptr); + new_enemy(rng, pchlist[i], get_rand_pos(rng, tiles), + enabled_features & FEATURE_EXTRA_STUFF); + pchlist[i]->set_room_num(map.which_room(pchlist[i]->get_position())); + chlist.push_back(pchlist[i].get()); + } +} + +position level::get_rand_pos(RNG *rng, std::vector &tiles) { + int room; + position pos; + room = rng->rand_under(tiles.size()); + + pos = rng->get_rand_in_vector(tiles[room]); + remove_from_list(tiles[room], pos); + + if (!tiles[room].size()) + tiles.erase(tiles.begin() + room); + + return pos; +} + +void level::gen_gold(RNG *rng, std::vector &tiles) { + glist.reserve(GOLD_CNT); + + for (int i = 0; i < GOLD_CNT; ++i) + glist.push_back({rand_gold_pile(rng), get_rand_pos(rng, tiles)}); +} + +void level::gen_potions(RNG *rng, std::vector &tiles) { + int cnt; + int max_type; + + if (enabled_features & FEATURE_EXTRA_STUFF) { + cnt = rng->rand_between(MIN_POTION_CNT, MAX_POTION_CNT + 1); + max_type = POTION_TYPE_CNT; + } else { + cnt = MIN_POTION_CNT; + max_type = DEFAULT_POTION_TYPE_CNT; + } + + plist.reserve(cnt); + pplist.reserve(cnt); + + for (int i = 0; i < cnt; ++i) { + pplist.push_back(nullptr); + new_potion(pplist[i], + (potion_type)rng->rand_under(max_type), + get_rand_pos(rng, tiles)); + plist.push_back(pplist[i].get()); + } +} + +void level::print(display *out) const { + map.print(out); + player->print(out, true); + + for (auto ch : chlist) + ch->print(out); + + for (auto p : plist) + p->print(out); + + for (auto gold : glist) + out->print_char(gold.pos, 'G', COLOR_PAIR(COLOR_YELLOW)); +} + +bool level::is_available(const position &pos) const { + if (!map.is_available(pos)) + return false; + + for (auto ch : chlist) + if (pos == ch->get_position()) + return false; + + for (auto p : plist) + if (pos == p->get_pos()) + return false; + + return true; +} + +position_list level::get_available_around(const position &pos) const { + position_list result; + + for (int i = 0; i < DIRECTION_CNT; ++i) + if (is_available(pos + MOVE[i])) + result.push_back(pos + MOVE[i]); + + return result; +} + +position level::get_up_stairs() const { + return map.get_up_stairs(); +} + +position level::get_down_stairs() const { + return map.get_down_stairs(); +} + +character_list &level::get_chlist() { + return chlist; +} + +potion_list &level::get_plist() { + return plist; +} + +gold_list &level::get_glist() { + return glist; +} diff --git a/src/potions.cc b/src/potions.cc new file mode 100644 index 0000000..74a1c1a --- /dev/null +++ b/src/potions.cc @@ -0,0 +1,13 @@ +#include "potions.h" + +void new_potion(std::unique_ptr &pp, potion_type type, + const position &pos) { + switch (type) { + case potion_type::restore_health: + pp = std::make_unique(pos); + break; + + default: + break; + } +} diff --git a/src/potions.h b/src/potions.h new file mode 100644 index 0000000..e0a5ad6 --- /dev/null +++ b/src/potions.h @@ -0,0 +1,13 @@ +#ifndef __POTIONS_H__ +#define __POTIONS_H__ + +#include "potion.h" +#include "restore_health.h" + +#include +#include + +void new_potion(std::unique_ptr &pp, potion_type type, + const position &pos); + +#endif