Merge branch 'master' of peisongxiao.com:~/cs246/a5
This commit is contained in:
@ -58,7 +58,7 @@ enum race : int {rshade = 0, rdrow, rvampire, rtroll,
|
|||||||
static const char CHAR_REP[RACE_CNT] = {
|
static const char CHAR_REP[RACE_CNT] = {
|
||||||
's', 'd', 'v', 't', 'g', 'H', 'W', 'E', 'O', 'M', 'D', 'L',
|
's', 'd', 'v', 't', 'g', 'H', 'W', 'E', 'O', 'M', 'D', 'L',
|
||||||
't', 'g', 'm', 'b', 'a',
|
't', 'g', 'm', 'b', 'a',
|
||||||
'V', 'S', 'l', 'W', 'h', 'B'
|
'V', 'S', 'l', 'Z', 'h', 'B'
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int MAX_HP[RACE_CNT] = {
|
static const int MAX_HP[RACE_CNT] = {
|
||||||
@ -68,13 +68,13 @@ static const int MAX_HP[RACE_CNT] = {
|
|||||||
};
|
};
|
||||||
static const int STARTING_HP[RACE_CNT] = {
|
static const int STARTING_HP[RACE_CNT] = {
|
||||||
125, 150, 50, 120, 110, 140, 100, 140, 180, 30, 150, 100,
|
125, 150, 50, 120, 110, 140, 100, 140, 180, 30, 150, 100,
|
||||||
800, 130, 150, 120, 100,
|
800, 130, 100, 120, 100,
|
||||||
150, 100, 60, 100, 90, 140
|
150, 100, 60, 100, 90, 140
|
||||||
};
|
};
|
||||||
static const int STARTING_ATK[RACE_CNT] = {
|
static const int STARTING_ATK[RACE_CNT] = {
|
||||||
25, 25, 25, 25, 15, 20, 20, 30, 30, 70, 20, 15,
|
25, 25, 25, 25, 15, 20, 20, 30, 30, 70, 20, 15,
|
||||||
40, 25, 80, 15, 30,
|
40, 25, 70, 15, 30,
|
||||||
30, 25, 10, 20, 15, 25
|
30, 25, 10, 20, 15, 20
|
||||||
};
|
};
|
||||||
static const int STARTING_DEF[RACE_CNT] = {
|
static const int STARTING_DEF[RACE_CNT] = {
|
||||||
25, 15, 25, 15, 20, 20, 30, 10, 25, 5, 20, 20,
|
25, 15, 25, 15, 20, 20, 30, 10, 25, 5, 20, 20,
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
#include "enemies/human.h"
|
#include "enemies/human.h"
|
||||||
#include "enemies/merchant.h"
|
#include "enemies/merchant.h"
|
||||||
#include "enemies/orc.h"
|
#include "enemies/orc.h"
|
||||||
|
#include "enemies/viking.h"
|
||||||
|
#include "enemies/swordsman.h"
|
||||||
|
#include "enemies/leprechaun.h"
|
||||||
|
#include "enemies/witch.h"
|
||||||
|
#include "enemies/hacker.h"
|
||||||
|
#include "enemies/baby_dragon.h"
|
||||||
|
|
||||||
std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
|
std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
|
||||||
const position &fallback,
|
const position &fallback,
|
||||||
@ -23,9 +29,10 @@ std::unique_ptr<enemy_base> new_dragon(RNG *rng, const position &pos,
|
|||||||
fallback, which_room);
|
fallback, which_room);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int EXCNT = 6;
|
const int EXCNT = 12;
|
||||||
const race EXCHOICES[EXCNT] = {
|
const race EXCHOICES[EXCNT] = {
|
||||||
rhuman, rdwarf, rhalfling, relf, rorc, rmerchant
|
rhuman, rdwarf, rhalfling, relf, rorc, rmerchant,
|
||||||
|
rviking, rswordsman, rleprechaun, rwitch, rhacker, rbaby_dragon
|
||||||
};
|
};
|
||||||
const int CNT = 18;
|
const int CNT = 18;
|
||||||
const race CHOICES[CNT] = {
|
const race CHOICES[CNT] = {
|
||||||
@ -61,32 +68,50 @@ std::unique_ptr<enemy_base> new_enemy(RNG *rng, const position &pos,
|
|||||||
case rdwarf:
|
case rdwarf:
|
||||||
return make_unique<dwarf>(rng, enabled_features,
|
return make_unique<dwarf>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
|
||||||
case rhuman:
|
case rhuman:
|
||||||
return make_unique<human>(rng, enabled_features,
|
return make_unique<human>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
|
||||||
case relf:
|
case relf:
|
||||||
return make_unique<elf>(rng, enabled_features,
|
return make_unique<elf>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
|
||||||
case rorc:
|
case rorc:
|
||||||
return make_unique<orc>(rng, enabled_features,
|
return make_unique<orc>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
|
||||||
case rmerchant:
|
case rmerchant:
|
||||||
return make_unique<merchant>(rng, enabled_features,
|
return make_unique<merchant>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
|
||||||
case rhalfling:
|
case rhalfling:
|
||||||
return make_unique<halfling>(rng, enabled_features,
|
return make_unique<halfling>(rng, enabled_features,
|
||||||
pos, which_room);
|
pos, which_room);
|
||||||
break;
|
|
||||||
|
case rviking:
|
||||||
|
return make_unique<viking>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
|
case rswordsman:
|
||||||
|
return make_unique<swordsman>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
|
case rleprechaun:
|
||||||
|
return make_unique<leprechaun>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
|
case rwitch:
|
||||||
|
return make_unique<witch>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
|
case rhacker:
|
||||||
|
return make_unique<hacker>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
|
case rbaby_dragon:
|
||||||
|
return make_unique<baby_dragon>(rng, enabled_features,
|
||||||
|
pos, which_room);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
15
src/enemies/baby_dragon.cc
Normal file
15
src/enemies/baby_dragon.cc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "baby_dragon.h"
|
||||||
|
|
||||||
|
#include "../constants.h"
|
||||||
|
|
||||||
|
baby_dragon::baby_dragon(RNG *rng, const feature enabled_features,
|
||||||
|
const position &pos, const int gen_room_num):
|
||||||
|
enemy_base{rng, enabled_features, rbaby_dragon, pos, gen_room_num, "B"} {}
|
||||||
|
|
||||||
|
const char *baby_dragon::get_race_name() const {
|
||||||
|
return "Baby_Dragon";
|
||||||
|
}
|
||||||
|
|
||||||
|
void baby_dragon::apply_effect(std::unique_ptr<potion> effect) {
|
||||||
|
return;
|
||||||
|
}
|
14
src/enemies/baby_dragon.h
Normal file
14
src/enemies/baby_dragon.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __BABY_DRAGON_H__
|
||||||
|
#define __BABY_DRAGON_H__
|
||||||
|
|
||||||
|
#include "../enemy.h"
|
||||||
|
|
||||||
|
class baby_dragon final: public enemy_base {
|
||||||
|
public:
|
||||||
|
baby_dragon(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
|
const int gen_room_num);
|
||||||
|
const char *get_race_name() const override;
|
||||||
|
void apply_effect(std::unique_ptr<potion> effect) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
40
src/enemies/hacker.cc
Normal file
40
src/enemies/hacker.cc
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "hacker.h"
|
||||||
|
|
||||||
|
#include "../constants.h"
|
||||||
|
|
||||||
|
hacker::hacker(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
|
const int gen_room_num):
|
||||||
|
enemy_base{rng, enabled_features, rhacker, pos, gen_room_num, "h"} {}
|
||||||
|
|
||||||
|
const char *hacker::get_race_name() const {
|
||||||
|
return "Hacker";
|
||||||
|
}
|
||||||
|
|
||||||
|
long_result hacker::get_hit(character *ch, const int tATK,
|
||||||
|
const fraction &hit_rate) {
|
||||||
|
if (rng->trial(hit_rate)) {
|
||||||
|
int tmp = calc_dmg(tATK, DEF);
|
||||||
|
tmp = tmp > HP ? HP : tmp;
|
||||||
|
HP -= tmp;
|
||||||
|
|
||||||
|
if (HP == 0)
|
||||||
|
return {result::hit, rand_str()};
|
||||||
|
|
||||||
|
return {result::hit, rand_str()};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {miss, rand_str()};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hacker::rand_str() {
|
||||||
|
size_t len = rng->rand_between(RAND_STR_LEN_MIN, RAND_STR_LEN_MAX);
|
||||||
|
std::string result{""};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
result += static_cast<char>(rng->rand_between(PRINT_CHAR_MIN,
|
||||||
|
PRINT_CHAR_MAX + 1));
|
||||||
|
|
||||||
|
result += ' ';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
20
src/enemies/hacker.h
Normal file
20
src/enemies/hacker.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __HACKER_H__
|
||||||
|
#define __HACKER_H__
|
||||||
|
|
||||||
|
#include "../enemy.h"
|
||||||
|
|
||||||
|
class hacker final: public enemy_base {
|
||||||
|
static const int RAND_STR_LEN_MIN = 10;
|
||||||
|
static const int RAND_STR_LEN_MAX = 30;
|
||||||
|
static const int PRINT_CHAR_MIN = 33;
|
||||||
|
static const int PRINT_CHAR_MAX = 126;
|
||||||
|
std::string rand_str();
|
||||||
|
public:
|
||||||
|
hacker(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
|
const int gen_room_num);
|
||||||
|
const char *get_race_name() const override;
|
||||||
|
long_result get_hit(character *ch, const int tATK,
|
||||||
|
const fraction &hit_rate) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -25,11 +25,13 @@ long_result halfling::get_hit(character *ch, const int tATK,
|
|||||||
if (HP == 0)
|
if (HP == 0)
|
||||||
return {result::hit,
|
return {result::hit,
|
||||||
"PC deals " + std::to_string(tmp) +
|
"PC deals " + std::to_string(tmp) +
|
||||||
" damage to " + abbrev + ". " + abbrev +
|
" damage to " + abbrev + " (" +
|
||||||
" is slain by PC. "};
|
std::to_string(HP) + " HP). " +
|
||||||
|
abbrev + " is slain by PC. "};
|
||||||
|
|
||||||
return {result::hit, "PC deals " +
|
return {result::hit, "PC deals " +
|
||||||
std::to_string(tmp) + " damage to " + abbrev + ". "};
|
std::to_string(tmp) + " damage to " + abbrev + " (" +
|
||||||
|
std::to_string(HP) + " HP). "};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {miss, "PC tried to hit " + abbrev +
|
return {miss, "PC tried to hit " + abbrev +
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
#include "../player.h"
|
#include "../player.h"
|
||||||
|
#include "../level.h"
|
||||||
|
|
||||||
leprechaun::leprechaun(RNG *rng, const feature enabled_features,
|
leprechaun::leprechaun(RNG *rng, const feature enabled_features,
|
||||||
const position &pos,
|
const position &pos,
|
||||||
const int gen_room_num):
|
const int gen_room_num):
|
||||||
enemy_base{rng, enabled_features, rleprechaun, pos, gen_room_num, "l"} {}
|
enemy_base{rng, enabled_features, rleprechaun, pos, gen_room_num, "l"},
|
||||||
|
gold_cnt{0} {}
|
||||||
|
|
||||||
const char *leprechaun::get_race_name() const {
|
const char *leprechaun::get_race_name() const {
|
||||||
return "Leprechaun";
|
return "Leprechaun";
|
||||||
@ -25,8 +27,14 @@ long_result leprechaun::attack(character *ch) {
|
|||||||
res.msg += "l steals " + std::to_string(STEAL_GOLD) +
|
res.msg += "l steals " + std::to_string(STEAL_GOLD) +
|
||||||
" pieces of gold from PC. ";
|
" pieces of gold from PC. ";
|
||||||
static_cast<player_base *>(ch)->add_gold(-STEAL_GOLD);
|
static_cast<player_base *>(ch)->add_gold(-STEAL_GOLD);
|
||||||
|
gold_cnt += STEAL_GOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int leprechaun::dies(level *lvl) {
|
||||||
|
lvl->add_gold(gold{pos, gold_cnt});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -12,7 +12,8 @@ public:
|
|||||||
leprechaun(RNG *rng, const feature enabled_features, const position &pos,
|
leprechaun(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
const int gen_room_num);
|
const int gen_room_num);
|
||||||
const char *get_race_name() const override;
|
const char *get_race_name() const override;
|
||||||
virtual long_result attack(character *ch) override;
|
long_result attack(character *ch) override;
|
||||||
|
int dies(level *lvl) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
27
src/enemies/witch.cc
Normal file
27
src/enemies/witch.cc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "witch.h"
|
||||||
|
|
||||||
|
#include "../constants.h"
|
||||||
|
|
||||||
|
witch::witch(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
|
const int gen_room_num):
|
||||||
|
enemy_base{rng, enabled_features, rwitch, pos, gen_room_num, "Z"} {}
|
||||||
|
|
||||||
|
const char *witch::get_race_name() const {
|
||||||
|
return "Witch";
|
||||||
|
}
|
||||||
|
|
||||||
|
long_result witch::attack(character *ch) {
|
||||||
|
auto res = ch->get_hit(this, ATK, base_hit_rate);
|
||||||
|
|
||||||
|
if (res.res == hit && rng->trial(POTION_RATE)) {
|
||||||
|
res.msg += "W's potion spilled onto PC. ";
|
||||||
|
potion_type type =
|
||||||
|
static_cast<potion_type>(rng->rand_under(
|
||||||
|
(enabled_features & FEATURE_EXTRA_STUFF) ?
|
||||||
|
POTION_TYPE_CNT :
|
||||||
|
DEFAULT_POTION_TYPE_CNT));
|
||||||
|
ch->apply_effect(new_potion(type, {0, 0}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
15
src/enemies/witch.h
Normal file
15
src/enemies/witch.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __WITCH_H__
|
||||||
|
#define __WITCH_H__
|
||||||
|
|
||||||
|
#include "../enemy.h"
|
||||||
|
|
||||||
|
class witch final: public enemy_base {
|
||||||
|
constexpr static const fraction POTION_RATE = {1, 5};
|
||||||
|
public:
|
||||||
|
witch(RNG *rng, const feature enabled_features, const position &pos,
|
||||||
|
const int gen_room_num);
|
||||||
|
const char *get_race_name() const override;
|
||||||
|
long_result attack(character *ch) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -75,8 +75,7 @@ long_result enemy_base::get_hit(character *ch, const int tATK,
|
|||||||
"PC deals " + std::to_string(tmp) +
|
"PC deals " + std::to_string(tmp) +
|
||||||
" damage to " + abbrev + " (" +
|
" damage to " + abbrev + " (" +
|
||||||
std::to_string(HP) + " HP). " +
|
std::to_string(HP) + " HP). " +
|
||||||
abbrev +
|
abbrev + " is slain by PC. "};
|
||||||
" is slain by PC. "};
|
|
||||||
|
|
||||||
return {result::hit, "PC deals " +
|
return {result::hit, "PC deals " +
|
||||||
std::to_string(tmp) + " damage to " + abbrev + " (" +
|
std::to_string(tmp) + " damage to " + abbrev + " (" +
|
||||||
|
@ -92,7 +92,7 @@ game_result game::run() {
|
|||||||
in->get_command());
|
in->get_command());
|
||||||
msg = res.msg;
|
msg = res.msg;
|
||||||
|
|
||||||
if (!hostile_merchants && res.msg.find('M') != std::string::npos) {
|
if (!hostile_merchants && res.msg.find(" M ") != std::string::npos) {
|
||||||
hostile_merchants = true;
|
hostile_merchants = true;
|
||||||
msg += "PC has angered the merchants. ";
|
msg += "PC has angered the merchants. ";
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,8 @@ long_result player_base::move(level *lvl,
|
|||||||
res.msg += "PC gains " +
|
res.msg += "PC gains " +
|
||||||
std::to_string(g) +
|
std::to_string(g) +
|
||||||
" pieces of gold. ";
|
" pieces of gold. ";
|
||||||
|
|
||||||
|
gold_cnt += g;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -180,13 +182,17 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) {
|
|||||||
} else if (cmd >= move_north && cmd <= move_southwest) {
|
} else if (cmd >= move_north && cmd <= move_southwest) {
|
||||||
auto res = move(lvl, pos + MOVE[cmd - move_north]);
|
auto res = move(lvl, pos + MOVE[cmd - move_north]);
|
||||||
|
|
||||||
gold g = get_gold_at(pos, lvl->get_glist());
|
gold g{{0, 0}, 0};
|
||||||
gold_cnt += g.get_amount();
|
int gold_tmp = 0;
|
||||||
|
|
||||||
if (g.get_amount())
|
while ((g = get_gold_at(pos, lvl->get_glist())).get_amount() != 0)
|
||||||
res.msg += "PC picked up " + std::to_string(g.get_amount()) +
|
gold_tmp += g.get_amount();
|
||||||
|
|
||||||
|
if (gold_tmp)
|
||||||
|
res.msg += "PC picked up " + std::to_string(gold_tmp) +
|
||||||
" pieces of gold. ";
|
" pieces of gold. ";
|
||||||
|
|
||||||
|
|
||||||
if (enabled_features & FEATURE_INVENTORY) {
|
if (enabled_features & FEATURE_INVENTORY) {
|
||||||
size_t idx = get_potion_at(pos, lvl->get_plist());
|
size_t idx = get_potion_at(pos, lvl->get_plist());
|
||||||
|
|
||||||
@ -223,6 +229,8 @@ long_result player_base::interpret_command(level *lvl, game_command cmd) {
|
|||||||
res.msg += "PC gains " +
|
res.msg += "PC gains " +
|
||||||
std::to_string(g) +
|
std::to_string(g) +
|
||||||
" pieces of gold. ";
|
" pieces of gold. ";
|
||||||
|
|
||||||
|
gold_cnt += g;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
Reference in New Issue
Block a user