WORK IN PROGRESS
TODO: implement random level generation moved exclude from list to position.h distinguished level and map
This commit is contained in:
6
src/cc3k.h
Normal file
6
src/cc3k.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __CC3K_H__
|
||||||
|
#define __CC3K_H__
|
||||||
|
|
||||||
|
class CC3K;
|
||||||
|
|
||||||
|
#endif
|
@ -110,24 +110,6 @@ result character::apply(direction &dir, const potion_list &potions) {
|
|||||||
return result::fine;
|
return result::fine;
|
||||||
}
|
}
|
||||||
|
|
||||||
position_list remove_from_list(const position_list &sorted_positions,
|
|
||||||
position_list excluded) {
|
|
||||||
std::sort(excluded.begin(), excluded.end());
|
|
||||||
|
|
||||||
position_list result{sorted_positions.size() - excluded.size()};
|
|
||||||
|
|
||||||
auto exc = excluded.begin();
|
|
||||||
|
|
||||||
for (auto src : sorted_positions) {
|
|
||||||
if (exc != excluded.end() && src == *exc)
|
|
||||||
++exc;
|
|
||||||
else
|
|
||||||
result.push_back(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPORTANT: remember to check if player is on the stairs
|
// IMPORTANT: remember to check if player is on the stairs
|
||||||
result character::move(const direction dir,
|
result character::move(const direction dir,
|
||||||
const position_list &available_positions) {
|
const position_list &available_positions) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "potion.h"
|
#include "potion.h"
|
||||||
|
#include "gold.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
|
||||||
// #include "inventory.h" // Reserved for later
|
// #include "inventory.h" // Reserved for later
|
||||||
@ -85,11 +86,6 @@ protected:
|
|||||||
bool hostile;
|
bool hostile;
|
||||||
};
|
};
|
||||||
|
|
||||||
// requires: all elements of excluded are in sorted_positions
|
|
||||||
position_list remove_from_list(const position_list &sorted_positions,
|
|
||||||
position_list excluded);
|
|
||||||
|
|
||||||
|
|
||||||
int calc_dmg(const int ATK, const int DEF);
|
int calc_dmg(const int ATK, const int DEF);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -106,6 +106,5 @@ const int COLOR_BLACK_ON_WHITE = 8;
|
|||||||
|
|
||||||
typedef std::vector<position> position_list;
|
typedef std::vector<position> position_list;
|
||||||
typedef std::vector<direction> direction_list;
|
typedef std::vector<direction> direction_list;
|
||||||
typedef std::vector<int> gold_list;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,6 +17,8 @@ private:
|
|||||||
display &out;
|
display &out;
|
||||||
logger &log;
|
logger &log;
|
||||||
RNG &rng;
|
RNG &rng;
|
||||||
|
|
||||||
|
// IMPORTANT: during player generation,
|
||||||
std::unique_ptr<character> player;
|
std::unique_ptr<character> player;
|
||||||
public:
|
public:
|
||||||
game(const feature enabled_features,
|
game(const feature enabled_features,
|
||||||
|
14
src/gold.h
Normal file
14
src/gold.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __GOLD_H__
|
||||||
|
#define __GOLD_H__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "position.h"
|
||||||
|
|
||||||
|
struct gold {
|
||||||
|
int amount;
|
||||||
|
position pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<gold> gold_list;
|
||||||
|
|
||||||
|
#endif
|
27
src/level.h
27
src/level.h
@ -1,6 +1,31 @@
|
|||||||
#ifndef __LEVEL_H__
|
#ifndef __LEVEL_H__
|
||||||
#define __LEVEL_H__
|
#define __LEVEL_H__
|
||||||
|
|
||||||
class level;
|
#include <string>
|
||||||
|
#include "display.h"
|
||||||
|
#include "characters.h"
|
||||||
|
#include "potion.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "gold.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
class level {
|
||||||
|
private:
|
||||||
|
game_map map;
|
||||||
|
const character &player;
|
||||||
|
character_list chlist;
|
||||||
|
potion_list plist;
|
||||||
|
gold_list glist;
|
||||||
|
public:
|
||||||
|
// randomly generate a map
|
||||||
|
level(const character &player);
|
||||||
|
// 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;
|
||||||
|
position get_up_stairs() const;
|
||||||
|
position get_down_stairs() const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "game.h"
|
#include "cc3k.h"
|
||||||
#include "arguments.h"
|
#include "arguments.h"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@ -19,10 +19,12 @@ int main(int argc, char **argv) {
|
|||||||
return RETURN_PANICKED;
|
return RETURN_PANICKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
game game_proc(enabled_features, *in, *out, *log, *rng);
|
CC3K game_proc(enabled_features, *in, *out, *log, *rng);
|
||||||
|
|
||||||
while (game_proc.run() != game_status::terminated)
|
while (game_proc.run() != game_status::terminated) {
|
||||||
out->render();
|
out->render();
|
||||||
|
out->clear();
|
||||||
|
}
|
||||||
|
|
||||||
return RETURN_FINE;
|
return RETURN_FINE;
|
||||||
}
|
}
|
||||||
|
120
src/map.cc
120
src/map.cc
@ -1,68 +1,82 @@
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
|
||||||
#include <sstream>
|
game_map::game_map(RNG &rng, const feature enabled_features):
|
||||||
#include <iostream>
|
enabled_features{enabled_features} {
|
||||||
#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) {
|
game_map::game_map(const std::string &map_data,
|
||||||
level = lvl;
|
RNG &rng, const feature enabled_features):
|
||||||
std::istringstream iss{map_data};
|
enabled_features{enabled_features} {
|
||||||
|
int map_size = MAP_HEIGHT * MAP_WIDTH;
|
||||||
|
map.reserve(map_size);
|
||||||
|
|
||||||
std::string line;
|
for (int i = 0; i < map_size; ++i) {
|
||||||
|
if (map_data[i] >= '0' && map_data[i] <= '9')
|
||||||
|
map.push_back(map_data[i] - '0');
|
||||||
|
else
|
||||||
|
map.push_back(map_data[i]);
|
||||||
|
|
||||||
for (int i = 0; i < MAP_HEIGHT; ++i) {
|
if ((map_data[i] >= '0' && map_data[i] <= '9') ||
|
||||||
getline(iss, line);
|
map_data[i] == '+' || map_data[i] == '#')
|
||||||
map[i] = line;
|
empty_spots.push_back(remap_index(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
down_stairs = rng.get_rand_in_vector(empty_spots);
|
||||||
|
|
||||||
|
|
||||||
|
if (enabled_features | FEATURE_REVISIT) {
|
||||||
|
up_stairs = rng.get_rand_in_vector(
|
||||||
|
remove_from_list(empty_spots, {down_stairs}));
|
||||||
|
map[remap_position(up_stairs)] = '<';
|
||||||
|
map[remap_position(down_stairs)] = '>';
|
||||||
|
} else {
|
||||||
|
map[remap_position(down_stairs)] = '\\';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
game_map::~game_map() {}
|
const position_list game_map::get_available_positions() const {
|
||||||
|
return empty_spots;
|
||||||
int game_map::get_level() const {
|
|
||||||
return this->level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<position> game_map::get_available_positions() const {
|
void game_map::print(display &out) const {
|
||||||
std::vector<position> result;
|
for (std::size_t i = 0; i < map.size(); ++i)
|
||||||
|
out.print_char(remap_index(i), map[i] <= 9 ? '.' : map[i],
|
||||||
|
map[i] == '\\' || map[i] == '>' ||
|
||||||
|
map[i] == '<' ? COLOR_PAIR(COLOR_BLUE) : A_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
position game_map::get_up_stairs() const {
|
||||||
|
return up_stairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
position game_map::get_down_stairs() const {
|
||||||
|
return down_stairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int game_map::get_up_stairs_room() const {
|
||||||
|
return map[remap_position(up_stairs)];
|
||||||
|
}
|
||||||
|
|
||||||
|
int game_map::get_down_stairs_room() const {
|
||||||
|
return map[remap_position(down_stairs)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<position_list>game_map::get_room_list() const {
|
||||||
|
std::vector<position_list> result;
|
||||||
|
result.reserve(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
result.push_back({});
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < map.size(); ++i)
|
||||||
|
if (map[i] <= 9)
|
||||||
|
result[map[i]].push_back(remap_index(i));
|
||||||
|
|
||||||
|
result.shrink_to_fit();
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < result.size(); ++i)
|
||||||
|
result[i].shrink_to_fit();
|
||||||
|
|
||||||
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;
|
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()]);
|
|
||||||
}
|
|
||||||
|
68
src/map.cc.bak
Normal file
68
src/map.cc.bak
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#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()]);
|
||||||
|
}
|
85
src/map.h
85
src/map.h
@ -12,49 +12,70 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "characters.h"
|
#include "characters.h"
|
||||||
|
#include "rng.h"
|
||||||
|
|
||||||
class game_map final {
|
class game_map final {
|
||||||
|
private:
|
||||||
|
const feature enabled_features;
|
||||||
|
std::vector<char> map;
|
||||||
|
// IMPORTANT: keep empty_spots ordered
|
||||||
|
position_list empty_spots;
|
||||||
|
position up_stairs;
|
||||||
|
position down_stairs;
|
||||||
|
int room_cnt;
|
||||||
public:
|
public:
|
||||||
game_map(int lvl = 0); // randomly generate one
|
// randomly generate a map
|
||||||
// initialize using stored data
|
game_map(RNG &rng, const feature enabled_features);
|
||||||
game_map(const std::string &map_data, int lvl);
|
// read map from a string
|
||||||
~game_map(); // placeholder
|
game_map(const std::string &map_data, RNG &rng,
|
||||||
|
const feature enabled_features);
|
||||||
|
|
||||||
int get_level() const;
|
const position_list get_available_positions() const;
|
||||||
|
|
||||||
position_list get_available_positions() const;
|
|
||||||
|
|
||||||
|
const std::vector<position_list> get_room_list() const;
|
||||||
// IMPORTANT: always print a map before anything else
|
// IMPORTANT: always print a map before anything else
|
||||||
|
void print(display &out) const;
|
||||||
|
|
||||||
// prints using ncurses
|
position get_up_stairs() const;
|
||||||
void print() const;
|
position get_down_stairs() const;
|
||||||
|
|
||||||
// prints to a string
|
int get_up_stairs_room() const;
|
||||||
void print(display &display) const;
|
int get_down_stairs_room() const;
|
||||||
|
private:
|
||||||
|
position remap_index(const int idx) const {
|
||||||
|
return {idx % MAP_WIDTH, idx / MAP_HEIGHT};
|
||||||
|
}
|
||||||
|
|
||||||
// This is implemented this way to do two things:
|
int remap_position(const position &pos) const {
|
||||||
// 1. avoid directly accessing heap memory (bonus points)
|
return pos.y * MAP_WIDTH + pos.x;
|
||||||
// 2. make a level revisitable
|
}
|
||||||
void apply_potion(character *who, const stat_name statn, const int amount);
|
|
||||||
|
|
||||||
// just in case you want to retain the potion effects
|
|
||||||
void enter_level(character *who);
|
|
||||||
void leave_level(character *who);
|
|
||||||
public:
|
|
||||||
struct effect {
|
|
||||||
character *who;
|
|
||||||
stat_name statn;
|
|
||||||
int amount;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string map[MAP_HEIGHT];
|
|
||||||
int level;
|
|
||||||
|
|
||||||
// use this to remember every applied potion
|
|
||||||
std::vector<effect> effects;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string default_map =
|
const std::string default_map =
|
||||||
"|-----------------------------------------------------------------------------|\n| |\n| |--------------------------| |-----------------------| |\n| |..........................| |.......................| |\n| |..........................+########+.......................|-------| |\n| |..........................| # |...............................|--| |\n| |..........................| # |..................................|--| |\n| |----------+---------------| # |----+----------------|...............| |\n| # ############# |...............| |\n| # # |-----+------| |...............| |\n| # # |............| |...............| |\n| ################### |............| ######+...............| |\n| # # |............| # |...............| |\n| # # |-----+------| # |--------+------| |\n| |---------+-----------| # # # # |\n| |.....................| # # # |----+------| |\n| |.....................| ######################## |...........| |\n| |.....................| # # |...........| |\n| |.....................| # |------+--------------------|...........| |\n| |.....................| # |.......................................| |\n| |.....................+##########+.......................................| |\n| |.....................| |.......................................| |\n| |---------------------| |---------------------------------------| |\n| |\n|-----------------------------------------------------------------------------|";
|
"|-----------------------------------------------------------------------------|\
|
||||||
|
| |\
|
||||||
|
| |--------------------------| |-----------------------| |\
|
||||||
|
| |11111111111111111111111111| |33333333333333333333333| |\
|
||||||
|
| |11111111111111111111111111+########+33333333333333333333333|-------| |\
|
||||||
|
| |11111111111111111111111111| # |3333333333333333333333333333333|--| |\
|
||||||
|
| |11111111111111111111111111| # |3333333333333333333333333333333333|--| |\
|
||||||
|
| |----------+---------------| # |----+----------------|333333333333333| |\
|
||||||
|
| # ############# |333333333333333| |\
|
||||||
|
| # # |-----+------| |333333333333333| |\
|
||||||
|
| # # |444444444444| |333333333333333| |\
|
||||||
|
| ################### |444444444444| ######+333333333333333| |\
|
||||||
|
| # # |444444444444| # |333333333333333| |\
|
||||||
|
| # # |-----+------| # |--------+------| |\
|
||||||
|
| |---------+-----------| # # # # |\
|
||||||
|
| |222222222222222222222| # # # |----+------| |\
|
||||||
|
| |222222222222222222222| ######################## |00000000000| |\
|
||||||
|
| |222222222222222222222| # # |00000000000| |\
|
||||||
|
| |222222222222222222222| # |------+--------------------|00000000000| |\
|
||||||
|
| |222222222222222222222| # |000000000000000000000000000000000000000| |\
|
||||||
|
| |222222222222222222222+##########+000000000000000000000000000000000000000| |\
|
||||||
|
| |222222222222222222222| |000000000000000000000000000000000000000| |\
|
||||||
|
| |---------------------| |---------------------------------------| |\
|
||||||
|
| |\
|
||||||
|
|-----------------------------------------------------------------------------|";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,3 +43,24 @@ size_t find(const std::vector<position> &sorted_list,
|
|||||||
|
|
||||||
return sorted_list.size();
|
return sorted_list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
std::vector<position> remove_from_list(const std::vector<position>
|
||||||
|
&sorted_positions,
|
||||||
|
std::vector<position> excluded) {
|
||||||
|
std::sort(excluded.begin(), excluded.end());
|
||||||
|
|
||||||
|
std::vector<position> result{sorted_positions.size() - excluded.size()};
|
||||||
|
|
||||||
|
auto exc = excluded.begin();
|
||||||
|
|
||||||
|
for (auto src : sorted_positions) {
|
||||||
|
if (exc != excluded.end() && src == *exc)
|
||||||
|
++exc;
|
||||||
|
else
|
||||||
|
result.push_back(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -26,4 +26,9 @@ typedef struct position {
|
|||||||
std::size_t find(const std::vector<position> &sorted_list,
|
std::size_t find(const std::vector<position> &sorted_list,
|
||||||
const position &target);
|
const position &target);
|
||||||
|
|
||||||
|
// requires: all elements of excluded are in sorted_positions
|
||||||
|
std::vector<position> remove_from_list(const std::vector<position>
|
||||||
|
&sorted_positions,
|
||||||
|
std::vector<position> excluded);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user