merged paul
This commit is contained in:
@ -13,9 +13,9 @@ void character::start_turn() {
|
||||
base_hit_rate = {1, 1};
|
||||
}
|
||||
|
||||
void character::print(display *out, bool color, bool player) {
|
||||
void character::print(display *out, bool player) {
|
||||
out->print_char(pos, player ? '@' : CHARACTER_REP[race],
|
||||
COLOR_PAIR(COLOR_BLACK_ON_WHITE));
|
||||
player ? COLOR_PAIR(COLOR_BLUE) : COLOR_PAIR(COLOR_RED));
|
||||
}
|
||||
|
||||
enum race character::get_race() const {
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
const fraction hitrate) = 0;
|
||||
|
||||
// overload for different races
|
||||
virtual void print(display *out, bool color = false, bool player = false);
|
||||
virtual void print(display *out, bool player = false);
|
||||
|
||||
result apply_effects();
|
||||
void discard_level_effects();
|
||||
|
34
src/dragon.cc
Normal file
34
src/dragon.cc
Normal file
@ -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;
|
||||
}
|
17
src/dragon.h
Normal file
17
src/dragon.h
Normal file
@ -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
|
20
src/enemies.cc
Normal file
20
src/enemies.cc
Normal file
@ -0,0 +1,20 @@
|
||||
#include "enemies.h"
|
||||
|
||||
// TODO: implement after characters
|
||||
void new_enemy(RNG *rng, std::unique_ptr<character> &pch, const position &pos,
|
||||
bool extras) {
|
||||
if (extras) {
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
void new_dragon(RNG *rng, std::unique_ptr<character> &pch, const position &pos,
|
||||
const position &fallback) {
|
||||
const position nil{0, 0};
|
||||
|
||||
if (pos != nil)
|
||||
pch = std::make_unique<dragon>(rng, pos);
|
||||
else
|
||||
pch = std::make_unique<dragon>(rng, fallback);
|
||||
}
|
14
src/enemies.h
Normal file
14
src/enemies.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __ENEMIES_H__
|
||||
#define __ENEMIES_H__
|
||||
|
||||
#include <memory>
|
||||
#include "characters.h"
|
||||
#include "races.h"
|
||||
|
||||
void new_enemy(RNG *rng, std::unique_ptr<character> &pch, const position &pos,
|
||||
bool extras);
|
||||
|
||||
void new_dragon(RNG *rng, std::unique_ptr<character> &pch, const position &pos,
|
||||
const position &fallback);
|
||||
|
||||
#endif
|
@ -18,7 +18,6 @@ private:
|
||||
logger *log;
|
||||
RNG *rng;
|
||||
|
||||
// IMPORTANT: during player generation,
|
||||
std::unique_ptr<character> player;
|
||||
public:
|
||||
game(const feature enabled_features,
|
||||
@ -28,7 +27,6 @@ public:
|
||||
RNG *new_rng);
|
||||
game_status run();
|
||||
private:
|
||||
int getcmd() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
18
src/gold.cc
Normal file
18
src/gold.cc
Normal file
@ -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;
|
||||
}
|
17
src/gold.h
17
src/gold.h
@ -13,21 +13,6 @@ struct gold {
|
||||
|
||||
typedef std::vector<gold> gold_list;
|
||||
|
||||
int rand_gold_pile(RNG *rng) {
|
||||
const int denominator = 8;
|
||||
const int normal = 5;
|
||||
const int dragon = 6;
|
||||
|
||||
int tmp = rng->rand_under(denominator);
|
||||
|
||||
if (tmp < normal)
|
||||
return GOLD_NORMAL;
|
||||
else if (tmp < dragon)
|
||||
return GOLD_DRAGON;
|
||||
else
|
||||
return GOLD_SMALL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int rand_gold_pile(RNG *rng);
|
||||
|
||||
#endif
|
||||
|
160
src/level.cc
Normal file
160
src/level.cc
Normal file
@ -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<position_list> &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<position_list> &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<position_list> &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<position_list> &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;
|
||||
}
|
@ -5,10 +5,10 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "display.h"
|
||||
#include "gold.h"
|
||||
#include "enemies.h"
|
||||
#include "potions.h"
|
||||
#include "constants.h"
|
||||
#include "gold.h"
|
||||
#include "map.h"
|
||||
|
||||
class level {
|
||||
|
@ -96,11 +96,6 @@ private:
|
||||
room &room2);
|
||||
bool overlap_y(room &room1,
|
||||
room &room2);
|
||||
// has anything between the two
|
||||
bool between_x(room &room1,
|
||||
room &room2);
|
||||
bool between_y(room &room1,
|
||||
room &room2);
|
||||
|
||||
void jitter(RNG *rng, std::vector<room> &rooms);
|
||||
|
||||
|
@ -41,6 +41,6 @@ potion &potion::operator=(potion &&p) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void potion::print(display *out, bool color) {
|
||||
out->print_char(pos, 'P');
|
||||
void potion::print(display *out) {
|
||||
out->print_char(pos, 'P', COLOR_PAIR(COLOR_GREEN));
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
position get_pos() const;
|
||||
void set_pos(const position &npos);
|
||||
|
||||
virtual void print(display *out, bool color = false);
|
||||
virtual void print(display *out);
|
||||
};
|
||||
|
||||
typedef std::vector<potion *> potion_list;
|
||||
|
13
src/potions.cc
Normal file
13
src/potions.cc
Normal file
@ -0,0 +1,13 @@
|
||||
#include "potions.h"
|
||||
|
||||
void new_potion(std::unique_ptr<potion> &pp, potion_type type,
|
||||
const position &pos) {
|
||||
switch (type) {
|
||||
case potion_type::restore_health:
|
||||
pp = std::make_unique<class restore_health>(pos);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
13
src/potions.h
Normal file
13
src/potions.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __POTIONS_H__
|
||||
#define __POTIONS_H__
|
||||
|
||||
#include "potion.h"
|
||||
#include "restore_health.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
void new_potion(std::unique_ptr<potion> &pp, potion_type type,
|
||||
const position &pos);
|
||||
|
||||
#endif
|
37
src/rng.cc
37
src/rng.cc
@ -1,35 +1,35 @@
|
||||
#include "rng.h"
|
||||
|
||||
RNG::RNG(): init_seed(time(0)), curr_rand_num(0) {
|
||||
srand(init_seed);
|
||||
srand(init_seed);
|
||||
}
|
||||
|
||||
RNG::RNG(const unsigned int seed): init_seed(seed), curr_rand_num(0) {
|
||||
srand(init_seed);
|
||||
srand(init_seed);
|
||||
}
|
||||
|
||||
int RNG::rand_num() {
|
||||
return curr_rand_num = rand();
|
||||
return curr_rand_num = rand();
|
||||
}
|
||||
|
||||
int RNG::rand_between(const int lower_bound, const int upper_bound) {
|
||||
curr_rand_num = rand();
|
||||
curr_rand_num = rand();
|
||||
|
||||
return lower_bound + (curr_rand_num % (upper_bound - lower_bound));
|
||||
return lower_bound + (curr_rand_num % (upper_bound - lower_bound));
|
||||
}
|
||||
|
||||
int RNG::rand_under(const int upper_bound) {
|
||||
curr_rand_num = rand();
|
||||
curr_rand_num = rand();
|
||||
|
||||
return curr_rand_num % upper_bound;
|
||||
return curr_rand_num % upper_bound;
|
||||
}
|
||||
|
||||
unsigned int RNG::get_init_seed() const {
|
||||
return init_seed;
|
||||
return init_seed;
|
||||
}
|
||||
|
||||
int RNG::get_curr_rand_num() const {
|
||||
return curr_rand_num;
|
||||
return curr_rand_num;
|
||||
}
|
||||
|
||||
bool RNG::trial(const fraction &psuccess) {
|
||||
@ -47,22 +47,3 @@ int RNG::exclude_middle(const int lower_bound, const int upper_bound,
|
||||
int tmp = (curr_rand_num % (upper_bound - lower_bound - 1));
|
||||
return tmp >= excluded ? tmp + 1 : tmp;
|
||||
}
|
||||
|
||||
template<class T> T RNG::rand_exclude(std::vector<T> &vec, T &target) {
|
||||
std::size_t idx = 0;
|
||||
|
||||
for (; idx < vec.size(); ++idx)
|
||||
if (vec[idx] == target)
|
||||
break;
|
||||
|
||||
return vec[exclude_middle(0, vec.size(), idx)];
|
||||
}
|
||||
|
||||
template<class T> T RNG::get_rand_in_vector(std::vector<T> &vec) {
|
||||
if (!vec.size())
|
||||
return T{};
|
||||
|
||||
curr_rand_num = rand();
|
||||
|
||||
return vec[curr_rand_num % vec.size()];
|
||||
}
|
||||
|
19
src/rng.h
19
src/rng.h
@ -33,9 +33,24 @@ public:
|
||||
int exclude_middle(const int lower_bound, const int upper_bound,
|
||||
const int excluded);
|
||||
|
||||
template<class T> T rand_exclude(std::vector<T> &vec, T &target);
|
||||
template<class T> T rand_exclude(std::vector<T> &vec, T &target) {
|
||||
std::size_t idx = 0;
|
||||
|
||||
template<class T> T get_rand_in_vector(std::vector<T> &vec);
|
||||
for (; idx < vec.size(); ++idx)
|
||||
if (vec[idx] == target)
|
||||
break;
|
||||
|
||||
return vec[exclude_middle(0, vec.size(), idx)];
|
||||
}
|
||||
|
||||
template<class T> T get_rand_in_vector(std::vector<T> &vec) {
|
||||
if (!vec.size())
|
||||
return T{};
|
||||
|
||||
curr_rand_num = rand();
|
||||
|
||||
return vec[curr_rand_num % vec.size()];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1 +0,0 @@
|
||||
#include "room.h"
|
@ -2,9 +2,8 @@
|
||||
#define __VAMPIRE_H__
|
||||
#include "characters.h"
|
||||
|
||||
const int GAIN_HP = 5;
|
||||
|
||||
class vampire final: public character {
|
||||
static const int GAIN_HP = 5;
|
||||
public:
|
||||
vampire(RNG *rng, const position &pos);
|
||||
virtual result attack(const direction dir,
|
||||
|
Reference in New Issue
Block a user