From 5f3565fa86b4046fe60299299ed82ebe1d670fbe Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Sat, 13 Jul 2024 16:13:20 -0400 Subject: [PATCH] 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