diff --git a/src/characters.cc b/src/characters.cc index 358531f..e85f07e 100644 --- a/src/characters.cc +++ b/src/characters.cc @@ -154,7 +154,7 @@ position_list remove_from_list(const position_list &sorted_positions, // IMPORTANT: remember to check if player is on the stairs result character::move(const direction dir, - const position_list &available_positions) { + const position_list &available_positions) { if (find(available_positions, pos + MOVE[dir]) != available_positions.size()) { pos += MOVE[dir]; @@ -165,12 +165,12 @@ result character::move(const direction dir, } result character::move_or_attack(const direction dir, - const position_list &available_positions, - const character_list &chlist) { - auto res = this->move(dir,available_positions); + const position_list &available_positions, + const character_list &chlist) { + auto res = this->move(dir, available_positions); - if(res != result::fine) - return res; + if (res != result::fine) + return res; - return this->attack(dir,chlist); + return this->attack(dir, chlist); } diff --git a/src/characters.cc.orig b/src/characters.cc.orig new file mode 100644 index 0000000..358531f --- /dev/null +++ b/src/characters.cc.orig @@ -0,0 +1,176 @@ +#include "characters.h" + +#include + +character::character(const enum race &nrace): + race{nrace}, HP{STARTING_HP[race]}, + ATK{STARTING_ATK[race]}, DEF{STARTING_DEF[race]} {} + +character::~character() {} + +enum race character::get_race() const { + return race; +} + +position character::get_position() const { + return pos; +} + +int character::get_HP() const { + return HP; +} + +int character::get_ATK() const { + return ATK; +} + +int character::get_DEF() const { + return DEF; +} + +int character::get_gold() const { + return gold; +} + +float character::get_hitrate() const { + return base_hitrate; +} + +bool character::is_hostile() const { + return hostile; +} + +void character::set_position(const position &npos) { + pos = npos; +} + +void character::set_HP(const int nHP) { + HP = nHP; +} + +void character::set_ATK(const int nATK) { + ATK = nATK; +} + +void character::set_DEF(const int nDEF) { + DEF = nDEF; +} + +void character::set_gold(const int ngold) { + gold = ngold; +} + +void character::set_hitrate(const float nhitrate) { + base_hitrate = nhitrate; +} + +void character::set_hostile(const bool is_hostile) { + hostile = is_hostile; +} + +void character::apply_buff(const stat_name statn, const int amount) { + // TODO: add checks for bounds + switch (statn) { + case stat_name::HP: + HP += amount; + break; + + case stat_name::ATK: + ATK += amount; + break; + + case stat_name::DEF: + DEF += amount; + break; + + case stat_name::hostile: { + if (amount > 0) + hostile = true; + else + hostile = false; + + break; + } + } +} + +character_list::character_list(): + layer{layer_num::characters} {} + +void character_list::print() const { + // TODO: implement it using ncurses +} + +void character_list::print(display &display) const { + for (auto &ch : characters) + display.print_position(ch->get_position(), + CHARACTER_REP[ch->get_race()]); +} + +std::vector>::const_iterator character_list::begin() +const { + return characters.begin(); +} + +std::vector>::const_iterator character_list::end() +const { + return characters.end(); +} + +direction_list character::moveable(const position_list &available_positions) +const { + direction_list result; + + for (int i = 0; i < DIRECTION_CNT; ++i) + if (find(available_positions, pos + MOVE[i]) + != available_positions.size()) + result.push_back((direction)i); + + return result; +} + +result character::apply(direction &dir, const potion_list &potions) { + // TODO: implement this after implementing potions + 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 +result character::move(const direction dir, + const position_list &available_positions) { + if (find(available_positions, pos + MOVE[dir]) + != available_positions.size()) { + pos += MOVE[dir]; + return result::moved; + } + + return result::fine; +} + +result character::move_or_attack(const direction dir, + const position_list &available_positions, + const character_list &chlist) { + auto res = this->move(dir,available_positions); + + if(res != result::fine) + return res; + + return this->attack(dir,chlist); +} diff --git a/src/constants.h b/src/constants.h index 5ec97ec..8b732a9 100644 --- a/src/constants.h +++ b/src/constants.h @@ -14,6 +14,8 @@ enum error {none}; // TODO: update result to include subject enum result {fine, died, go_down, hit, moved}; +enum game_status {terminated, main_menu, in_game, options}; + enum stat_name {HP, ATK, DEF, hostile}; const int LAYER_CNT = 4; // TODO: update as you go @@ -60,6 +62,8 @@ const feature FEATURE_ENEMIES_CHASE = 1 << 2; const feature FEATURE_INVENTORY = 1 << 3; const feature FEATURE_THROW = 1 << 4; const feature FEATURE_REVISIT = 1 << 5; +const feature FEATURE_LOG = 1 << 6; +const feature FEATURE_SAVE = 1 << 7; typedef std::vector position_list; typedef std::vector direction_list; diff --git a/src/constants.h.orig b/src/constants.h.orig new file mode 100644 index 0000000..0c22ffd --- /dev/null +++ b/src/constants.h.orig @@ -0,0 +1,71 @@ +// TODO: Consider moving the contents of this header to their relevant +// headers + +#ifndef __CONSTANTS_H__ +#define __CONSTANTS_H__ +#include +#include "position.h" + +// IMPORTANT: added END to the end of all valued enums so that you can +// iterate over them + +enum error {none}; + +// TODO: update result to include subject +enum result {fine, died, go_down, hit, moved}; + +enum game_status{terminated, main_menu, in_game, options}; + +enum stat_name {HP, ATK, DEF, hostile}; + +const int LAYER_CNT = 4; // TODO: update as you go +enum layer_num {map = 0, objects, characters, shop}; + +const int RACE_CNT = 2; // TODO: update as you go + +enum race {unknown = 0, rshade /* TODO: fill out the other races (including enemies) */}; + +// TODO: fill out the other races (including enemies) +const int MAX_HP[RACE_CNT] = {0, 125}; +const int STARTING_HP[RACE_CNT] = {0, 125}; +const int STARTING_ATK[RACE_CNT] = {0, 25}; +const int STARTING_DEF[RACE_CNT] = {0, 25}; +const char CHARACTER_REP[RACE_CNT] = {'@', 'S'}; + +const int DIRECTION_CNT = 8; +// IMPORTANT: east is positive for x and SOUTH is positive for y +// initializes all directions to an int +enum direction {east = 0, west, north, south, northeast, + northwest, southeast, southest + }; + +const position MOVE[DIRECTION_CNT] = { + {1, 0}, {-1, 0}, {0, -1}, {0, 1}, + {1, -1}, {-1, -1}, {1, 1}, {-1, 1} +}; + +const int MAP_HEIGHT = 25; +const int MAP_WIDTH = 79; +const int DISPLAY_HEIGHT = 30; +const int DISPLAY_WIDTH = 79; + +// TODO: list all extra features +// using constants to keep track of features +// method: features: FEATURE_XXX | FEATURE_YYY +// That is: use bit manipulation +// check if feature is enabled: +// features & FEATURE_XXX +typedef unsigned int feature; // can extend to unsigned long (long) if needed +const feature FEATURE_NCURSES = 1 << 0; +const feature FEATURE_RAND_MAP = 1 << 1; +const feature FEATURE_ENEMIES_CHASE = 1 << 2; +const feature FEATURE_INVENTORY = 1 << 3; +const feature FEATURE_THROW = 1 << 4; +const feature FEATURE_REVISIT = 1 << 5; +const feature FEATURE_LOG = 1 << 6; +const feature FEATURE_SAVE = 1 << 7; + +typedef std::vector position_list; +typedef std::vector direction_list; + +#endif diff --git a/src/cursor.h b/src/cursor.h new file mode 100644 index 0000000..bf04ec4 --- /dev/null +++ b/src/cursor.h @@ -0,0 +1,7 @@ +#ifndef __CURSOR_H__ +#define __CURSOR_H__ +#include + +class cursor; + +#endif diff --git a/src/display.h b/src/display.h index 8d9d36f..fe49468 100644 --- a/src/display.h +++ b/src/display.h @@ -11,18 +11,23 @@ #include #include "position.h" #include "constants.h" +#include "cursor.h" class display final { private: std::vector contents; + cursor &curs; public: display(); + display(cursor &s); void clear(); // use this instead of overloading for clarity void print(std::ostream &out) const; void print_line(const std::string &line, const int linenum); + void render() const ; + // will override any character that was there void print_position(const position &pos, const char ch); }; diff --git a/src/display.h.orig b/src/display.h.orig new file mode 100644 index 0000000..17aa02b --- /dev/null +++ b/src/display.h.orig @@ -0,0 +1,35 @@ +/* + * CS 246 Final Project + * File: display.h + * Purpose: handles map functionality + */ + +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ +#include +#include +#include +#include "position.h" +#include "constants.h" +#include "cursor.h" + +class display final { +private: + std::vector contents; + cursor &curs; +public: + display(); + display(cursor &s); + + void clear(); + // use this instead of overloading for clarity + void print(std::ostream &out) const; + void print_line(const std::string &line, const int linenum); + + void render() const ; + + // will override any character that was there + void print_position(const position &pos, const char ch); +}; + +#endif diff --git a/src/game.h b/src/game.h index b3907ec..d7854f4 100644 --- a/src/game.h +++ b/src/game.h @@ -3,21 +3,22 @@ #include #include #include "constants.h" +#include "display.h" #include "rng.h" -#include "spell.h" // this is for ncurses #include "characters.h" #include "map.h" +#include "log.h" class game final { private: + display &d; feature features; std::unique_ptr rng; - std::unique_ptr spell; std::unique_ptr player; - std::vector levels; + std::vector levels; public: - game(int argc = 0, char **argv = nullptr); - void run(); + game(display &new_display, int argc, char **argv); + game_status run(); }; #endif diff --git a/src/game.h.orig b/src/game.h.orig new file mode 100644 index 0000000..bf2618f --- /dev/null +++ b/src/game.h.orig @@ -0,0 +1,24 @@ +#ifndef __GAME_H__ +#define __GAME_H__ +#include +#include +#include "constants.h" +#include "display.h" +#include "rng.h" +#include "characters.h" +#include "map.h" +#include "log.h" + +class game final { +private: + display &d; + feature features; + std::unique_ptr rng; + std::unique_ptr player; + std::vector levels; +public: + game(display &new_display, int argc, char **argv); + game_status run(); +}; + +#endif diff --git a/src/level.h b/src/level.h new file mode 100644 index 0000000..dff3881 --- /dev/null +++ b/src/level.h @@ -0,0 +1,6 @@ +#ifndef __LEVEL_H__ +#define __LEVEL_H__ + +class level; + +#endif diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..a5eede2 --- /dev/null +++ b/src/log.h @@ -0,0 +1,6 @@ +#ifndef __LOG_H__ +#define __LOG_H__ + +class log; + +#endif diff --git a/src/main.cc b/src/main.cc index 5e5ea22..b05715f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,52 +1,23 @@ -#include -#include -#include -#include -#include -#include -#include -#include "map.h" -#include "races.h" +#include "game.h" +#include "cursor.h" #include "display.h" -#include "rng.h" -using namespace std; +// The way things are designed to work: +// 1. initializes a new ncurses wrapper c +// Note: This is done the first thing in main because ncurses +// are from procedural programming and may break otherwise (unlikely) +// 2. bind c to a new display c (that handles all output) +// 3. bind d to g for graphics -RNG rng;//{(unsigned int)time(0)}; +int main(int argc, char **argv) { + cursor c; + // binds a ncurses cursor to display + display d(c); + // binds display to the game + game g(d, argc, argv); -int main() { - display display; - unique_ptr mmap(new game_map{default_map, 0}); - unique_ptr - player(new shade{mmap->get_available_positions()}); + while (g.run() != game_status::terminated) + d.render(); - for (char ch = ' '; ch != 'q'; ch = getchar()) { - //system("CLS"); - cout << "\033[2J"; - display.clear(); - mmap->print(display); - display.print_position(player->get_position(), '@'); - display.print(cout); - cout << "Command: " << ch << endl; - - auto available_positions = mmap->get_available_positions(); - - switch (ch) { - case 'w': - player->move(direction::north, available_positions); - break; - - case 'a': - player->move(direction::west, available_positions); - break; - - case 's': - player->move(direction::south, available_positions); - break; - - case 'd': - player->move(direction::east, available_positions); - break; - } - } + return 0; } diff --git a/src/main.cc.orig b/src/main.cc.orig new file mode 100644 index 0000000..bf48e3d --- /dev/null +++ b/src/main.cc.orig @@ -0,0 +1,21 @@ +#include "game.h" +#include "cursor.h" +#include "display.h" + +// The way things are designed to work: +// 1. initializes a new ncurses wrapper c +// Note: This is done the first thing in main because ncurses +// are from procedural programming and may break otherwise (unlikely) +// 2. bind c to a new display c (that handles all output) +// 3. bind d to g for graphics + +int main(int argc, char **argv) { + cursor c; + // binds a ncurses cursor to display + display d(c); + // binds display to the game + game g(d,argc, argv); + while(g.run()!=game_status::terminated) + d.render(); + return 0; +} diff --git a/src/position.h b/src/position.h index 9a65a45..6d794a5 100644 --- a/src/position.h +++ b/src/position.h @@ -23,7 +23,7 @@ typedef struct position { bool operator<(const position &other) const; } position; -size_t find(const std::vector &sorted_list, - const position &target); +std::size_t find(const std::vector &sorted_list, + const position &target); #endif diff --git a/src/position.h.orig b/src/position.h.orig new file mode 100644 index 0000000..33ec991 --- /dev/null +++ b/src/position.h.orig @@ -0,0 +1,29 @@ +/* + * CS 246 Final Project + * File: map.h + * Purpose: handles map functionality + */ + +#ifndef __POSITION_H__ +#define __POSITION_H__ +#include + +typedef struct position { + int x; + int y; + + position(); + position(int nx, int ny); + + position operator+(const position &other) const; + position &operator=(const position &other); + position &operator+=(const position &other); + bool operator==(const position &other) const; + bool operator!=(const position &other) const; + bool operator<(const position &other) const; +} position; + +std::size_t find(const std::vector &sorted_list, + const position &target); + +#endif diff --git a/src/test.d b/src/test.d deleted file mode 100644 index 2a41aa7..0000000 --- a/src/test.d +++ /dev/null @@ -1 +0,0 @@ -test.o: test.cc diff --git a/src/test.o b/src/test.o deleted file mode 100644 index 9670de7..0000000 Binary files a/src/test.o and /dev/null differ