From 1ebdd2d162a396a579fe561590b75e2d73b9012f Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Mon, 15 Jul 2024 17:56:45 -0400 Subject: [PATCH 01/12] fixed output not found --- src/output.cc | 17 ++++++ src/output.h | 35 ++++++++++++ src/output/console_output.cc | 100 +++++++++++++++++++++++++++++++++++ src/output/console_output.h | 21 ++++++++ src/output/curses_output.cc | 38 +++++++++++++ src/output/curses_output.h | 23 ++++++++ src/output/file_output.cc | 38 +++++++++++++ src/output/file_output.h | 20 +++++++ 8 files changed, 292 insertions(+) create mode 100644 src/output.cc create mode 100644 src/output.h create mode 100644 src/output/console_output.cc create mode 100644 src/output/console_output.h create mode 100644 src/output/curses_output.cc create mode 100644 src/output/curses_output.h create mode 100644 src/output/file_output.cc create mode 100644 src/output/file_output.h diff --git a/src/output.cc b/src/output.cc new file mode 100644 index 0000000..0723667 --- /dev/null +++ b/src/output.cc @@ -0,0 +1,17 @@ +#include "output.h" + +#include "constants.h" + +output::output(): + contents{DISPLAY_BUFFER_SIZE, 0} { + for (int i = 0; i < DISPLAY_BUFFER_SIZE; ++i) + contents.push_back(0); +} + +void output::clear() { + contents.clear(); + contents.reserve(DISPLAY_BUFFER_SIZE); + + for (int i = 0; i < DISPLAY_BUFFER_SIZE; ++i) + contents.push_back(0); +} diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000..217aa75 --- /dev/null +++ b/src/output.h @@ -0,0 +1,35 @@ +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include +#include +#include "position.h" +#include "cursor.h" + +class output { +protected: + // use an array of ints to keep track of what's on the screen + // This will have a bit of buffer for the last line + // just in case it overflows + std::vector contents; +public: + output(); + + virtual ~output() = default; + + // Only call this to refresh the entire output + virtual void render() = 0; + + // Clears the contents buffer + virtual void clear(); + + virtual void print_char(const position &pos, const char ch, + const int attrs = + A_NORMAL | COLOR_PAIR(COLOR_WHITE)) = 0; + virtual void print_str(const position &pos, const std::string &str, + const int attrs = + A_NORMAL | COLOR_PAIR(COLOR_WHITE)) = 0; + // default arguments are to be set in the base class's declaration +}; + +#endif diff --git a/src/output/console_output.cc b/src/output/console_output.cc new file mode 100644 index 0000000..beff4c2 --- /dev/null +++ b/src/output/console_output.cc @@ -0,0 +1,100 @@ +#include "console_output.h" + +#include +#include +#include + +#include "../constants.h" + +console_output::console_output(std::ostream &cout): out{cout} {} + +/* Attributes + black 30 40 + red 31 41 + green 32 42 + yellow 33 43 + blue 34 44 + magenta 35 45 + cyan 36 46 + white 37 47 + reset 0 (everything back to normal) + bold/bright 1 (often a brighter shade of the same colour) + underline 4 + inverse 7 (swap foreground and background colours) + bold/bright off 21 + underline off 24 + inverse off 27 + + Format: + \033[X;Ym + X Y are numbers from above +*/ + +std::string console_output::get_code(const int attrs) { + if (attrs < 255) + return "\033[0m"; + + std::string result = "\033[0m\033["; + + if (attrs & A_BOLD) + result += "1;"; + + if (attrs & A_UNDERLINE) + result += "4;"; + + if (attrs & A_STANDOUT) + result += "7;"; + + if ((attrs & COLOR_PAIR(COLOR_WHITE)) == COLOR_PAIR(COLOR_WHITE)) + result += "37;"; + else if ((attrs & COLOR_PAIR(COLOR_CYAN)) == COLOR_PAIR(COLOR_CYAN)) + result += "36;"; + else if ((attrs & COLOR_PAIR(COLOR_MAGENTA)) == COLOR_PAIR(COLOR_MAGENTA)) + result += "35;"; + else if ((attrs & COLOR_PAIR(COLOR_BLUE)) == COLOR_PAIR(COLOR_BLUE)) + result += "34;"; + else if ((attrs & COLOR_PAIR(COLOR_YELLOW)) == COLOR_PAIR(COLOR_YELLOW)) + result += "33;"; + else if ((attrs & COLOR_PAIR(COLOR_RED)) == COLOR_PAIR(COLOR_RED)) + result += "31;"; + else if ((attrs & COLOR_PAIR(COLOR_GREEN)) == COLOR_PAIR(COLOR_GREEN)) + result += "32;"; + else if ((attrs & COLOR_PAIR(COLOR_BLACK_ON_WHITE)) == COLOR_BLACK_ON_WHITE) + result += "30;47;"; + + result[result.length() - 1] = 'm'; + return result; +} + +void console_output::render() { + out << "\x1B[2J\x1B[H"; + + for (std::size_t idx = 0; idx < contents.size(); ++idx) { + if (idx % DISPLAY_WIDTH == 0 && idx) + out << std::endl; + + out << get_code(contents[idx]) + << (char)(contents[idx] ? contents[idx] : ' '); + } + + out << std::endl; +} + +void console_output::print_char(const position &pos, const char ch, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + contents[pos.y * DISPLAY_WIDTH + pos.x] = attrs | ch; +} + +void console_output::print_str(const position &pos, const std::string &str, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + int head = pos.y * DISPLAY_WIDTH + pos.x; + + for (std::size_t i = 0; i < str.length(); ++i) + contents[i + head] = attrs | str[i]; +} diff --git a/src/output/console_output.h b/src/output/console_output.h new file mode 100644 index 0000000..c8dbfd1 --- /dev/null +++ b/src/output/console_output.h @@ -0,0 +1,21 @@ +#ifndef __CONSOLE_OUTPUT_H__ +#define __CONSOLE_OUTPUT_H__ + +#include +#include "../output.h" + +class console_output final : public output { +private: + std::ostream &out; + std::string get_code(const int attrs); +public: + console_output(std::ostream &cout); + + void render() override; + void print_char(const position &pos, + const char ch, const int attrs) override; + void print_str(const position &pos, + const std::string &str, const int attrs) override; +}; + +#endif diff --git a/src/output/curses_output.cc b/src/output/curses_output.cc new file mode 100644 index 0000000..bee3adf --- /dev/null +++ b/src/output/curses_output.cc @@ -0,0 +1,38 @@ +#include "curses_output.h" + +#include "../constants.h" + +curses_output::curses_output(cursor *new_curse): + curse{new_curse} {} + +void curses_output::render() { + curse->show(); +} + +void curses_output::clear() { + curse->clear(); +} + +void curses_output::print_char(const position &pos, const char ch, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + curse->print_char(pos, ch, attrs); +} + +void curses_output::print_str(const position &pos, const std::string &str, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + position tmp = pos; + + for (std::size_t i = 0; i < str.length(); ++i) { + curse->print_char(tmp, str[i], attrs); + tmp += {1, 0}; + + if (tmp.x >= DISPLAY_WIDTH) + tmp = {0, tmp.y + 1}; + } +} diff --git a/src/output/curses_output.h b/src/output/curses_output.h new file mode 100644 index 0000000..7d841b9 --- /dev/null +++ b/src/output/curses_output.h @@ -0,0 +1,23 @@ +#ifndef __CURSES_OUTPUT_H__ +#define __CURSES_OUTPUT_H__ + +#include +#include +#include "../cursor.h" +#include "../output.h" + +class curses_output final : public output { +private: + cursor *curse; +public: + curses_output(cursor *new_curse); + + void render() override; + void clear() override; + void print_char(const position &pos, + const char ch, const int attrs) override; + void print_str(const position &pos, + const std::string &str, const int attrs) override; +}; + +#endif diff --git a/src/output/file_output.cc b/src/output/file_output.cc new file mode 100644 index 0000000..5408220 --- /dev/null +++ b/src/output/file_output.cc @@ -0,0 +1,38 @@ +#include "file_output.h" + +#include + +#include "../constants.h" + +file_output::file_output(std::ofstream &&ofs): + out{std::move(ofs)} {} + +void file_output::render() { + for (std::size_t idx = 0; idx < contents.size(); ++idx) { + if (idx % DISPLAY_WIDTH == 0 && idx) + out << std::endl; + + out << (char)(contents[idx] ? contents[idx] : ' '); + } + + out << std::endl; +} + +void file_output::print_char(const position &pos, const char ch, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + contents[pos.y * DISPLAY_WIDTH + pos.x] = ch; +} + +void file_output::print_str(const position &pos, const std::string &str, + const int attrs) { + if (pos.x >= DISPLAY_WIDTH || pos.y >= DISPLAY_HEIGHT) + return; + + int head = pos.y * DISPLAY_WIDTH + pos.x; + + for (std::size_t i = 0; i < str.length(); ++i) + contents[i + head] = str[i]; +} diff --git a/src/output/file_output.h b/src/output/file_output.h new file mode 100644 index 0000000..5e0f80d --- /dev/null +++ b/src/output/file_output.h @@ -0,0 +1,20 @@ +#ifndef __FILE_OUTPUT_H__ +#define __FILE_OUTPUT_H__ + +#include +#include "../output.h" + +class file_output final : public output { +private: + std::ofstream out; +public: + file_output(std::ofstream &&ofs); + + void render() override; + void print_char(const position &pos, + const char ch, const int attrs) override; + void print_str(const position &pos, + const std::string &str, const int attrs) override; +}; + +#endif From 120aa9cacd8536ae8465bd775cc8e0a95249bc16 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Mon, 15 Jul 2024 18:59:28 -0400 Subject: [PATCH 02/12] fixed issue when player revisits a level from above his position doesn't change --- src/game.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game.cc b/src/game.cc index 8f41182..c21fe7a 100644 --- a/src/game.cc +++ b/src/game.cc @@ -112,6 +112,8 @@ game_result game::run() { if (curr_level == levels.size()) new_level(); + player->set_pos(levels[curr_level]->get_up_stairs()); + break; } From 991ab34ca2ee05ac3be87a14f0488aba81bf18ec Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Mon, 15 Jul 2024 19:33:32 -0400 Subject: [PATCH 03/12] added T-800 as playable character --- src/characters.cc | 4 ++-- src/characters.h | 1 - src/constants.h | 21 ++++++++++++++------- src/enemy.cc | 4 +--- src/pc.cc | 5 +++++ src/player.cc | 4 ++++ src/player/t_800.cc | 15 +++++++++++++++ src/player/t_800.h | 15 +++++++++++++++ 8 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 src/player/t_800.cc create mode 100644 src/player/t_800.h diff --git a/src/characters.cc b/src/characters.cc index 6203f55..aea13d0 100644 --- a/src/characters.cc +++ b/src/characters.cc @@ -9,12 +9,12 @@ character::character(RNG *rng, const feature enabled_features, rng{rng}, enabled_features{enabled_features}, race{nrace}, HP{STARTING_HP[race]}, pos{pos}, ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]}, - base_hit_rate{1, 1}, base_hit_rate_reset{1, 1} {} + base_hit_rate{STARTING_HR[race]} {} void character::start_turn() { ATK = STARTING_ATK[race]; DEF = STARTING_DEF[race]; - base_hit_rate = base_hit_rate_reset; + base_hit_rate = STARTING_HR[race]; } enum race character::get_race() const { diff --git a/src/characters.h b/src/characters.h index 5b9543f..980c985 100644 --- a/src/characters.h +++ b/src/characters.h @@ -56,7 +56,6 @@ protected: int ATK; int DEF; fraction base_hit_rate; - fraction base_hit_rate_reset; potion_list effects; diff --git a/src/constants.h b/src/constants.h index fbaa5cc..5768ca7 100644 --- a/src/constants.h +++ b/src/constants.h @@ -4,6 +4,7 @@ #include #include #include "position.h" +#include "fraction.h" static const int INF = 0x3F3F3F3F; @@ -41,27 +42,33 @@ enum game_command : int {game_command_terminate = 0, }; // Character generation related -static const int RACE_CNT = 12; +static const int RACE_CNT = 13; enum race : int {rshade = 0, rdrow, rvampire, rtroll, rgoblin, rhuman, rdwarf, relf, - rorc, rmerchant, rdragon, rhalfling + rorc, rmerchant, rdragon, rhalfling, + rt_800 }; static const char CHAR_REP[RACE_CNT] = { - 's', 'd', 'v', 't', 'g', 'H', 'W', 'E', 'O', 'M', 'D', 'L' + 's', 'd', 'v', 't', 'g', 'H', 'W', 'E', 'O', 'M', 'D', 'L', 't' }; static const int MAX_HP[RACE_CNT] = { - 125, 150, INF, 120, 110, 140, 100, 140, 180, 30, 150, 100 + 125, 150, INF, 120, 110, 140, 100, 140, 180, 30, 150, 100, 500 }; static const int STARTING_HP[RACE_CNT] = { - 125, 150, 50, 120, 110, 140, 100, 140, 180, 30, 150, 100 + 125, 150, 50, 120, 110, 140, 100, 140, 180, 30, 150, 100, 500 }; static const int STARTING_ATK[RACE_CNT] = { - 25, 25, 25, 25, 15, 20, 20, 30, 30, 70, 20, 15 + 25, 25, 25, 25, 15, 20, 20, 30, 30, 70, 20, 15, 40 }; static const int STARTING_DEF[RACE_CNT] = { - 25, 15, 25, 15, 20, 20, 30, 10, 25, 5, 20, 20 + 25, 15, 25, 15, 20, 20, 30, 10, 25, 5, 20, 20, 50 +}; +static const fraction STARTING_HR[RACE_CNT] = { + {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {1, 1} }; diff --git a/src/enemy.cc b/src/enemy.cc index 40810c8..45b64ae 100644 --- a/src/enemy.cc +++ b/src/enemy.cc @@ -8,9 +8,7 @@ enemy_base::enemy_base(RNG *rng, const feature enabled_features, const enum race &nrace, const position &pos, const int gen_room_num, std::string abbrev): character{rng, enabled_features, nrace, pos}, - room_num{gen_room_num}, abbrev{abbrev} { - base_hit_rate_reset = {1, 2}; -} + room_num{gen_room_num}, abbrev{abbrev} {} int enemy_base::get_room_num() const { return room_num; diff --git a/src/pc.cc b/src/pc.cc index a5df804..b87b1cd 100644 --- a/src/pc.cc +++ b/src/pc.cc @@ -6,6 +6,7 @@ #include "player/shade.h" #include "player/troll.h" #include "player/vampire.h" +#include "player/t_800.h" void init_player(RNG *rng, std::unique_ptr &pc, const feature enabled_features, const enum race &r) { @@ -34,6 +35,10 @@ void init_player(RNG *rng, std::unique_ptr &pc, pc = make_unique(rng, enabled_features); break; + case rt_800: + pc = make_unique(rng, enabled_features); + break; + default: break; } diff --git a/src/player.cc b/src/player.cc index 2640d7b..d897e6e 100644 --- a/src/player.cc +++ b/src/player.cc @@ -39,6 +39,10 @@ long_result player_base::apply(potion *p) { apply_effect(p); + if (race == rt_800) + return {result::applied, + "PC gets rusty joints (-5 HP). "}; + return {result::applied, (std::string)"PC applied potion of " + p->get_name() + ". "}; } diff --git a/src/player/t_800.cc b/src/player/t_800.cc new file mode 100644 index 0000000..b9bddb2 --- /dev/null +++ b/src/player/t_800.cc @@ -0,0 +1,15 @@ +#include "t_800.h" + +#include "../constants.h" + +t_800::t_800(RNG *rng, const feature enabled_features): + player_base{rng, enabled_features, race::rt_800} {} + +const char *t_800::get_race_name() const { + return "T-800"; +} + +void t_800::apply_effect(potion *p) { + HP -= RUSTY; + return; +} diff --git a/src/player/t_800.h b/src/player/t_800.h new file mode 100644 index 0000000..987bbb6 --- /dev/null +++ b/src/player/t_800.h @@ -0,0 +1,15 @@ +#ifndef __T_800_H__ +#define __T_800_H__ + +#include "../player.h" +class potion; + +class t_800 final: public player_base { + static const int RUSTY = 5; +public: + t_800(RNG *rng, const feature enabled_features); + const char *get_race_name() const override; + void apply_effect(potion *p) override; +}; + +#endif From 70e80c1474c7198253745196b7e2df4bdd8f7bb0 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Mon, 15 Jul 2024 19:47:07 -0400 Subject: [PATCH 04/12] fixed: enemies may spawn on top of dragons added prompting to picking up gold --- src/enemy.cc | 8 +++++--- src/enemy.h | 2 +- src/game.cc | 8 ++++++-- src/level.cc | 9 ++++++++- src/player.cc | 25 +++++++++++++++++++++---- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/enemy.cc b/src/enemy.cc index 45b64ae..db4aa83 100644 --- a/src/enemy.cc +++ b/src/enemy.cc @@ -86,7 +86,7 @@ long_result enemy_base::get_hit(character *ch, const int tATK, return {miss, "PC tried to hit " + abbrev + " but missed. "}; } -void enemy_base::dies(level *lvl, character *pc) { +int enemy_base::dies(level *lvl) { auto &elist = lvl->get_elist(); for (size_t i = 0; i < elist.size(); ++i) @@ -96,17 +96,19 @@ void enemy_base::dies(level *lvl, character *pc) { } if (race == race::rdragon) { - return; + return 0; } else if (race == race::rmerchant) { lvl->add_gold({GOLD_MERCHANT, pos}); + return 0; } else if (race == race::rhuman) { lvl->add_gold({GOLD_NORMAL, pos}); auto plist = lvl->get_available_around_all(pos); lvl->add_gold({GOLD_NORMAL, rng->get_rand_in_vector(plist)}); + return 0; } - ((player_base *)pc)->add_gold(rand_gold_drop(rng)); + return rand_gold_drop(rng); } enemy_base *get_enemy_at(const position &pos, const enemy_list &elist) { diff --git a/src/enemy.h b/src/enemy.h index e43fd32..aed9034 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -26,7 +26,7 @@ public: virtual std::string get_abbrev() const override; - virtual void dies(level *lvl, character *pc); + virtual int dies(level *lvl); }; typedef std::vector enemy_list; diff --git a/src/game.cc b/src/game.cc index c21fe7a..3e85c79 100644 --- a/src/game.cc +++ b/src/game.cc @@ -73,8 +73,12 @@ character *game::move_enemies() { if (player->is_dead()) return ch; - if (ch->is_dead()) - ch->dies(levels[curr_level].get(), player.get()); + if (ch->is_dead()) { + int g = ch->dies(levels[curr_level].get()); + + if (g) + levels[curr_level]->add_gold({g, ch->get_pos()}); + } msg += res.msg; } diff --git a/src/level.cc b/src/level.cc index 6f66f5a..a50b357 100644 --- a/src/level.cc +++ b/src/level.cc @@ -67,9 +67,16 @@ void level::gen_enemies(RNG *rng, std::vector &tiles) { } pelist.push_back(nullptr); - new_dragon(rng, pelist[i], rng->get_rand_in_vector(spots), + auto pos = rng->get_rand_in_vector(spots); + new_dragon(rng, pelist[i], pos, dhoard[i].pos, enabled_features, map.which_room(dhoard[i].pos)); + int room = map.which_room(pos); + remove_from_list(tiles[room], pos); + + if (!tiles[room].size()) + tiles.erase(tiles.begin() + room); + elist.push_back(pelist[i].get()); } diff --git a/src/player.cc b/src/player.cc index d897e6e..9a40167 100644 --- a/src/player.cc +++ b/src/player.cc @@ -66,8 +66,14 @@ long_result player_base::move(level *lvl, } else if ((tmp = get_enemy_at(p, lvl->get_elist())) != nullptr) { auto res = attack((character *)tmp); - if (tmp->is_dead()) - tmp->dies(lvl, this); + if (tmp->is_dead()) { + int g = tmp->dies(lvl); + + if (g) + res.msg += "PC gains " + + std::to_string(g) + + " pieces of gold. "; + } return res; } @@ -121,6 +127,11 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { gold g = get_gold_at(pos, lvl->get_glist()); gold_cnt += g.amount; + + if (g.amount) + res.msg += "PC picked up " + std::to_string(g.amount) + + " pieces of gold. "; + return res; } else if (cmd >= apply_north && cmd <= apply_southwest) { auto res = apply(get_potion_at(pos + MOVE[cmd - apply_north], @@ -142,8 +153,14 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { auto res = attack((character *)tmp); - if (tmp != nullptr && tmp->is_dead()) - tmp->dies(lvl, this); + if (tmp != nullptr && tmp->is_dead()) { + int g = tmp->dies(lvl); + + if (g) + res.msg += "PC gains " + + std::to_string(g) + + " pieces of gold. "; + } return res; } else if (cmd == up_stairs) { From 7b86c20a0ce1f325aa320f0c7fa891bb905ecbe1 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 17:43:30 -0400 Subject: [PATCH 05/12] fixed bug where player gets stuck when going downstairs --- src/game.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game.cc b/src/game.cc index 3e85c79..ee3743e 100644 --- a/src/game.cc +++ b/src/game.cc @@ -116,7 +116,8 @@ game_result game::run() { if (curr_level == levels.size()) new_level(); - player->set_pos(levels[curr_level]->get_up_stairs()); + if (enabled_features & FEATURE_REVISIT) + player->set_pos(levels[curr_level]->get_up_stairs()); break; } From 7d9807c0267ccc3c797c426e4b1ee20566ec5e76 Mon Sep 17 00:00:00 2001 From: a25liang Date: Tue, 16 Jul 2024 19:23:47 -0400 Subject: [PATCH 06/12] - fix elf: no two attacks to drow --- src/enemies/elf.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/enemies/elf.cc b/src/enemies/elf.cc index ed37011..79aa218 100644 --- a/src/enemies/elf.cc +++ b/src/enemies/elf.cc @@ -20,6 +20,8 @@ long_result elf::attack(character *ch) { if (res1.res == result::died) return res1; + if (ch->get_race() == rdrow) return res1; + auto res2 = ch->get_hit(this, ATK, base_hit_rate); if (res1.res == miss && res2.res == miss) From ce0a31197cee810f1c300ff89ede95184e49b0c8 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 19:25:58 -0400 Subject: [PATCH 07/12] trivial: formatted code --- src/enemies/elf.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/enemies/elf.cc b/src/enemies/elf.cc index 79aa218..dc292e0 100644 --- a/src/enemies/elf.cc +++ b/src/enemies/elf.cc @@ -20,7 +20,8 @@ long_result elf::attack(character *ch) { if (res1.res == result::died) return res1; - if (ch->get_race() == rdrow) return res1; + if (ch->get_race() == rdrow) + return res1; auto res2 = ch->get_hit(this, ATK, base_hit_rate); From 50e10509b3282846b0af5fbc8607292db7ca5038 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 19:57:29 -0400 Subject: [PATCH 08/12] fixed 1. enemies spawning on the same tile as the player 2. start_turn in the wrong places --- src/game.cc | 5 +++++ src/level.cc | 6 ++++++ src/player.cc | 18 ++---------------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/game.cc b/src/game.cc index ee3743e..d12d17e 100644 --- a/src/game.cc +++ b/src/game.cc @@ -109,6 +109,8 @@ game_result game::run() { std::to_string(curr_turn + 1) + " turns!"}; + player->start_turn(); + player->discard_level_effects(); ++curr_level; @@ -130,6 +132,8 @@ game_result game::run() { std::to_string(curr_turn + 1) + " turns! Coward!"}; + player->start_turn(); + player->discard_level_effects(); --curr_level; @@ -153,6 +157,7 @@ game_result game::run() { return {in_game, ""}; default: + player->start_turn(); break; } diff --git a/src/level.cc b/src/level.cc index a50b357..ce7750b 100644 --- a/src/level.cc +++ b/src/level.cc @@ -7,6 +7,9 @@ level::level(character *player, RNG *rng, const feature enabled_features): player{player} { auto tiles = map.get_room_list(); + for (size_t i = 0; i < tiles.size(); ++i) + remove_from_list(tiles[i], player->get_pos()); + for (size_t i = 0; i < tiles.size(); ++i) remove_from_list(tiles[i], map.get_down_stairs()); @@ -26,6 +29,9 @@ level::level(const std::string &map_data, character *player, RNG *rng, map{player, map_data, rng, enabled_features}, player{player} { auto tiles = map.get_room_list(); + for (size_t i = 0; i < tiles.size(); ++i) + remove_from_list(tiles[i], player->get_pos()); + for (size_t i = 0; i < tiles.size(); ++i) remove_from_list(tiles[i], map.get_down_stairs()); diff --git a/src/player.cc b/src/player.cc index 9a40167..677b675 100644 --- a/src/player.cc +++ b/src/player.cc @@ -122,9 +122,6 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { } else if (cmd >= move_north && cmd <= move_southwest) { auto res = move(lvl, pos + MOVE[cmd - move_north]); - if (res.res == result::moved) - start_turn(); - gold g = get_gold_at(pos, lvl->get_glist()); gold_cnt += g.amount; @@ -136,10 +133,6 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { } else if (cmd >= apply_north && cmd <= apply_southwest) { auto res = apply(get_potion_at(pos + MOVE[cmd - apply_north], lvl->get_plist())); - - if (res.res == result::applied) - start_turn(); - return res; } else if (cmd == apply_panic) { return {result::fine, @@ -148,9 +141,6 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { enemy_base *tmp = get_enemy_at(pos + MOVE[cmd - attack_north], lvl->get_elist()); - if (tmp != nullptr) - start_turn(); - auto res = attack((character *)tmp); if (tmp != nullptr && tmp->is_dead()) { @@ -165,18 +155,14 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { return res; } else if (cmd == up_stairs) { if (lvl->get_up_stairs() == pos && - enabled_features & FEATURE_REVISIT) { - start_turn(); + enabled_features & FEATURE_REVISIT) return {go_up, "PC went up the stairs. "}; - } return {result::fine, "PC tried to fly through the ceiling. "}; } else if (cmd == down_stairs) { - if (lvl->get_down_stairs() == pos) { - start_turn(); + if (lvl->get_down_stairs() == pos) return {go_down, "PC went down the stairs. "}; - } return {result::fine, "PC tried to dig through the floor. "}; From 6844a953058226b978068d8f2ce58d530bd13d8b Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 20:01:45 -0400 Subject: [PATCH 09/12] fixed turn counter --- src/game.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game.cc b/src/game.cc index d12d17e..ef69219 100644 --- a/src/game.cc +++ b/src/game.cc @@ -153,7 +153,6 @@ game_result game::run() { case unknown: case fine: case applied_nothing: - ++curr_turn; return {in_game, ""}; default: @@ -161,6 +160,8 @@ game_result game::run() { break; } + ++curr_turn; + player->calc_effects(); if (player->is_dead()) @@ -176,7 +177,6 @@ game_result game::run() { killer->get_race_name()}; } - ++curr_turn; return {in_game, ""}; } From ea3164ae07bdddf83fa4d5e5c285eb70a00596b4 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 22:09:28 -0400 Subject: [PATCH 10/12] added when -d isn't enabled, human gold drop won't drop out of rooms --- src/level.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/level.cc b/src/level.cc index ce7750b..1a4ff56 100644 --- a/src/level.cc +++ b/src/level.cc @@ -185,6 +185,10 @@ bool level::is_available_all(const position &pos) const { if (!map.is_available(pos)) return false; + if (!(enabled_features & FEATURE_DOORS) && + map.which_room(pos) == -1) + return false; + if (player->get_pos() == pos) return false; From 3b164bbe9ff987af704f8083b2737cf4c79ca7a3 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 23:00:10 -0400 Subject: [PATCH 11/12] fixed: dragon generation breaking the game seed validation wrong --- src/arguments.cc | 3 +-- src/enemies.cc | 43 +++++++++++++++++++++++++------------------ src/enemies.h | 13 +++++++------ src/game.cc | 2 +- src/level.cc | 20 +++++++++----------- src/pc.cc | 20 ++++++++++---------- src/pc.h | 4 ++-- src/potions.cc | 17 +++++++++-------- src/potions.h | 3 +-- 9 files changed, 65 insertions(+), 60 deletions(-) diff --git a/src/arguments.cc b/src/arguments.cc index 8d52f2c..e5d98b3 100644 --- a/src/arguments.cc +++ b/src/arguments.cc @@ -117,9 +117,8 @@ feature proc_args(int argc, char **argv, if (result & FEATURE_SEED) { std::istringstream iss {seed}; unsigned int tmp; - iss >> tmp; - if (!iss.good()) + if (!(iss >> tmp)) return FEATURE_PANIC_SEED; rng = std::make_unique(tmp); diff --git a/src/enemies.cc b/src/enemies.cc index 1665f1a..0ed2561 100644 --- a/src/enemies.cc +++ b/src/enemies.cc @@ -9,17 +9,18 @@ #include "enemies/merchant.h" #include "enemies/orc.h" -void new_dragon(RNG *rng, std::unique_ptr &p, - const position &pos, const position &fallback, - const feature enabled_features, int which_room) { +std::unique_ptr new_dragon(RNG *rng, const position &pos, + const position &fallback, + const feature enabled_features, + int which_room) { const position nil{0, 0}; if (pos != nil) - p = std::make_unique(rng, enabled_features, - pos, which_room); + return std::make_unique(rng, enabled_features, + pos, which_room); else - p = std::make_unique(rng, enabled_features, - fallback, which_room); + return std::make_unique(rng, enabled_features, + fallback, which_room); } const int EXCNT = 6; @@ -44,9 +45,9 @@ enum race get_normal_race(RNG *rng) { return CHOICES[rng->rand_under(CNT)]; } -void new_enemy(RNG *rng, std::unique_ptr &p, - const position &pos, const feature enabled_features, - int which_room) { +std::unique_ptr new_enemy(RNG *rng, const position &pos, + const feature enabled_features, + int which_room) { using std::make_unique; enum race r; @@ -56,34 +57,40 @@ void new_enemy(RNG *rng, std::unique_ptr &p, else r = get_normal_race(rng); - p = nullptr; - switch (r) { case rdwarf: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; case rhuman: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; case relf: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; case rorc: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; case rmerchant: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; case rhalfling: - p = make_unique(rng, enabled_features, pos, which_room); + return make_unique(rng, enabled_features, + pos, which_room); break; default: break; } + + return nullptr; } diff --git a/src/enemies.h b/src/enemies.h index ea44300..14183c8 100644 --- a/src/enemies.h +++ b/src/enemies.h @@ -4,12 +4,13 @@ #include #include "enemy.h" -void new_dragon(RNG *rng, std::unique_ptr &p, - const position &pos, const position &fallback, - const feature enabled_features, int which_room); +std::unique_ptr new_dragon(RNG *rng, const position &pos, + const position &fallback, + const feature enabled_features, + int which_room); -void new_enemy(RNG *rng, std::unique_ptr &p, - const position &pos, const feature enabled_features, - int which_room); +std::unique_ptr new_enemy(RNG *rng, const position &pos, + const feature enabled_features, + int which_room); #endif diff --git a/src/game.cc b/src/game.cc index ef69219..bd2297c 100644 --- a/src/game.cc +++ b/src/game.cc @@ -15,7 +15,7 @@ game::game(const enum race starting_race, the_world = false; // TODO: add the other races - init_player(rng, player, enabled_features, starting_race); + 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); diff --git a/src/level.cc b/src/level.cc index 1a4ff56..0995abd 100644 --- a/src/level.cc +++ b/src/level.cc @@ -72,11 +72,11 @@ void level::gen_enemies(RNG *rng, std::vector &tiles) { spots.push_back(dhoard[i].pos + MOVE[i]); } - pelist.push_back(nullptr); - auto pos = rng->get_rand_in_vector(spots); - new_dragon(rng, pelist[i], pos, - dhoard[i].pos, enabled_features, - map.which_room(dhoard[i].pos)); + auto pos = spots.size() ? rng->get_rand_in_vector(spots) : + dhoard[i].pos; + pelist.push_back(new_dragon(rng, pos, dhoard[i].pos, + enabled_features, + map.which_room(dhoard[i].pos))); int room = map.which_room(pos); remove_from_list(tiles[room], pos); @@ -88,9 +88,9 @@ void level::gen_enemies(RNG *rng, std::vector &tiles) { for (int i = dhoard.size(); i < cnt; ++i) { - pelist.push_back(nullptr); auto p = get_rand_pos(rng, tiles); - new_enemy(rng, pelist[i], p, enabled_features, map.which_room(p)); + pelist.push_back(new_enemy(rng, p, enabled_features, + map.which_room(p))); elist.push_back(pelist[i].get()); } } @@ -136,10 +136,8 @@ void level::gen_potions(RNG *rng, std::vector &tiles) { 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)); + pplist.push_back(new_potion((potion_type)rng->rand_under(max_type), + get_rand_pos(rng, tiles))); plist.push_back(pplist[i].get()); } } diff --git a/src/pc.cc b/src/pc.cc index b87b1cd..572e23b 100644 --- a/src/pc.cc +++ b/src/pc.cc @@ -8,38 +8,38 @@ #include "player/vampire.h" #include "player/t_800.h" -void init_player(RNG *rng, std::unique_ptr &pc, - const feature enabled_features, const enum race &r) { +std::unique_ptr init_player(RNG *rng, + const feature enabled_features, const enum race &r) { using std::make_unique; - pc = nullptr; - switch (r) { case rgoblin: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; case rdrow: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; case rshade: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; case rtroll: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; case rvampire: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; case rt_800: - pc = make_unique(rng, enabled_features); + return make_unique(rng, enabled_features); break; default: break; } + + return nullptr; } diff --git a/src/pc.h b/src/pc.h index 7c67f2c..fbede40 100644 --- a/src/pc.h +++ b/src/pc.h @@ -4,7 +4,7 @@ #include #include "player.h" -void init_player(RNG *rng, std::unique_ptr &pc, - const feature enabled_features, const enum race &r); +std::unique_ptr init_player(RNG *rng, + const feature enabled_features, const enum race &r); #endif diff --git a/src/potions.cc b/src/potions.cc index 4034745..ae8725e 100644 --- a/src/potions.cc +++ b/src/potions.cc @@ -8,34 +8,35 @@ #include "potions/wound_atk.h" #include "potions/wound_def.h" -void new_potion(std::unique_ptr &pp, potion_type type, - const position &pos) { +std::unique_ptr new_potion(potion_type type, const position &pos) { switch (type) { case restore_health: - pp = std::make_unique(pos); + return std::make_unique(pos); break; case boost_atk: - pp = std::make_unique(pos); + return std::make_unique(pos); break; case boost_def: - pp = std::make_unique(pos); + return std::make_unique(pos); break; case poison_health: - pp = std::make_unique(pos); + return std::make_unique(pos); break; case wound_atk: - pp = std::make_unique(pos); + return std::make_unique(pos); break; case wound_def: - pp = std::make_unique(pos); + return std::make_unique(pos); break; default: break; } + + return nullptr; } diff --git a/src/potions.h b/src/potions.h index ae83786..e4c8651 100644 --- a/src/potions.h +++ b/src/potions.h @@ -6,7 +6,6 @@ #include #include -void new_potion(std::unique_ptr &pp, potion_type type, - const position &pos); +std::unique_ptr new_potion(potion_type type, const position &pos); #endif From 3232d91ac1ca23cf9632d626f70bb593c6b269b8 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Tue, 16 Jul 2024 23:36:31 -0400 Subject: [PATCH 12/12] better managed ownership (two new functions in level.h) --- src/cc3k.cc | 6 +++++- src/characters.cc | 26 +++++++++++++------------- src/characters.h | 6 +++--- src/cursor.cc | 1 + src/enemy.cc | 8 -------- src/game.cc | 1 + src/level.cc | 25 +++++++++++++++++++++++-- src/level.h | 7 +++++-- src/player.cc | 17 +++++++++++------ src/player.h | 4 ++-- src/player/t_800.cc | 2 +- src/player/t_800.h | 4 ++-- src/potion.cc | 13 ++++--------- src/potion.h | 4 +++- 14 files changed, 74 insertions(+), 50 deletions(-) diff --git a/src/cc3k.cc b/src/cc3k.cc index 519606a..495dd73 100644 --- a/src/cc3k.cc +++ b/src/cc3k.cc @@ -18,8 +18,10 @@ game_status CC3K::run() { case main_menu: { auto tmp = curr_menu->run(in); - if (tmp == -2) + if (tmp == -2) { + gresult.status = terminated; return terminated; + } if (tmp != -1) { curr_menu = nullptr; @@ -55,6 +57,8 @@ game_status CC3K::run() { curr_game->print(); out->render(); return in_game; + } else if (gresult.status == terminated) { + return terminated; } out->clear(); diff --git a/src/characters.cc b/src/characters.cc index aea13d0..cb1be92 100644 --- a/src/characters.cc +++ b/src/characters.cc @@ -29,12 +29,12 @@ void character::set_pos(const position &npos) { pos = npos; } -void character::apply_effect(potion *effect) { - insert_effect(effect); +void character::apply_effect(std::unique_ptr effect) { + insert_effect(std::move(effect)); } -void character::insert_effect(potion *effect) { - effects.push_back(effect); +void character::insert_effect(std::unique_ptr effect) { + effects.push_back(std::move(effect)); for (int i = effects.size() - 1; i > 0 && effect->get_priority() < effects[i - 1]->get_priority(); --i) @@ -42,17 +42,17 @@ void character::insert_effect(potion *effect) { } result character::calc_effects() { - potion_list tmp; + potion_own_list tmp; tmp.reserve(effects.size()); - for (auto p : effects) { - p->apply(this->race, HP, ATK, DEF, base_hit_rate); + for (size_t i = 0; i < effects.size(); ++i) { + effects[i]->apply(this->race, HP, ATK, DEF, base_hit_rate); if (HP <= 0) return result::died; - if (p->get_duration() != 0) - tmp.push_back(p); + if (effects[i]->get_duration() != 0) + tmp.push_back(std::move(effects[i])); } tmp.shrink_to_fit(); @@ -63,12 +63,12 @@ result character::calc_effects() { } void character::discard_level_effects() { - potion_list tmp; + potion_own_list tmp; tmp.reserve(effects.size()); - for (auto p : effects) - if (p->get_duration() > 0) - tmp.push_back(p); + for (size_t i = 0; i < effects.size(); ++i) + if (effects[i]->get_duration() > 0) + tmp.push_back(std::move(effects[i])); tmp.shrink_to_fit(); diff --git a/src/characters.h b/src/characters.h index 980c985..8163ea8 100644 --- a/src/characters.h +++ b/src/characters.h @@ -26,7 +26,7 @@ public: virtual long_result get_hit(character *ch, const int tATK, const fraction &hit_rate) = 0; - virtual void apply_effect(potion *effect); + virtual void apply_effect(std::unique_ptr effect); // override for different types virtual void print(output *out) = 0; @@ -57,10 +57,10 @@ protected: int DEF; fraction base_hit_rate; - potion_list effects; + potion_own_list effects; private: - void insert_effect(potion *effect); + void insert_effect(std::unique_ptr effect); }; int calc_dmg(const int ATK, const int DEF); diff --git a/src/cursor.cc b/src/cursor.cc index 892a90c..c010ca6 100644 --- a/src/cursor.cc +++ b/src/cursor.cc @@ -19,6 +19,7 @@ cursor::cursor() { cursor::~cursor() { endwin(); + refresh(); } int cursor::getcmd() const { diff --git a/src/enemy.cc b/src/enemy.cc index db4aa83..89e8246 100644 --- a/src/enemy.cc +++ b/src/enemy.cc @@ -87,14 +87,6 @@ long_result enemy_base::get_hit(character *ch, const int tATK, } int enemy_base::dies(level *lvl) { - auto &elist = lvl->get_elist(); - - for (size_t i = 0; i < elist.size(); ++i) - if (elist[i] == this) { - elist.erase(elist.begin() + i); - break; - } - if (race == race::rdragon) { return 0; } else if (race == race::rmerchant) { diff --git a/src/game.cc b/src/game.cc index bd2297c..f1358a3 100644 --- a/src/game.cc +++ b/src/game.cc @@ -75,6 +75,7 @@ character *game::move_enemies() { if (ch->is_dead()) { int g = ch->dies(levels[curr_level].get()); + levels[curr_level]->erase_enemy(ch); if (g) levels[curr_level]->add_gold({g, ch->get_pos()}); diff --git a/src/level.cc b/src/level.cc index 0995abd..62b5a1f 100644 --- a/src/level.cc +++ b/src/level.cc @@ -237,14 +237,35 @@ position level::get_down_stairs() const { return map.get_down_stairs(); } -enemy_list &level::get_elist() { +const enemy_list &level::get_elist() { return elist; } -potion_list &level::get_plist() { +const potion_list &level::get_plist() { return plist; } gold_list &level::get_glist() { return glist; } + +std::unique_ptr level::detach_potion(size_t idx) { + if (idx >= plist.size()) + return nullptr; + + auto tmp = std::move(pplist[idx]); + plist.erase(plist.begin() + idx); + pplist.erase(pplist.begin() + idx); + return tmp; +} + +void level::erase_enemy(character *ch) { + if (ch == nullptr) + return; + + for (size_t i = 0; i < elist.size(); ++i) + if (elist[i] == ch) { + elist.erase(elist.begin() + i); + pelist.erase(pelist.begin() + i); + } +} diff --git a/src/level.h b/src/level.h index 34f6ca7..2f02e3b 100644 --- a/src/level.h +++ b/src/level.h @@ -45,11 +45,14 @@ public: position get_down_stairs() const; // you can delete the pointers to the stuff - enemy_list &get_elist(); - potion_list &get_plist(); + const enemy_list &get_elist(); + const potion_list &get_plist(); gold_list &get_glist(); void add_gold(gold g); + + void erase_enemy(character *ch); + std::unique_ptr detach_potion(size_t idx); private: // every gen will delete the positions in tiles void gen_potions(RNG *rng, std::vector &tiles); diff --git a/src/player.cc b/src/player.cc index 677b675..0a83085 100644 --- a/src/player.cc +++ b/src/player.cc @@ -32,19 +32,21 @@ int player_base::get_HP() const { return this->HP; } -long_result player_base::apply(potion *p) { +long_result player_base::apply(std::unique_ptr p) { if (p == nullptr) return {result::applied_nothing, "PC tried to breathe the magic in the air. "}; - apply_effect(p); + std::string name = p->get_name(); + + apply_effect(std::move(p)); if (race == rt_800) return {result::applied, - "PC gets rusty joints (-5 HP). "}; + "PC gets rusty joints (-50 HP). "}; return {result::applied, - (std::string)"PC applied potion of " + p->get_name() + ". "}; + "PC applied potion of " + name + ". "}; } long_result player_base::attack(character *ch) { @@ -68,6 +70,7 @@ long_result player_base::move(level *lvl, if (tmp->is_dead()) { int g = tmp->dies(lvl); + lvl->erase_enemy(tmp); if (g) res.msg += "PC gains " + @@ -131,8 +134,9 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { return res; } else if (cmd >= apply_north && cmd <= apply_southwest) { - auto res = apply(get_potion_at(pos + MOVE[cmd - apply_north], - lvl->get_plist())); + size_t idx = get_potion_at(pos + MOVE[cmd - apply_north], + lvl->get_plist()); + auto res = apply(lvl->detach_potion(idx)); return res; } else if (cmd == apply_panic) { return {result::fine, @@ -145,6 +149,7 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) { if (tmp != nullptr && tmp->is_dead()) { int g = tmp->dies(lvl); + lvl->erase_enemy(tmp); if (g) res.msg += "PC gains " + diff --git a/src/player.h b/src/player.h index 0139bc4..bc6e2f8 100644 --- a/src/player.h +++ b/src/player.h @@ -8,13 +8,13 @@ enum game_command : int; class player_base: public character { protected: int gold_cnt; - potion_list potions; + potion_own_list potions; public: player_base(RNG *rng, const feature enabled_features, const enum race &nrace); virtual long_result move(level *lvl, const position &p); - virtual long_result apply(potion *p); + virtual long_result apply(std::unique_ptr p); virtual long_result attack(character *ch) override; virtual long_result get_hit(character *ch, const int tATK, diff --git a/src/player/t_800.cc b/src/player/t_800.cc index b9bddb2..f84380d 100644 --- a/src/player/t_800.cc +++ b/src/player/t_800.cc @@ -9,7 +9,7 @@ const char *t_800::get_race_name() const { return "T-800"; } -void t_800::apply_effect(potion *p) { +void t_800::apply_effect(std::unique_ptr p) { HP -= RUSTY; return; } diff --git a/src/player/t_800.h b/src/player/t_800.h index 987bbb6..e5c41b5 100644 --- a/src/player/t_800.h +++ b/src/player/t_800.h @@ -5,11 +5,11 @@ class potion; class t_800 final: public player_base { - static const int RUSTY = 5; + static const int RUSTY = 50; public: t_800(RNG *rng, const feature enabled_features); const char *get_race_name() const override; - void apply_effect(potion *p) override; + void apply_effect(std::unique_ptr p) override; }; #endif diff --git a/src/potion.cc b/src/potion.cc index 95751e0..accd252 100644 --- a/src/potion.cc +++ b/src/potion.cc @@ -47,15 +47,10 @@ void potion::print(output *out) { out->print_char(pos, 'P', COLOR_PAIR(COLOR_GREEN)); } -potion *get_potion_at(const position &pos, potion_list &plist) { - potion *ret = nullptr; - +size_t get_potion_at(const position &pos, const potion_list &plist) { for (size_t i = 0; i < plist.size(); ++i) - if (plist[i]->get_pos() == pos) { - ret = plist[i]; - plist.erase(plist.begin() + i); - return ret; - } + if (plist[i]->get_pos() == pos) + return i; - return ret; + return plist.size(); } diff --git a/src/potion.h b/src/potion.h index 745e889..fd3de67 100644 --- a/src/potion.h +++ b/src/potion.h @@ -2,6 +2,7 @@ #define __POTION_H__ #include +#include #include "fraction.h" #include "output.h" @@ -40,7 +41,8 @@ public: }; typedef std::vector potion_list; +typedef std::vector > potion_own_list; -potion *get_potion_at(const position &pos, potion_list &plist); +size_t get_potion_at(const position &pos, const potion_list &plist); #endif