diff --git a/src/characters.cc b/src/characters.cc index f610ff9..6178766 100644 --- a/src/characters.cc +++ b/src/characters.cc @@ -33,7 +33,7 @@ int character::get_gold() const { } float character::get_hitrate() const { - return base_hitrate; + return base_hit_rate; } bool character::is_hostile() const { @@ -61,7 +61,7 @@ void character::set_gold(const int ngold) { } void character::set_hitrate(const float nhitrate) { - base_hitrate = nhitrate; + base_hit_rate = nhitrate; } void character::set_hostile(const bool is_hostile) { @@ -174,3 +174,9 @@ result character::move_or_attack(const direction dir, return this->attack(dir, chlist); } + + +int calc_dmg(const int ATK, const int DEF) { + return ceil((100 / (100 + DEF)) * ATK); +} + diff --git a/src/characters.h b/src/characters.h index 9962f7e..a6aaf55 100644 --- a/src/characters.h +++ b/src/characters.h @@ -9,28 +9,21 @@ #include #include #include +#include + #include "constants.h" #include "position.h" #include "layer.h" #include "objects.h" #include "rng.h" + // #include "inventory.h" // Reserved for later class character; // forward declaration extern RNG rng; // Note: player should not be in the character list -class character_list final: public layer { -private: - std::vector> characters; -public: - character_list(); - void print() const; - void print(display &display) const; - - std::vector>::const_iterator begin() const; - std::vector>::const_iterator end() const; -}; +typedef std::vector character_list; class character { public: @@ -45,7 +38,7 @@ public: virtual result move(const direction dir, const position_list &available_positions); virtual result attack(const direction dir, - const character_list &chlist) = 0; + character_list &chlist) = 0; virtual result move_or_attack(const direction dir, const position_list &available_positions, const character_list &chlist); @@ -87,7 +80,7 @@ protected: int gold; // characters spawn with gold // inventory inventory; // Reserved - float base_hitrate; // requires: between [0,1] + float base_hit_rate; // requires: between [0,1] bool hostile; }; @@ -96,4 +89,7 @@ protected: position_list remove_from_list(const position_list &sorted_positions, position_list excluded); + +int calc_dmg(const int ATK, const int DEF); + #endif diff --git a/src/constants.h b/src/constants.h index 80c1a1b..4a594cb 100644 --- a/src/constants.h +++ b/src/constants.h @@ -4,12 +4,12 @@ #include #include "position.h" -// IMPORTANT: panic is reserved for invalid results +const int INF = 0x3F3F3F3F; enum error {none}; // TODO: update result to include subject -enum result {fine, died, go_down, hit, moved}; +enum result {fine, died, go_down, hit, moved, miss}; enum game_status {terminated, main_menu, in_game, options}; @@ -34,16 +34,18 @@ 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 +const int RACE_CNT = 4; // TODO: update as you go -enum race {unknown = 0, rshade /* TODO: fill out the other races (including enemies) */}; +enum race {unknown = 0, rshade, rvampire, goblin /* 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 MAX_HP[RACE_CNT] = {0, 125, INF, 110}; +const int STARTING_HP[RACE_CNT] = {0, 125, 50, 110}; +const int STARTING_ATK[RACE_CNT] = {0, 25, 25, 15}; +const int STARTING_DEF[RACE_CNT] = {0, 25, 25, 20}; +const char CHARACTER_REP[RACE_CNT] = {'@', 'S', 'V', 'G'}; + + const int DIRECTION_CNT = 8; // IMPORTANT: east is positive for x and SOUTH is positive for y diff --git a/src/goblin.cc b/src/goblin.cc new file mode 100644 index 0000000..48907b6 --- /dev/null +++ b/src/goblin.cc @@ -0,0 +1,30 @@ +#include "goblin.h" +#include +#include + + +result goblin::attack(const direction dir, const 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 (res == result::died) { + gold += GAIN_GOLD; + } + return res; + } + + return result::fine; +} + +result goblin::get_hit(const enum race &race, const int atk, + const float hitrate) { + if (rng.rand_num() <= hitrate * (float)RAND_MAX) + HP = std::max(HP - calc_dmg(atk, DEF), 0); + + if (HP == 0) + return result::died; + + return result::hit; +} diff --git a/src/goblin.h b/src/goblin.h new file mode 100644 index 0000000..d2f89db --- /dev/null +++ b/src/goblin.h @@ -0,0 +1,16 @@ +#ifndef __GOBLIN_H__ +#define __GOBLIN_H__ +#include "characters.h" + +const int GAIN_GOLD = 5; + +class goblin final: public character { +public: + goblin(const position_list &available_positions); // spawn at a random place + virtual result attack(const direction dir, + const character_list &chlist) override; + virtual result get_hit(const enum race &race, const int atk, + const float hit_rate) override; +}; + +#endif \ No newline at end of file diff --git a/src/inventory.h b/src/inventory.h new file mode 100644 index 0000000..00b572f --- /dev/null +++ b/src/inventory.h @@ -0,0 +1,10 @@ +#ifndef __INVENTORY_H__ +#define __INVENTORY_H__ + +class inventory final { +private: + object_list objects; + +}; + +#endif diff --git a/src/objects.h b/src/objects.h index e4ae59b..c2e0424 100644 --- a/src/objects.h +++ b/src/objects.h @@ -18,6 +18,11 @@ public: void print(display &display) {} }; +class object_list final: public layer { +private: + +}; + // TODO: throw potion into another header class potion final: public object { diff --git a/src/races.h b/src/races.h index 0351a9e..73b9cd4 100644 --- a/src/races.h +++ b/src/races.h @@ -6,20 +6,9 @@ #ifndef __RACES_H__ #define __RACES_H__ -#include "characters.h" -// IMPORTANT: assumes all available positions have excluded chlist - -class shade final: public character { -public: - shade(const position_list &available_positions); // spawn at a random place - virtual result attack(const direction dir, - const character_list &chlist) override; - virtual result get_hit(const enum race &race, const int atk, - const float hitrate) override; -}; - -// TODO: fill out the other races -// TODO: implement enemie movement +#include "shade.h" +#include "goblin.h" +#include "vampire.h" #endif diff --git a/src/room.cc b/src/room.cc new file mode 100644 index 0000000..fe6026a --- /dev/null +++ b/src/room.cc @@ -0,0 +1 @@ +#include "room.h" diff --git a/src/room.h b/src/room.h new file mode 100644 index 0000000..f0a7b58 --- /dev/null +++ b/src/room.h @@ -0,0 +1,6 @@ +#ifndef __ROOM_H__ +#define __ROOM_H__ + + + +#endif diff --git a/src/races.cc b/src/shade.cc similarity index 70% rename from src/races.cc rename to src/shade.cc index 9594b3d..e5c54fa 100644 --- a/src/races.cc +++ b/src/shade.cc @@ -1,4 +1,4 @@ -#include "races.h" +#include "shade.h" #include #include @@ -10,21 +10,17 @@ shade::shade(const position_list &available_positions): hostile = true; } -result shade::attack(const direction dir, const character_list &chlist) { +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_hitrate); + if (tmp == ch.get_position()) { + return ch.get_hit(race, ATK, base_hit_rate); } return result::fine; } -int calc_dmg(const int ATK, const int DEF) { - return ceil((100 / (100 + DEF)) * ATK); -} - result shade::get_hit(const enum race &race, const int atk, const float hitrate) { if (rng.rand_num() <= hitrate * (float)RAND_MAX) // This is a hit! @@ -35,3 +31,4 @@ result shade::get_hit(const enum race &race, const int atk, return result::hit; } + diff --git a/src/shade.h b/src/shade.h new file mode 100644 index 0000000..b470d96 --- /dev/null +++ b/src/shade.h @@ -0,0 +1,15 @@ +#ifndef __SHADE_H__ +#define __SHADE_H__ + +#include "characters.h" + +class shade final: public character { +public: + shade(const position_list &available_positions); // 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, + const float hit_rate) override; +}; + +#endif diff --git a/src/vampire.cc b/src/vampire.cc new file mode 100644 index 0000000..99fffd7 --- /dev/null +++ b/src/vampire.cc @@ -0,0 +1,30 @@ +#include "vampire.h" +#include +#include + + +result vampire::attack(const direction dir, const 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 (res != result::miss) { + HP += GAIN_HP; + } + return res; + } + + return result::fine; +} + +result vampire::get_hit(const enum race &race, const int atk, + const float hitrate) { + if (rng.rand_num() <= hitrate * (float)RAND_MAX) + HP = std::max(HP - calc_dmg(atk, DEF), 0); + + if (HP == 0) + return result::died; + + return result::hit; +} diff --git a/src/vampire.h b/src/vampire.h new file mode 100644 index 0000000..6c6d560 --- /dev/null +++ b/src/vampire.h @@ -0,0 +1,16 @@ +#ifndef __VAMPIRE_H__ +#define __VAMPIRE_H__ +#include "characters.h" + +const int GAIN_HP = 5; + +class vampire final: public character { +public: + vampire(const position_list &available_positions); // spawn at a random place + virtual result attack(const direction dir, + const character_list &chlist) override; + virtual result get_hit(const enum race &race, const int atk, + const float hit_rate) override; +}; + +#endif diff --git a/tools/astyle b/tools/astyle new file mode 100755 index 0000000..f09624b Binary files /dev/null and b/tools/astyle differ