Merge branch 'master' of peisongxiao.com:~/cs246/a5
This commit is contained in:
@ -117,9 +117,8 @@ feature proc_args(int argc, char **argv,
|
|||||||
if (result & FEATURE_SEED) {
|
if (result & FEATURE_SEED) {
|
||||||
std::istringstream iss {seed};
|
std::istringstream iss {seed};
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
iss >> tmp;
|
|
||||||
|
|
||||||
if (!iss.good())
|
if (!(iss >> tmp))
|
||||||
return FEATURE_PANIC_SEED;
|
return FEATURE_PANIC_SEED;
|
||||||
|
|
||||||
rng = std::make_unique<RNG>(tmp);
|
rng = std::make_unique<RNG>(tmp);
|
||||||
|
@ -18,8 +18,10 @@ game_status CC3K::run() {
|
|||||||
case main_menu: {
|
case main_menu: {
|
||||||
auto tmp = curr_menu->run(in);
|
auto tmp = curr_menu->run(in);
|
||||||
|
|
||||||
if (tmp == -2)
|
if (tmp == -2) {
|
||||||
|
gresult.status = terminated;
|
||||||
return terminated;
|
return terminated;
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp != -1) {
|
if (tmp != -1) {
|
||||||
curr_menu = nullptr;
|
curr_menu = nullptr;
|
||||||
|
@ -9,12 +9,12 @@ character::character(RNG *rng, const feature enabled_features,
|
|||||||
rng{rng}, enabled_features{enabled_features},
|
rng{rng}, enabled_features{enabled_features},
|
||||||
race{nrace}, HP{STARTING_HP[race]}, pos{pos},
|
race{nrace}, HP{STARTING_HP[race]}, pos{pos},
|
||||||
ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]},
|
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() {
|
void character::start_turn() {
|
||||||
ATK = STARTING_ATK[race];
|
ATK = STARTING_ATK[race];
|
||||||
DEF = STARTING_DEF[race];
|
DEF = STARTING_DEF[race];
|
||||||
base_hit_rate = base_hit_rate_reset;
|
base_hit_rate = STARTING_HR[race];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum race character::get_race() const {
|
enum race character::get_race() const {
|
||||||
@ -29,12 +29,12 @@ void character::set_pos(const position &npos) {
|
|||||||
pos = npos;
|
pos = npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void character::apply_effect(potion *effect) {
|
void character::apply_effect(std::unique_ptr<potion> effect) {
|
||||||
insert_effect(effect);
|
insert_effect(std::move(effect));
|
||||||
}
|
}
|
||||||
|
|
||||||
void character::insert_effect(potion *effect) {
|
void character::insert_effect(std::unique_ptr<potion> effect) {
|
||||||
effects.push_back(effect);
|
effects.push_back(std::move(effect));
|
||||||
|
|
||||||
for (int i = effects.size() - 1; i > 0 &&
|
for (int i = effects.size() - 1; i > 0 &&
|
||||||
effect->get_priority() < effects[i - 1]->get_priority(); --i)
|
effect->get_priority() < effects[i - 1]->get_priority(); --i)
|
||||||
@ -42,17 +42,17 @@ void character::insert_effect(potion *effect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result character::calc_effects() {
|
result character::calc_effects() {
|
||||||
potion_list tmp;
|
potion_own_list tmp;
|
||||||
tmp.reserve(effects.size());
|
tmp.reserve(effects.size());
|
||||||
|
|
||||||
for (auto p : effects) {
|
for (size_t i = 0; i < effects.size(); ++i) {
|
||||||
p->apply(this->race, HP, ATK, DEF, base_hit_rate);
|
effects[i]->apply(this->race, HP, ATK, DEF, base_hit_rate);
|
||||||
|
|
||||||
if (HP <= 0)
|
if (HP <= 0)
|
||||||
return result::died;
|
return result::died;
|
||||||
|
|
||||||
if (p->get_duration() != 0)
|
if (effects[i]->get_duration() != 0)
|
||||||
tmp.push_back(p);
|
tmp.push_back(std::move(effects[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp.shrink_to_fit();
|
tmp.shrink_to_fit();
|
||||||
@ -63,12 +63,12 @@ result character::calc_effects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void character::discard_level_effects() {
|
void character::discard_level_effects() {
|
||||||
potion_list tmp;
|
potion_own_list tmp;
|
||||||
tmp.reserve(effects.size());
|
tmp.reserve(effects.size());
|
||||||
|
|
||||||
for (auto p : effects)
|
for (size_t i = 0; i < effects.size(); ++i)
|
||||||
if (p->get_duration() > 0)
|
if (effects[i]->get_duration() > 0)
|
||||||
tmp.push_back(p);
|
tmp.push_back(std::move(effects[i]));
|
||||||
|
|
||||||
tmp.shrink_to_fit();
|
tmp.shrink_to_fit();
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
virtual long_result get_hit(character *ch, const int tATK,
|
virtual long_result get_hit(character *ch, const int tATK,
|
||||||
const fraction &hit_rate) = 0;
|
const fraction &hit_rate) = 0;
|
||||||
|
|
||||||
virtual void apply_effect(potion *effect);
|
virtual void apply_effect(std::unique_ptr<potion> effect);
|
||||||
|
|
||||||
// override for different types
|
// override for different types
|
||||||
virtual void print(output *out) = 0;
|
virtual void print(output *out) = 0;
|
||||||
@ -56,12 +56,11 @@ protected:
|
|||||||
int ATK;
|
int ATK;
|
||||||
int DEF;
|
int DEF;
|
||||||
fraction base_hit_rate;
|
fraction base_hit_rate;
|
||||||
fraction base_hit_rate_reset;
|
|
||||||
|
|
||||||
potion_list effects;
|
potion_own_list effects;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void insert_effect(potion *effect);
|
void insert_effect(std::unique_ptr<potion> effect);
|
||||||
};
|
};
|
||||||
|
|
||||||
int calc_dmg(const int ATK, const int DEF);
|
int calc_dmg(const int ATK, const int DEF);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
|
#include "fraction.h"
|
||||||
|
|
||||||
static const int INF = 0x3F3F3F3F;
|
static const int INF = 0x3F3F3F3F;
|
||||||
|
|
||||||
@ -41,27 +42,33 @@ enum game_command : int {game_command_terminate = 0,
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Character generation related
|
// Character generation related
|
||||||
static const int RACE_CNT = 12;
|
static const int RACE_CNT = 13;
|
||||||
enum race : int {rshade = 0, rdrow, rvampire, rtroll,
|
enum race : int {rshade = 0, rdrow, rvampire, rtroll,
|
||||||
rgoblin, rhuman, rdwarf, relf,
|
rgoblin, rhuman, rdwarf, relf,
|
||||||
rorc, rmerchant, rdragon, rhalfling
|
rorc, rmerchant, rdragon, rhalfling,
|
||||||
|
rt_800
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char CHAR_REP[RACE_CNT] = {
|
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] = {
|
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] = {
|
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] = {
|
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] = {
|
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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ cursor::cursor() {
|
|||||||
|
|
||||||
cursor::~cursor() {
|
cursor::~cursor() {
|
||||||
endwin();
|
endwin();
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cursor::getcmd() const {
|
int cursor::getcmd() const {
|
||||||
|
@ -9,17 +9,18 @@
|
|||||||
#include "enemies/merchant.h"
|
#include "enemies/merchant.h"
|
||||||
#include "enemies/orc.h"
|
#include "enemies/orc.h"
|
||||||
|
|
||||||
void new_dragon(RNG *rng, std::unique_ptr<enemy_base> &p,
|
std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
|
||||||
const position &pos, const position &fallback,
|
const position &fallback,
|
||||||
const feature enabled_features, int which_room) {
|
const feature enabled_features,
|
||||||
|
int which_room) {
|
||||||
const position nil{0, 0};
|
const position nil{0, 0};
|
||||||
|
|
||||||
if (pos != nil)
|
if (pos != nil)
|
||||||
p = std::make_unique<dragon>(rng, enabled_features,
|
return std::make_unique<dragon>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
else
|
else
|
||||||
p = std::make_unique<dragon>(rng, enabled_features,
|
return std::make_unique<dragon>(rng, enabled_features,
|
||||||
fallback, which_room);
|
fallback, which_room);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int EXCNT = 6;
|
const int EXCNT = 6;
|
||||||
@ -44,9 +45,9 @@ enum race get_normal_race(RNG *rng) {
|
|||||||
return CHOICES[rng->rand_under(CNT)];
|
return CHOICES[rng->rand_under(CNT)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void new_enemy(RNG *rng, std::unique_ptr<enemy_base> &p,
|
std::unique_ptr<enemy_base> new_enemy(RNG *rng, const position &pos,
|
||||||
const position &pos, const feature enabled_features,
|
const feature enabled_features,
|
||||||
int which_room) {
|
int which_room) {
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
|
||||||
enum race r;
|
enum race r;
|
||||||
@ -56,34 +57,40 @@ void new_enemy(RNG *rng, std::unique_ptr<enemy_base> &p,
|
|||||||
else
|
else
|
||||||
r = get_normal_race(rng);
|
r = get_normal_race(rng);
|
||||||
|
|
||||||
p = nullptr;
|
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case rdwarf:
|
case rdwarf:
|
||||||
p = make_unique<dwarf>(rng, enabled_features, pos, which_room);
|
return make_unique<dwarf>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rhuman:
|
case rhuman:
|
||||||
p = make_unique<human>(rng, enabled_features, pos, which_room);
|
return make_unique<human>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case relf:
|
case relf:
|
||||||
p = make_unique<elf>(rng, enabled_features, pos, which_room);
|
return make_unique<elf>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rorc:
|
case rorc:
|
||||||
p = make_unique<orc>(rng, enabled_features, pos, which_room);
|
return make_unique<orc>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rmerchant:
|
case rmerchant:
|
||||||
p = make_unique<merchant>(rng, enabled_features, pos, which_room);
|
return make_unique<merchant>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rhalfling:
|
case rhalfling:
|
||||||
p = make_unique<halfling>(rng, enabled_features, pos, which_room);
|
return make_unique<halfling>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "enemy.h"
|
#include "enemy.h"
|
||||||
|
|
||||||
void new_dragon(RNG *rng, std::unique_ptr<enemy_base> &p,
|
std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
|
||||||
const position &pos, const position &fallback,
|
const position &fallback,
|
||||||
const feature enabled_features, int which_room);
|
const feature enabled_features,
|
||||||
|
int which_room);
|
||||||
|
|
||||||
void new_enemy(RNG *rng, std::unique_ptr<enemy_base> &p,
|
std::unique_ptr<enemy_base> new_enemy(RNG *rng, const position &pos,
|
||||||
const position &pos, const feature enabled_features,
|
const feature enabled_features,
|
||||||
int which_room);
|
int which_room);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,9 @@ long_result elf::attack(character *ch) {
|
|||||||
if (res1.res == result::died)
|
if (res1.res == result::died)
|
||||||
return res1;
|
return res1;
|
||||||
|
|
||||||
|
if (ch->get_race() == rdrow)
|
||||||
|
return res1;
|
||||||
|
|
||||||
auto res2 = ch->get_hit(this, ATK, base_hit_rate);
|
auto res2 = ch->get_hit(this, ATK, base_hit_rate);
|
||||||
|
|
||||||
if (res1.res == miss && res2.res == miss)
|
if (res1.res == miss && res2.res == miss)
|
||||||
|
20
src/enemy.cc
20
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 enum race &nrace, const position &pos,
|
||||||
const int gen_room_num, std::string abbrev):
|
const int gen_room_num, std::string abbrev):
|
||||||
character{rng, enabled_features, nrace, pos},
|
character{rng, enabled_features, nrace, pos},
|
||||||
room_num{gen_room_num}, abbrev{abbrev} {
|
room_num{gen_room_num}, abbrev{abbrev} {}
|
||||||
base_hit_rate_reset = {1, 2};
|
|
||||||
}
|
|
||||||
|
|
||||||
int enemy_base::get_room_num() const {
|
int enemy_base::get_room_num() const {
|
||||||
return room_num;
|
return room_num;
|
||||||
@ -88,27 +86,21 @@ long_result enemy_base::get_hit(character *ch, const int tATK,
|
|||||||
return {miss, "PC tried to hit " + abbrev + " but missed. "};
|
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)
|
|
||||||
if (elist[i] == this) {
|
|
||||||
elist.erase(elist.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (race == race::rdragon) {
|
if (race == race::rdragon) {
|
||||||
return;
|
return 0;
|
||||||
} else if (race == race::rmerchant) {
|
} else if (race == race::rmerchant) {
|
||||||
lvl->add_gold({GOLD_MERCHANT, pos});
|
lvl->add_gold({GOLD_MERCHANT, pos});
|
||||||
|
return 0;
|
||||||
} else if (race == race::rhuman) {
|
} else if (race == race::rhuman) {
|
||||||
lvl->add_gold({GOLD_NORMAL, pos});
|
lvl->add_gold({GOLD_NORMAL, pos});
|
||||||
auto plist = lvl->get_available_around_all(pos);
|
auto plist = lvl->get_available_around_all(pos);
|
||||||
lvl->add_gold({GOLD_NORMAL,
|
lvl->add_gold({GOLD_NORMAL,
|
||||||
rng->get_rand_in_vector(plist)});
|
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) {
|
enemy_base *get_enemy_at(const position &pos, const enemy_list &elist) {
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
|
|
||||||
virtual std::string get_abbrev() const override;
|
virtual std::string get_abbrev() const override;
|
||||||
|
|
||||||
virtual void dies(level *lvl, character *pc);
|
virtual int dies(level *lvl);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<enemy_base *> enemy_list;
|
typedef std::vector<enemy_base *> enemy_list;
|
||||||
|
23
src/game.cc
23
src/game.cc
@ -15,7 +15,7 @@ game::game(const enum race starting_race,
|
|||||||
the_world = false;
|
the_world = false;
|
||||||
|
|
||||||
// TODO: add the other races
|
// 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)
|
if (enabled_features & FEATURE_EXTRA_LEVELS)
|
||||||
max_level = rng->rand_between(MIN_LEVEL_CNT, MAX_LEVEL_CNT + 1);
|
max_level = rng->rand_between(MIN_LEVEL_CNT, MAX_LEVEL_CNT + 1);
|
||||||
@ -73,8 +73,13 @@ character *game::move_enemies() {
|
|||||||
if (player->is_dead())
|
if (player->is_dead())
|
||||||
return ch;
|
return ch;
|
||||||
|
|
||||||
if (ch->is_dead())
|
if (ch->is_dead()) {
|
||||||
ch->dies(levels[curr_level].get(), player.get());
|
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()});
|
||||||
|
}
|
||||||
|
|
||||||
msg += res.msg;
|
msg += res.msg;
|
||||||
}
|
}
|
||||||
@ -105,6 +110,8 @@ game_result game::run() {
|
|||||||
std::to_string(curr_turn + 1) +
|
std::to_string(curr_turn + 1) +
|
||||||
" turns!"};
|
" turns!"};
|
||||||
|
|
||||||
|
player->start_turn();
|
||||||
|
|
||||||
player->discard_level_effects();
|
player->discard_level_effects();
|
||||||
|
|
||||||
++curr_level;
|
++curr_level;
|
||||||
@ -112,6 +119,9 @@ game_result game::run() {
|
|||||||
if (curr_level == levels.size())
|
if (curr_level == levels.size())
|
||||||
new_level();
|
new_level();
|
||||||
|
|
||||||
|
if (enabled_features & FEATURE_REVISIT)
|
||||||
|
player->set_pos(levels[curr_level]->get_up_stairs());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +133,8 @@ game_result game::run() {
|
|||||||
std::to_string(curr_turn + 1) +
|
std::to_string(curr_turn + 1) +
|
||||||
" turns! Coward!"};
|
" turns! Coward!"};
|
||||||
|
|
||||||
|
player->start_turn();
|
||||||
|
|
||||||
player->discard_level_effects();
|
player->discard_level_effects();
|
||||||
|
|
||||||
--curr_level;
|
--curr_level;
|
||||||
@ -142,13 +154,15 @@ game_result game::run() {
|
|||||||
case unknown:
|
case unknown:
|
||||||
case fine:
|
case fine:
|
||||||
case applied_nothing:
|
case applied_nothing:
|
||||||
++curr_turn;
|
|
||||||
return {in_game, ""};
|
return {in_game, ""};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
player->start_turn();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++curr_turn;
|
||||||
|
|
||||||
player->calc_effects();
|
player->calc_effects();
|
||||||
|
|
||||||
if (player->is_dead())
|
if (player->is_dead())
|
||||||
@ -164,7 +178,6 @@ game_result game::run() {
|
|||||||
killer->get_race_name()};
|
killer->get_race_name()};
|
||||||
}
|
}
|
||||||
|
|
||||||
++curr_turn;
|
|
||||||
return {in_game, ""};
|
return {in_game, ""};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
src/level.cc
60
src/level.cc
@ -7,6 +7,9 @@ level::level(character *player, RNG *rng, const feature enabled_features):
|
|||||||
player{player} {
|
player{player} {
|
||||||
auto tiles = map.get_room_list();
|
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)
|
for (size_t i = 0; i < tiles.size(); ++i)
|
||||||
remove_from_list(tiles[i], map.get_down_stairs());
|
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} {
|
map{player, map_data, rng, enabled_features}, player{player} {
|
||||||
auto tiles = map.get_room_list();
|
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)
|
for (size_t i = 0; i < tiles.size(); ++i)
|
||||||
remove_from_list(tiles[i], map.get_down_stairs());
|
remove_from_list(tiles[i], map.get_down_stairs());
|
||||||
|
|
||||||
@ -66,18 +72,25 @@ void level::gen_enemies(RNG *rng, std::vector<position_list> &tiles) {
|
|||||||
spots.push_back(dhoard[i].pos + MOVE[i]);
|
spots.push_back(dhoard[i].pos + MOVE[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pelist.push_back(nullptr);
|
auto pos = spots.size() ? rng->get_rand_in_vector(spots) :
|
||||||
new_dragon(rng, pelist[i], rng->get_rand_in_vector(spots),
|
dhoard[i].pos;
|
||||||
dhoard[i].pos, enabled_features,
|
pelist.push_back(new_dragon(rng, pos, dhoard[i].pos,
|
||||||
map.which_room(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());
|
elist.push_back(pelist[i].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = dhoard.size(); i < cnt; ++i) {
|
for (int i = dhoard.size(); i < cnt; ++i) {
|
||||||
pelist.push_back(nullptr);
|
|
||||||
auto p = get_rand_pos(rng, tiles);
|
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());
|
elist.push_back(pelist[i].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,10 +136,8 @@ void level::gen_potions(RNG *rng, std::vector<position_list> &tiles) {
|
|||||||
pplist.reserve(cnt);
|
pplist.reserve(cnt);
|
||||||
|
|
||||||
for (int i = 0; i < cnt; ++i) {
|
for (int i = 0; i < cnt; ++i) {
|
||||||
pplist.push_back(nullptr);
|
pplist.push_back(new_potion((potion_type)rng->rand_under(max_type),
|
||||||
new_potion(pplist[i],
|
get_rand_pos(rng, tiles)));
|
||||||
(potion_type)rng->rand_under(max_type),
|
|
||||||
get_rand_pos(rng, tiles));
|
|
||||||
plist.push_back(pplist[i].get());
|
plist.push_back(pplist[i].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,6 +183,10 @@ bool level::is_available_all(const position &pos) const {
|
|||||||
if (!map.is_available(pos))
|
if (!map.is_available(pos))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!(enabled_features & FEATURE_DOORS) &&
|
||||||
|
map.which_room(pos) == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (player->get_pos() == pos)
|
if (player->get_pos() == pos)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -222,14 +237,35 @@ position level::get_down_stairs() const {
|
|||||||
return map.get_down_stairs();
|
return map.get_down_stairs();
|
||||||
}
|
}
|
||||||
|
|
||||||
enemy_list &level::get_elist() {
|
const enemy_list &level::get_elist() {
|
||||||
return elist;
|
return elist;
|
||||||
}
|
}
|
||||||
|
|
||||||
potion_list &level::get_plist() {
|
const potion_list &level::get_plist() {
|
||||||
return plist;
|
return plist;
|
||||||
}
|
}
|
||||||
|
|
||||||
gold_list &level::get_glist() {
|
gold_list &level::get_glist() {
|
||||||
return glist;
|
return glist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<potion> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -45,11 +45,14 @@ public:
|
|||||||
position get_down_stairs() const;
|
position get_down_stairs() const;
|
||||||
|
|
||||||
// you can delete the pointers to the stuff
|
// you can delete the pointers to the stuff
|
||||||
enemy_list &get_elist();
|
const enemy_list &get_elist();
|
||||||
potion_list &get_plist();
|
const potion_list &get_plist();
|
||||||
gold_list &get_glist();
|
gold_list &get_glist();
|
||||||
|
|
||||||
void add_gold(gold g);
|
void add_gold(gold g);
|
||||||
|
|
||||||
|
void erase_enemy(character *ch);
|
||||||
|
std::unique_ptr<potion> detach_potion(size_t idx);
|
||||||
private:
|
private:
|
||||||
// every gen will delete the positions in tiles
|
// every gen will delete the positions in tiles
|
||||||
void gen_potions(RNG *rng, std::vector<position_list> &tiles);
|
void gen_potions(RNG *rng, std::vector<position_list> &tiles);
|
||||||
|
17
src/output.cc
Normal file
17
src/output.cc
Normal file
@ -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);
|
||||||
|
}
|
35
src/output.h
Normal file
35
src/output.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __DISPLAY_H__
|
||||||
|
#define __DISPLAY_H__
|
||||||
|
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <vector>
|
||||||
|
#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<int> 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
|
100
src/output/console_output.cc
Normal file
100
src/output/console_output.cc
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include "console_output.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <ncurses.h>
|
||||||
|
|
||||||
|
#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];
|
||||||
|
}
|
21
src/output/console_output.h
Normal file
21
src/output/console_output.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef __CONSOLE_OUTPUT_H__
|
||||||
|
#define __CONSOLE_OUTPUT_H__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#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
|
38
src/output/curses_output.cc
Normal file
38
src/output/curses_output.cc
Normal file
@ -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};
|
||||||
|
}
|
||||||
|
}
|
23
src/output/curses_output.h
Normal file
23
src/output/curses_output.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef __CURSES_OUTPUT_H__
|
||||||
|
#define __CURSES_OUTPUT_H__
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
#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
|
38
src/output/file_output.cc
Normal file
38
src/output/file_output.cc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "file_output.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#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];
|
||||||
|
}
|
20
src/output/file_output.h
Normal file
20
src/output/file_output.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __FILE_OUTPUT_H__
|
||||||
|
#define __FILE_OUTPUT_H__
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#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
|
23
src/pc.cc
23
src/pc.cc
@ -6,35 +6,40 @@
|
|||||||
#include "player/shade.h"
|
#include "player/shade.h"
|
||||||
#include "player/troll.h"
|
#include "player/troll.h"
|
||||||
#include "player/vampire.h"
|
#include "player/vampire.h"
|
||||||
|
#include "player/t_800.h"
|
||||||
|
|
||||||
void init_player(RNG *rng, std::unique_ptr<player_base> &pc,
|
std::unique_ptr<player_base> init_player(RNG *rng,
|
||||||
const feature enabled_features, const enum race &r) {
|
const feature enabled_features, const enum race &r) {
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
|
||||||
pc = nullptr;
|
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case rgoblin:
|
case rgoblin:
|
||||||
pc = make_unique<goblin>(rng, enabled_features);
|
return make_unique<goblin>(rng, enabled_features);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rdrow:
|
case rdrow:
|
||||||
pc = make_unique<drow>(rng, enabled_features);
|
return make_unique<drow>(rng, enabled_features);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rshade:
|
case rshade:
|
||||||
pc = make_unique<shade>(rng, enabled_features);
|
return make_unique<shade>(rng, enabled_features);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rtroll:
|
case rtroll:
|
||||||
pc = make_unique<troll>(rng, enabled_features);
|
return make_unique<troll>(rng, enabled_features);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rvampire:
|
case rvampire:
|
||||||
pc = make_unique<vampire>(rng, enabled_features);
|
return make_unique<vampire>(rng, enabled_features);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rt_800:
|
||||||
|
return make_unique<t_800>(rng, enabled_features);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
4
src/pc.h
4
src/pc.h
@ -4,7 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|
||||||
void init_player(RNG *rng, std::unique_ptr<player_base> &pc,
|
std::unique_ptr<player_base> init_player(RNG *rng,
|
||||||
const feature enabled_features, const enum race &r);
|
const feature enabled_features, const enum race &r);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,15 +32,21 @@ int player_base::get_HP() const {
|
|||||||
return this->HP;
|
return this->HP;
|
||||||
}
|
}
|
||||||
|
|
||||||
long_result player_base::apply(potion *p) {
|
long_result player_base::apply(std::unique_ptr<potion> p) {
|
||||||
if (p == nullptr)
|
if (p == nullptr)
|
||||||
return {result::applied_nothing,
|
return {result::applied_nothing,
|
||||||
"PC tried to breathe the magic in the air. "};
|
"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 (-50 HP). "};
|
||||||
|
|
||||||
return {result::applied,
|
return {result::applied,
|
||||||
(std::string)"PC applied potion of " + p->get_name() + ". "};
|
"PC applied potion of " + name + ". "};
|
||||||
}
|
}
|
||||||
|
|
||||||
long_result player_base::attack(character *ch) {
|
long_result player_base::attack(character *ch) {
|
||||||
@ -62,8 +68,15 @@ long_result player_base::move(level *lvl,
|
|||||||
} else if ((tmp = get_enemy_at(p, lvl->get_elist())) != nullptr) {
|
} else if ((tmp = get_enemy_at(p, lvl->get_elist())) != nullptr) {
|
||||||
auto res = attack((character *)tmp);
|
auto res = attack((character *)tmp);
|
||||||
|
|
||||||
if (tmp->is_dead())
|
if (tmp->is_dead()) {
|
||||||
tmp->dies(lvl, this);
|
int g = tmp->dies(lvl);
|
||||||
|
lvl->erase_enemy(tmp);
|
||||||
|
|
||||||
|
if (g)
|
||||||
|
res.msg += "PC gains " +
|
||||||
|
std::to_string(g) +
|
||||||
|
" pieces of gold. ";
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -112,19 +125,18 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) {
|
|||||||
} else if (cmd >= move_north && cmd <= move_southwest) {
|
} else if (cmd >= move_north && cmd <= move_southwest) {
|
||||||
auto res = move(lvl, pos + MOVE[cmd - move_north]);
|
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 g = get_gold_at(pos, lvl->get_glist());
|
||||||
gold_cnt += g.amount;
|
gold_cnt += g.amount;
|
||||||
|
|
||||||
|
if (g.amount)
|
||||||
|
res.msg += "PC picked up " + std::to_string(g.amount) +
|
||||||
|
" pieces of gold. ";
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} else if (cmd >= apply_north && cmd <= apply_southwest) {
|
} else if (cmd >= apply_north && cmd <= apply_southwest) {
|
||||||
auto res = apply(get_potion_at(pos + MOVE[cmd - apply_north],
|
size_t idx = get_potion_at(pos + MOVE[cmd - apply_north],
|
||||||
lvl->get_plist()));
|
lvl->get_plist());
|
||||||
|
auto res = apply(lvl->detach_potion(idx));
|
||||||
if (res.res == result::applied)
|
|
||||||
start_turn();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} else if (cmd == apply_panic) {
|
} else if (cmd == apply_panic) {
|
||||||
return {result::fine,
|
return {result::fine,
|
||||||
@ -133,29 +145,29 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) {
|
|||||||
enemy_base *tmp = get_enemy_at(pos + MOVE[cmd - attack_north],
|
enemy_base *tmp = get_enemy_at(pos + MOVE[cmd - attack_north],
|
||||||
lvl->get_elist());
|
lvl->get_elist());
|
||||||
|
|
||||||
if (tmp != nullptr)
|
|
||||||
start_turn();
|
|
||||||
|
|
||||||
auto res = attack((character *)tmp);
|
auto res = attack((character *)tmp);
|
||||||
|
|
||||||
if (tmp != nullptr && tmp->is_dead())
|
if (tmp != nullptr && tmp->is_dead()) {
|
||||||
tmp->dies(lvl, this);
|
int g = tmp->dies(lvl);
|
||||||
|
lvl->erase_enemy(tmp);
|
||||||
|
|
||||||
|
if (g)
|
||||||
|
res.msg += "PC gains " +
|
||||||
|
std::to_string(g) +
|
||||||
|
" pieces of gold. ";
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} else if (cmd == up_stairs) {
|
} else if (cmd == up_stairs) {
|
||||||
if (lvl->get_up_stairs() == pos &&
|
if (lvl->get_up_stairs() == pos &&
|
||||||
enabled_features & FEATURE_REVISIT) {
|
enabled_features & FEATURE_REVISIT)
|
||||||
start_turn();
|
|
||||||
return {go_up, "PC went up the stairs. "};
|
return {go_up, "PC went up the stairs. "};
|
||||||
}
|
|
||||||
|
|
||||||
return {result::fine,
|
return {result::fine,
|
||||||
"PC tried to fly through the ceiling. "};
|
"PC tried to fly through the ceiling. "};
|
||||||
} else if (cmd == down_stairs) {
|
} else if (cmd == down_stairs) {
|
||||||
if (lvl->get_down_stairs() == pos) {
|
if (lvl->get_down_stairs() == pos)
|
||||||
start_turn();
|
|
||||||
return {go_down, "PC went down the stairs. "};
|
return {go_down, "PC went down the stairs. "};
|
||||||
}
|
|
||||||
|
|
||||||
return {result::fine,
|
return {result::fine,
|
||||||
"PC tried to dig through the floor. "};
|
"PC tried to dig through the floor. "};
|
||||||
|
@ -8,13 +8,13 @@ enum game_command : int;
|
|||||||
class player_base: public character {
|
class player_base: public character {
|
||||||
protected:
|
protected:
|
||||||
int gold_cnt;
|
int gold_cnt;
|
||||||
potion_list potions;
|
potion_own_list potions;
|
||||||
public:
|
public:
|
||||||
player_base(RNG *rng, const feature enabled_features,
|
player_base(RNG *rng, const feature enabled_features,
|
||||||
const enum race &nrace);
|
const enum race &nrace);
|
||||||
virtual long_result move(level *lvl, const position &p);
|
virtual long_result move(level *lvl, const position &p);
|
||||||
|
|
||||||
virtual long_result apply(potion *p);
|
virtual long_result apply(std::unique_ptr<potion> p);
|
||||||
|
|
||||||
virtual long_result attack(character *ch) override;
|
virtual long_result attack(character *ch) override;
|
||||||
virtual long_result get_hit(character *ch, const int tATK,
|
virtual long_result get_hit(character *ch, const int tATK,
|
||||||
|
15
src/player/t_800.cc
Normal file
15
src/player/t_800.cc
Normal file
@ -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(std::unique_ptr<potion> p) {
|
||||||
|
HP -= RUSTY;
|
||||||
|
return;
|
||||||
|
}
|
15
src/player/t_800.h
Normal file
15
src/player/t_800.h
Normal file
@ -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 = 50;
|
||||||
|
public:
|
||||||
|
t_800(RNG *rng, const feature enabled_features);
|
||||||
|
const char *get_race_name() const override;
|
||||||
|
void apply_effect(std::unique_ptr<potion> p) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -47,15 +47,10 @@ void potion::print(output *out) {
|
|||||||
out->print_char(pos, 'P', COLOR_PAIR(COLOR_GREEN));
|
out->print_char(pos, 'P', COLOR_PAIR(COLOR_GREEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
potion *get_potion_at(const position &pos, potion_list &plist) {
|
size_t get_potion_at(const position &pos, const potion_list &plist) {
|
||||||
potion *ret = nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < plist.size(); ++i)
|
for (size_t i = 0; i < plist.size(); ++i)
|
||||||
if (plist[i]->get_pos() == pos) {
|
if (plist[i]->get_pos() == pos)
|
||||||
ret = plist[i];
|
return i;
|
||||||
plist.erase(plist.begin() + i);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return plist.size();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __POTION_H__
|
#define __POTION_H__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
#include "fraction.h"
|
#include "fraction.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<potion *> potion_list;
|
typedef std::vector<potion *> potion_list;
|
||||||
|
typedef std::vector<std::unique_ptr<potion> > 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
|
#endif
|
||||||
|
@ -8,34 +8,35 @@
|
|||||||
#include "potions/wound_atk.h"
|
#include "potions/wound_atk.h"
|
||||||
#include "potions/wound_def.h"
|
#include "potions/wound_def.h"
|
||||||
|
|
||||||
void new_potion(std::unique_ptr<potion> &pp, potion_type type,
|
std::unique_ptr<potion> new_potion(potion_type type, const position &pos) {
|
||||||
const position &pos) {
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case restore_health:
|
case restore_health:
|
||||||
pp = std::make_unique<class restore_health>(pos);
|
return std::make_unique<class restore_health>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case boost_atk:
|
case boost_atk:
|
||||||
pp = std::make_unique<class boost_atk>(pos);
|
return std::make_unique<class boost_atk>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case boost_def:
|
case boost_def:
|
||||||
pp = std::make_unique<class boost_def>(pos);
|
return std::make_unique<class boost_def>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case poison_health:
|
case poison_health:
|
||||||
pp = std::make_unique<class poison_health>(pos);
|
return std::make_unique<class poison_health>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wound_atk:
|
case wound_atk:
|
||||||
pp = std::make_unique<class wound_atk>(pos);
|
return std::make_unique<class wound_atk>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wound_def:
|
case wound_def:
|
||||||
pp = std::make_unique<class wound_def>(pos);
|
return std::make_unique<class wound_def>(pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
void new_potion(std::unique_ptr<potion> &pp, potion_type type,
|
std::unique_ptr<potion> new_potion(potion_type type, const position &pos);
|
||||||
const position &pos);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user