TODO: modify other races constructors
did some reworking
This commit is contained in:
@ -41,6 +41,8 @@ feature proc_args(int argc, char **argv,
|
||||
result |= FEATURE_MENU;
|
||||
} else if (str == "-c") {
|
||||
result |= FEATURE_ENEMIES_CHASE;
|
||||
} else if (str == "-C") {
|
||||
result |= FEATURE_COLORFUL;
|
||||
} else if (str == "-i") {
|
||||
result |= FEATURE_INVENTORY;
|
||||
} else if (str == "-t") {
|
||||
@ -186,6 +188,7 @@ void print_args_list() {
|
||||
-r : Randomly generate maps\n\
|
||||
-m : Enabled a main menu + options\n\
|
||||
-c : Enemies chase the player (through doors and up stairs)\n\
|
||||
-C : Give things better coloring\n\
|
||||
-i : Enable inventory\n\
|
||||
-t : Enable throw\n\
|
||||
-R : Enable revisiting levels\n\
|
||||
|
@ -2,11 +2,10 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
character::character(RNG *rng, const enum race &nrace):
|
||||
rng{rng},
|
||||
race{nrace}, HP{STARTING_HP[race]},
|
||||
character::character(RNG *rng, const enum race &nrace, const position &pos):
|
||||
rng{rng}, race{nrace}, HP{STARTING_HP[race]},
|
||||
ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]},
|
||||
base_hit_rate{1, 1} {}
|
||||
base_hit_rate{1, 1}, pos{pos} {}
|
||||
|
||||
void character::start_turn() {
|
||||
ATK = STARTING_ATK[race];
|
||||
@ -14,6 +13,11 @@ void character::start_turn() {
|
||||
base_hit_rate = {1, 1};
|
||||
}
|
||||
|
||||
void character::print(display *out, bool color, bool player) {
|
||||
out->print_char(pos, player ? '@' : CHARACTER_REP[race],
|
||||
COLOR_PAIR(COLOR_BLACK_ON_WHITE));
|
||||
}
|
||||
|
||||
enum race character::get_race() const {
|
||||
return race;
|
||||
}
|
||||
@ -46,10 +50,18 @@ fraction character::get_hitrate() const {
|
||||
return base_hit_rate;
|
||||
}
|
||||
|
||||
int character::get_room_num() const {
|
||||
return room_num;
|
||||
}
|
||||
|
||||
bool character::is_hostile() const {
|
||||
return hostile;
|
||||
}
|
||||
|
||||
void character::set_room_num(const int room) {
|
||||
room_num = room;
|
||||
}
|
||||
|
||||
void character::set_position(const position &npos) {
|
||||
pos = npos;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "display.h"
|
||||
#include "fraction.h"
|
||||
#include "position.h"
|
||||
#include "potions.h"
|
||||
@ -15,11 +16,12 @@
|
||||
class character; // forward declaration
|
||||
|
||||
// Note: player should not be in the character list
|
||||
typedef std::vector<character> character_list;
|
||||
typedef std::vector<character *> character_list;
|
||||
|
||||
class character {
|
||||
public:
|
||||
character(RNG *rng, const race &nrace); // fills out the starting stats
|
||||
character(RNG *rng, const race &nrace,
|
||||
const position &pos); // fills out the starting stats
|
||||
|
||||
// usually I wouldn't do this but considering that the map has
|
||||
// a super small size an O(n) solution is acceptable
|
||||
@ -36,6 +38,10 @@ public:
|
||||
potion_list &potions);
|
||||
virtual result get_hit(const enum race &race, const int atk,
|
||||
const fraction hitrate) = 0;
|
||||
|
||||
// overload for different races
|
||||
virtual void print(display *out, bool color = false, bool player = false);
|
||||
|
||||
result apply_effects();
|
||||
void discard_level_effects();
|
||||
void start_turn();
|
||||
@ -49,6 +55,7 @@ public:
|
||||
float get_hitrate_real() const;
|
||||
fraction get_hitrate() const;
|
||||
bool is_hostile() const;
|
||||
int get_room_num() const;
|
||||
|
||||
void set_position(const position &npos);
|
||||
void set_HP(const int nHP);
|
||||
@ -56,7 +63,8 @@ public:
|
||||
void set_DEF(const int nDEF);
|
||||
void set_gold(const int ngold);
|
||||
void set_hitrate(const fraction nhitrate);
|
||||
void set_hostile(const bool is_hostile);
|
||||
virtual void set_hostile(const bool is_hostile);
|
||||
void set_room_num(const int room);
|
||||
|
||||
// if stat is hostile, positive to set it to hostile,
|
||||
// negative to set it to peaceful
|
||||
@ -81,6 +89,7 @@ protected:
|
||||
potion_list effects; // applied potions
|
||||
|
||||
bool hostile;
|
||||
int room_num;
|
||||
private:
|
||||
void insert_potion(potion *p);
|
||||
};
|
||||
|
@ -31,17 +31,19 @@ enum game_command {game_command_terminate = 0,
|
||||
|
||||
enum stat_name {HP, ATK, DEF, hostile};
|
||||
|
||||
const int RACE_CNT = 4; // TODO: update as you go
|
||||
const int RACE_CNT = 5; // TODO: update as you go
|
||||
|
||||
enum race {rshade = 0, rvampire, rgoblin, rdrow /* TODO: fill out the other races (including enemies) */};
|
||||
enum race {rshade = 0, rvampire, rgoblin, rdrow, rdragon /* TODO: fill out the other races (including enemies) */};
|
||||
|
||||
// TODO: fill out the other races (including enemies)
|
||||
const int MAX_HP[RACE_CNT] = {125, INF, 110, 150};
|
||||
const int STARTING_HP[RACE_CNT] = {125, 50, 110, 150};
|
||||
const int STARTING_ATK[RACE_CNT] = {25, 25, 15, 25};
|
||||
const int STARTING_DEF[RACE_CNT] = {25, 25, 20, 15};
|
||||
const char CHARACTER_REP[RACE_CNT] = {'S', 'V', 'G', 'D'};
|
||||
const int MAX_HP[RACE_CNT] = {125, INF, 110, 150, 150};
|
||||
const int STARTING_HP[RACE_CNT] = {125, 50, 110, 150, 150};
|
||||
const int STARTING_ATK[RACE_CNT] = {25, 25, 15, 25, 20};
|
||||
const int STARTING_DEF[RACE_CNT] = {25, 25, 20, 15, 20};
|
||||
const char CHARACTER_REP[RACE_CNT] = {'S', 'V', 'G', 'd', 'D'};
|
||||
|
||||
const int POTION_TYPE_CNT = 6;
|
||||
const int DEFAULT_POTION_TYPE_CNT = 6;
|
||||
enum potion_type {restore_health = 0, boost_atk, boost_def,
|
||||
poison_health, wound_atk, wound_def
|
||||
};
|
||||
@ -94,6 +96,7 @@ const feature FEATURE_IN_FILE = 1 << 9;
|
||||
const feature FEATURE_OUT_FILE = 1 << 10;
|
||||
const feature FEATURE_EXTRA_STUFF = 1 << 11;
|
||||
const feature FEATURE_EXTRA_LEVELS = 1 << 12;
|
||||
const feature FEATURE_COLORFUL = 1 << 13;
|
||||
|
||||
const feature FEATURE_PANIC_SEED = 1 << 27;
|
||||
const feature FEATURE_PANIC_FILE = 1 << 28;
|
||||
@ -109,4 +112,9 @@ const int COLOR_BLACK_ON_WHITE = 8;
|
||||
typedef std::vector<position> position_list;
|
||||
typedef std::vector<direction> direction_list;
|
||||
|
||||
const int GOLD_SMALL = 1;
|
||||
const int GOLD_NORMAL = 2;
|
||||
const int GOLD_MERCHANT = 4;
|
||||
const int GOLD_DRAGON = 6;
|
||||
|
||||
#endif
|
||||
|
@ -2,9 +2,8 @@
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
goblin::goblin(RNG *rng, const position_list &available_positions):
|
||||
character{rng, race::rshade} {
|
||||
pos = available_positions[rng->rand_under(available_positions.size())];
|
||||
goblin::goblin(RNG *rng, const position &pos):
|
||||
character{rng, race::rshade, pos} {
|
||||
gold = 0;
|
||||
hostile = true;
|
||||
}
|
||||
@ -13,8 +12,8 @@ result goblin::attack(const direction dir, character_list &chlist) {
|
||||
position tmp{pos + MOVE[dir]};
|
||||
|
||||
for (auto &ch : chlist)
|
||||
if (tmp == ch.get_position()) {
|
||||
auto res = ch.get_hit(race, ATK, base_hit_rate);
|
||||
if (tmp == ch->get_position()) {
|
||||
auto res = ch->get_hit(race, ATK, base_hit_rate);
|
||||
|
||||
if (res == result::died) {
|
||||
gold += GAIN_GOLD;
|
||||
|
@ -2,12 +2,10 @@
|
||||
#define __GOBLIN_H__
|
||||
#include "characters.h"
|
||||
|
||||
const int GAIN_GOLD = 5;
|
||||
|
||||
class goblin final: public character {
|
||||
static const int GAIN_GOLD = 5;
|
||||
public:
|
||||
goblin(RNG *rng,
|
||||
const position_list &available_positions);
|
||||
goblin(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,
|
||||
|
19
src/gold.h
19
src/gold.h
@ -2,7 +2,9 @@
|
||||
#define __GOLD_H__
|
||||
|
||||
#include <vector>
|
||||
#include "constants.h"
|
||||
#include "position.h"
|
||||
#include "rng.h"
|
||||
|
||||
struct gold {
|
||||
int amount;
|
||||
@ -11,4 +13,21 @@ 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
42
src/level.h
42
src/level.h
@ -2,30 +2,56 @@
|
||||
#define __LEVEL_H__
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "display.h"
|
||||
#include "characters.h"
|
||||
#include "potion.h"
|
||||
#include "enemies.h"
|
||||
#include "potions.h"
|
||||
#include "constants.h"
|
||||
#include "gold.h"
|
||||
#include "map.h"
|
||||
|
||||
class level {
|
||||
private:
|
||||
static const int MAX_POTION_CNT = 15;
|
||||
static const int MAX_ENEMIE_CNT = 30;
|
||||
static const int MIN_POTION_CNT = 10;
|
||||
static const int MIN_ENEMIE_CNT = 20;
|
||||
static const int GOLD_CNT = 10;
|
||||
|
||||
const feature enabled_features;
|
||||
game_map map;
|
||||
const character &player;
|
||||
character *player;
|
||||
std::vector<std::unique_ptr<character>>pchlist;
|
||||
std::vector<std::unique_ptr<potion>>pplist;
|
||||
character_list chlist;
|
||||
potion_list plist;
|
||||
gold_list glist;
|
||||
public:
|
||||
// randomly generate a map
|
||||
level(const character &player);
|
||||
level(character *player, RNG *rng, const feature enabled_features);
|
||||
// read map from a string
|
||||
level(const std::string &map_data, const character &player);
|
||||
void print(display &out) const;
|
||||
void run();
|
||||
position_list get_available_positions() const;
|
||||
level(const std::string &map_data, character *player, RNG *rng,
|
||||
const feature enabled_features);
|
||||
void print(display *out) const;
|
||||
|
||||
bool is_available(const position &pos) const;
|
||||
position_list get_available_around(const position &pos) const;
|
||||
position get_up_stairs() const;
|
||||
position get_down_stairs() const;
|
||||
|
||||
// you can delete the pointers to the stuff
|
||||
character_list &get_chlist();
|
||||
potion_list &get_plist();
|
||||
gold_list &get_glist();
|
||||
private:
|
||||
// every gen will delete the positions in tiles
|
||||
void gen_potions(RNG *rng, std::vector<position_list> &tiles);
|
||||
void gen_gold(RNG *rng, std::vector<position_list> &tiles);
|
||||
void gen_enemies(RNG *rng, std::vector<position_list> &tiles);
|
||||
|
||||
position get_rand_pos(RNG *rng, std::vector<position_list> &tiles);
|
||||
gold_list dragon_hoard();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
91
src/map.cc
91
src/map.cc
@ -1,11 +1,10 @@
|
||||
#include "map.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
game_map::game_map(RNG *rng, const feature enabled_features):
|
||||
game_map::game_map(character *player, RNG *rng, const feature enabled_features):
|
||||
enabled_features{enabled_features} {
|
||||
map.reserve(MAP_HEIGHT * MAP_WIDTH);
|
||||
|
||||
@ -26,21 +25,40 @@ game_map::game_map(RNG *rng, const feature enabled_features):
|
||||
|
||||
gen_path(layer_data, rng);
|
||||
|
||||
for (std::size_t i = 0; i < map.size(); ++i)
|
||||
if (map[i] >= 0 && map[i] < MAX_ROOM_CNT)
|
||||
empty_spots.push_back(remap_index(i));
|
||||
|
||||
down_stairs = rng->get_rand_in_vector(empty_spots);
|
||||
rooms_tile_list.reserve(room_data.size());
|
||||
|
||||
for (size_t i = 0; i < room_data.size(); ++i)
|
||||
rooms_tile_list.push_back({});
|
||||
|
||||
for (size_t i = 0; i < map.size(); ++i)
|
||||
if (map[i] >= 0 && map[i] < MAX_ROOM_CNT)
|
||||
rooms_tile_list[map[i]].push_back(remap_index(i));
|
||||
|
||||
for (size_t i = 0; i < rooms_tile_list.size(); ++i)
|
||||
rooms_tile_list[i].shrink_to_fit();
|
||||
|
||||
rooms_tile_list.shrink_to_fit();
|
||||
|
||||
int player_room = rng->rand_under(room_data.size());
|
||||
player->set_position(rng->get_rand_in_vector(rooms_tile_list[player_room]));
|
||||
|
||||
gen_stairs(player_room, rng);
|
||||
}
|
||||
|
||||
void game_map::gen_stairs(int player_room, RNG *rng) {
|
||||
down_stairs = rng->get_rand_in_vector(rooms_tile_list[
|
||||
rng->exclude_middle(0, room_data.size(), player_room)]);
|
||||
|
||||
if (enabled_features & FEATURE_REVISIT) {
|
||||
auto tmp = remove_from_list(empty_spots, down_stairs);
|
||||
up_stairs = rng->get_rand_in_vector(tmp);
|
||||
up_stairs = rng->get_rand_in_vector(rooms_tile_list[player_room]);
|
||||
|
||||
map[remap_position(up_stairs)] = '<';
|
||||
map[remap_position(down_stairs)] = '>';
|
||||
} else {
|
||||
map[remap_position(down_stairs)] = '\\';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
position game_map::random_size(int min_width, int min_height,
|
||||
@ -50,11 +68,15 @@ position game_map::random_size(int min_width, int min_height,
|
||||
rng->rand_between(min_height, max_height + 1)};
|
||||
}
|
||||
|
||||
game_map::game_map(const std::string &map_data,
|
||||
game_map::game_map(character *player, const std::string &map_data,
|
||||
RNG *rng, const feature enabled_features):
|
||||
enabled_features{enabled_features} {
|
||||
int map_size = MAP_HEIGHT * MAP_WIDTH;
|
||||
map.reserve(map_size);
|
||||
rooms_tile_list.reserve(MAX_ROOM_CNT);
|
||||
|
||||
for (int i = 0; i < MAX_ROOM_CNT; ++i)
|
||||
rooms_tile_list.push_back({});
|
||||
|
||||
int max_room_num = 0;
|
||||
|
||||
@ -67,24 +89,17 @@ game_map::game_map(const std::string &map_data,
|
||||
}
|
||||
|
||||
if (map_data[i] >= '0' && map_data[i] <= '9')
|
||||
empty_spots.push_back(remap_index(i));
|
||||
}
|
||||
|
||||
down_stairs = rng->get_rand_in_vector(empty_spots);
|
||||
|
||||
|
||||
if (enabled_features & FEATURE_REVISIT) {
|
||||
auto tmp = remove_from_list(empty_spots, down_stairs);
|
||||
up_stairs = rng->get_rand_in_vector(tmp);
|
||||
|
||||
map[remap_position(up_stairs)] = '<';
|
||||
map[remap_position(down_stairs)] = '>';
|
||||
} else {
|
||||
map[remap_position(down_stairs)] = '\\';
|
||||
rooms_tile_list[map_data[i] - '0'].push_back(remap_index(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i <= max_room_num; ++i)
|
||||
room_data.push_back({0, 0, 0, 0});
|
||||
|
||||
int player_room = rng->rand_under(room_data.size());
|
||||
player->set_position(rng->get_rand_in_vector(rooms_tile_list[player_room]));
|
||||
|
||||
gen_stairs(player_room, rng);
|
||||
|
||||
}
|
||||
|
||||
bool game_map::is_available(const position &pos) const {
|
||||
@ -113,6 +128,14 @@ void game_map::print(display *out) const {
|
||||
map[i] == '<' ? COLOR_PAIR(COLOR_BLUE) : A_NORMAL);
|
||||
}
|
||||
|
||||
int game_map::which_room(const position &pos) const {
|
||||
if (pos.y > MAP_HEIGHT || pos.x > MAP_WIDTH || pos.x < 0 || pos.y < 0)
|
||||
return -1;
|
||||
|
||||
char tmp = map[remap_position(pos)];
|
||||
return tmp < MAX_ROOM_CNT ? tmp : -1;
|
||||
}
|
||||
|
||||
position game_map::get_up_stairs() const {
|
||||
return up_stairs;
|
||||
}
|
||||
@ -130,29 +153,11 @@ int game_map::get_down_stairs_room() const {
|
||||
}
|
||||
|
||||
position_list game_map::get_room_list(int idx) const {
|
||||
position_list result;
|
||||
|
||||
for (size_t i = 0; i < map.size(); ++i) {
|
||||
if (map[i] == idx)
|
||||
result.push_back(remap_index(i));
|
||||
}
|
||||
|
||||
result.shrink_to_fit();
|
||||
return result;
|
||||
return rooms_tile_list[idx];
|
||||
}
|
||||
|
||||
std::vector<position_list> game_map::get_room_list() const {
|
||||
std::vector<position_list> result;
|
||||
result.reserve(room_data.size());
|
||||
|
||||
for (size_t i = 0; i < room_data.size(); ++i)
|
||||
result.push_back({});
|
||||
|
||||
for (size_t i = 0; i < map.size(); ++i)
|
||||
if (map[i] >= 0 && map[i] < MAX_ROOM_CNT)
|
||||
result[map[i]].push_back(remap_index(i));
|
||||
|
||||
return result;
|
||||
return rooms_tile_list;
|
||||
}
|
||||
|
||||
std::vector<std::pair<position, int>> game_map::gen_room_dims(RNG *rng) {
|
||||
|
@ -1,68 +0,0 @@
|
||||
#include "map.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
game_map::game_map(int lvl) {
|
||||
level = lvl;
|
||||
// TODO: randomly generate a map
|
||||
}
|
||||
|
||||
game_map::game_map(const std::string &map_data, int lvl) {
|
||||
level = lvl;
|
||||
std::istringstream iss{map_data};
|
||||
|
||||
std::string line;
|
||||
|
||||
for (int i = 0; i < MAP_HEIGHT; ++i) {
|
||||
getline(iss, line);
|
||||
map[i] = line;
|
||||
}
|
||||
}
|
||||
|
||||
game_map::~game_map() {}
|
||||
|
||||
int game_map::get_level() const {
|
||||
return this->level;
|
||||
}
|
||||
|
||||
std::vector<position> game_map::get_available_positions() const {
|
||||
std::vector<position> result;
|
||||
|
||||
for (int line = 0; line < MAP_HEIGHT; ++line)
|
||||
for (int x = 0; x < MAP_WIDTH; ++x)
|
||||
if (map[line][x] == '.' ||
|
||||
map[line][x] == '#' ||
|
||||
map[line][x] == '+')
|
||||
result.push_back(position{x, line});
|
||||
return result;
|
||||
}
|
||||
|
||||
void game_map::print() const {
|
||||
|
||||
// TODO: write a print function using ncurses
|
||||
}
|
||||
|
||||
void game_map::print(display &display) const {
|
||||
for (int i = 0; i < MAP_HEIGHT; ++i)
|
||||
display.print_str(position{0, i}, map[i]);
|
||||
}
|
||||
|
||||
void game_map::apply_potion(character *who, const stat_name statn,
|
||||
const int amount) {
|
||||
effects.push_back(effect{who, statn, amount});
|
||||
who->apply_buff(statn, amount);
|
||||
}
|
||||
|
||||
void game_map::enter_level(character *who) {
|
||||
for (auto eff : effects)
|
||||
if (eff.who == who)
|
||||
who->apply_buff(eff.statn, eff.amount);
|
||||
}
|
||||
|
||||
void game_map::leave_level(character *who) {
|
||||
who->set_ATK(STARTING_ATK[who->get_race()]);
|
||||
who->set_DEF(STARTING_DEF[who->get_race()]);
|
||||
}
|
11
src/map.h
11
src/map.h
@ -8,6 +8,7 @@
|
||||
#include "position.h"
|
||||
#include "rng.h"
|
||||
#include "fraction.h"
|
||||
#include "characters.h"
|
||||
|
||||
class game_map final {
|
||||
private:
|
||||
@ -26,10 +27,9 @@ private:
|
||||
|
||||
const feature enabled_features;
|
||||
std::vector<char> map;
|
||||
// IMPORTANT: keep empty_spots ordered
|
||||
position_list empty_spots;
|
||||
position up_stairs;
|
||||
position down_stairs;
|
||||
std::vector<position_list> rooms_tile_list;
|
||||
public:
|
||||
struct room {
|
||||
int top;
|
||||
@ -51,13 +51,14 @@ public:
|
||||
}
|
||||
};
|
||||
// randomly generate a map
|
||||
game_map(RNG *rng, const feature enabled_features);
|
||||
game_map(character *player, RNG *rng, const feature enabled_features);
|
||||
// read map from a string
|
||||
game_map(const std::string &map_data, RNG *rng,
|
||||
game_map(character *player, const std::string &map_data, RNG *rng,
|
||||
const feature enabled_features);
|
||||
|
||||
bool is_available(const position &pos) const;
|
||||
position_list get_available_around(const position &pos) const;
|
||||
int which_room(const position &pos) const;
|
||||
|
||||
position_list get_room_list(int idx) const;
|
||||
std::vector<position_list> get_room_list() const;
|
||||
@ -115,6 +116,8 @@ private:
|
||||
void connect(position s, position t);
|
||||
room hit_room(const position &a);
|
||||
bool hit_room(const position &a, const room &r);
|
||||
|
||||
void gen_stairs(int player_room, RNG *rng);
|
||||
};
|
||||
|
||||
const std::string default_map =
|
||||
|
@ -65,16 +65,12 @@ std::vector<position> remove_from_list(const std::vector<position>
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<position> remove_from_list(const std::vector<position>
|
||||
&sorted_positions,
|
||||
position &excluded) {
|
||||
|
||||
std::vector<position> result{sorted_positions.size() - 1};
|
||||
|
||||
for (auto src : sorted_positions) {
|
||||
if (src != excluded)
|
||||
result.push_back(src);
|
||||
}
|
||||
|
||||
return result;
|
||||
void remove_from_list(std::vector<position>
|
||||
&positions,
|
||||
position &excluded) {
|
||||
for (auto i = positions.begin(); i != positions.end(); ++i)
|
||||
if (*i == excluded) {
|
||||
positions.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ std::size_t find(const std::vector<position> &sorted_list,
|
||||
std::vector<position> remove_from_list(const std::vector<position>
|
||||
&sorted_positions,
|
||||
std::vector<position> excluded);
|
||||
std::vector<position> remove_from_list(const std::vector<position>
|
||||
&sorted_positions,
|
||||
position &excluded);
|
||||
void remove_from_list(std::vector<position> &sorted_positions,
|
||||
position &excluded);
|
||||
#endif
|
||||
|
@ -40,3 +40,7 @@ potion &potion::operator=(potion &&p) {
|
||||
pos = p.pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void potion::print(display *out, bool color) {
|
||||
out->print_char(pos, 'P');
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
#include "constants.h"
|
||||
#include "fraction.h"
|
||||
#include "display.h"
|
||||
|
||||
// IMPORTANT: pop all potions of duration == 0, and when entering a
|
||||
// new level, pop all potions of duration == -1
|
||||
@ -31,6 +32,8 @@ public:
|
||||
int get_duration() const;
|
||||
position get_pos() const;
|
||||
void set_pos(const position &npos);
|
||||
|
||||
virtual void print(display *out, bool color = false);
|
||||
};
|
||||
|
||||
typedef std::vector<potion *> potion_list;
|
||||
|
@ -4,5 +4,6 @@
|
||||
#include "shade.h"
|
||||
#include "goblin.h"
|
||||
#include "vampire.h"
|
||||
#include "dragon.h"
|
||||
|
||||
#endif
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
restore_health::restore_health():
|
||||
potion{potion_type::restore_health, -1, {0, 0}} {}
|
||||
restore_health::restore_health(const position &pos):
|
||||
potion{potion_type::restore_health, -1, pos} {}
|
||||
|
||||
void restore_health::apply(const enum race &race, int &HP, int &ATK, int &DEF,
|
||||
fraction &base_hit_rate) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
class restore_health final: public potion {
|
||||
public:
|
||||
restore_health();
|
||||
restore_health(const position &pos);
|
||||
void apply(const enum race &race, int &HP, int &ATK, int &DEF,
|
||||
fraction &base_hit_rate) override;
|
||||
int get_priority() const override;
|
||||
|
33
src/rng.cc
33
src/rng.cc
@ -33,9 +33,36 @@ int RNG::get_curr_rand_num() const {
|
||||
}
|
||||
|
||||
bool RNG::trial(const fraction &psuccess) {
|
||||
return (rand() % psuccess.denominator) < psuccess.numerator;
|
||||
return ((curr_rand_num = rand()) % psuccess.denominator) <
|
||||
psuccess.numerator;
|
||||
}
|
||||
|
||||
bool RNG::coin_flip() const {
|
||||
return rand() % 2;
|
||||
bool RNG::coin_flip() {
|
||||
return (curr_rand_num = rand()) % 2;
|
||||
}
|
||||
|
||||
int RNG::exclude_middle(const int lower_bound, const int upper_bound,
|
||||
const int excluded) {
|
||||
curr_rand_num = rand();
|
||||
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()];
|
||||
}
|
||||
|
11
src/rng.h
11
src/rng.h
@ -28,13 +28,14 @@ public:
|
||||
|
||||
bool trial(const fraction &psuccess);
|
||||
|
||||
bool coin_flip() const;
|
||||
bool coin_flip();
|
||||
|
||||
template<class T> T &get_rand_in_vector(std::vector<T> &vec) {
|
||||
curr_rand_num = rand();
|
||||
int exclude_middle(const int lower_bound, const int upper_bound,
|
||||
const int excluded);
|
||||
|
||||
return vec[curr_rand_num % vec.size()];
|
||||
}
|
||||
template<class T> T rand_exclude(std::vector<T> &vec, T &target);
|
||||
|
||||
template<class T> T get_rand_in_vector(std::vector<T> &vec);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3,9 +3,8 @@
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
shade::shade(RNG *rng, const position_list &available_positions):
|
||||
character{rng, race::rshade} {
|
||||
pos = available_positions[rng->rand_under(available_positions.size())];
|
||||
shade::shade(RNG *rng, const position &pos):
|
||||
character{rng, race::rshade, pos} {
|
||||
gold = 0;
|
||||
hostile = true;
|
||||
}
|
||||
@ -14,8 +13,8 @@ result shade::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);
|
||||
if (tmp == ch->get_position()) {
|
||||
return ch->get_hit(race, ATK, base_hit_rate);
|
||||
}
|
||||
|
||||
return result::fine;
|
||||
|
@ -5,8 +5,7 @@
|
||||
|
||||
class shade final: public character {
|
||||
public:
|
||||
shade(RNG *rng, const position_list
|
||||
&available_positions); // spawn at a random place
|
||||
shade(RNG *rng, const position &pos); // spawn at a random place
|
||||
virtual result attack(const direction dir,
|
||||
character_list &chlist) override;
|
||||
virtual result get_hit(const enum race &race, const int atk,
|
||||
|
@ -2,9 +2,8 @@
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
vampire::vampire(RNG *rng, const position_list &available_positions):
|
||||
character{rng, race::rshade} {
|
||||
pos = available_positions[rng->rand_under(available_positions.size())];
|
||||
vampire::vampire(RNG *rng, const position &pos):
|
||||
character{rng, race::rshade, pos} {
|
||||
gold = 0;
|
||||
hostile = true;
|
||||
}
|
||||
@ -13,8 +12,8 @@ result vampire::attack(const direction dir, character_list &chlist) {
|
||||
position tmp{pos + MOVE[dir]};
|
||||
|
||||
for (auto &ch : chlist)
|
||||
if (tmp == ch.get_position()) {
|
||||
auto res = ch.get_hit(race, ATK, base_hit_rate);
|
||||
if (tmp == ch->get_position()) {
|
||||
auto res = ch->get_hit(race, ATK, base_hit_rate);
|
||||
|
||||
if (res != result::miss) {
|
||||
HP += GAIN_HP;
|
||||
|
@ -6,8 +6,7 @@ const int GAIN_HP = 5;
|
||||
|
||||
class vampire final: public character {
|
||||
public:
|
||||
vampire(RNG *rng,
|
||||
const position_list &available_positions);
|
||||
vampire(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,
|
||||
|
Reference in New Issue
Block a user