full implementation!
bug: level generation will generate nullptrs
This commit is contained in:
76
src/cc3k.cc
Normal file
76
src/cc3k.cc
Normal file
@ -0,0 +1,76 @@
|
||||
#include "cc3k.h"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
CC3K::CC3K(const feature enabled_features,
|
||||
input *in, display *out, RNG *rng):
|
||||
enabled_features{enabled_features},
|
||||
in{in}, out{out}, rng{rng} {
|
||||
curr_menu = std::make_unique<menu>(enabled_features);
|
||||
out->clear();
|
||||
curr_menu->print(out);
|
||||
out->render();
|
||||
gresult.status = game_status::main_menu;
|
||||
}
|
||||
|
||||
game_status CC3K::run() {
|
||||
switch (gresult.status) {
|
||||
case main_menu: {
|
||||
auto tmp = curr_menu->run(in);
|
||||
|
||||
if (tmp == -2)
|
||||
return terminated;
|
||||
|
||||
if (tmp != -1) {
|
||||
curr_menu = nullptr;
|
||||
curr_game = std::make_unique<game>((race)tmp,
|
||||
enabled_features,
|
||||
in, out, rng);
|
||||
out->clear();
|
||||
curr_game->print();
|
||||
out->render();
|
||||
gresult.status = in_game;
|
||||
return in_game;
|
||||
}
|
||||
|
||||
out->clear();
|
||||
curr_menu->print(out);
|
||||
out->render();
|
||||
return main_menu;
|
||||
}
|
||||
|
||||
case in_game: {
|
||||
gresult = curr_game->run();
|
||||
|
||||
if (gresult.status == restart) {
|
||||
curr_game = nullptr;
|
||||
curr_menu = std::make_unique<menu>(enabled_features);
|
||||
out->clear();
|
||||
curr_menu->print(out);
|
||||
out->render();
|
||||
return main_menu;
|
||||
} else if (gresult.status == in_game) {
|
||||
out->clear();
|
||||
curr_game->print();
|
||||
out->render();
|
||||
return in_game;
|
||||
}
|
||||
|
||||
out->clear();
|
||||
gresult.print(out);
|
||||
out->render();
|
||||
return gresult.status;
|
||||
}
|
||||
|
||||
case dead:
|
||||
case won:
|
||||
case escaped:
|
||||
gresult.run(in);
|
||||
return terminated;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return terminated;
|
||||
}
|
22
src/cc3k.h
22
src/cc3k.h
@ -1,8 +1,26 @@
|
||||
#ifndef __CC3K_H__
|
||||
#define __CC3K_H__
|
||||
|
||||
class CC3K;
|
||||
#include "input.h"
|
||||
#include "display.h"
|
||||
#include "game.h"
|
||||
#include "menu.h"
|
||||
#include "result.h"
|
||||
|
||||
// every time it runs, clear first
|
||||
class CC3K final {
|
||||
private:
|
||||
const feature enabled_features;
|
||||
input *in;
|
||||
display *out;
|
||||
RNG *rng;
|
||||
|
||||
game_result gresult;
|
||||
std::unique_ptr<game> curr_game;
|
||||
std::unique_ptr<menu> curr_menu;
|
||||
public:
|
||||
CC3K(const feature enabled_features,
|
||||
input *in, display *out, RNG *rng);
|
||||
game_status run();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@ struct long_result {
|
||||
};
|
||||
|
||||
enum game_status : int {terminated, main_menu, in_game, options,
|
||||
dead, won, escaped, restart, skip_turn
|
||||
dead, won, escaped, restart
|
||||
};
|
||||
|
||||
enum game_command : int {game_command_terminate = 0,
|
||||
|
49
src/game.cc
49
src/game.cc
@ -46,9 +46,9 @@ bool compare_characters(const character *a, const character *b) {
|
||||
return a->get_pos() < b->get_pos();
|
||||
}
|
||||
|
||||
void game::move_enemies() {
|
||||
character *game::move_enemies() {
|
||||
if (the_world)
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
auto enemies = levels[curr_level]->get_elist();
|
||||
std::sort(enemies.begin(), enemies.end(), ::compare_characters);
|
||||
@ -62,16 +62,18 @@ void game::move_enemies() {
|
||||
ch->act(levels[curr_level].get(), player.get(), hostile);
|
||||
|
||||
if (player->is_dead())
|
||||
return;
|
||||
return ch;
|
||||
|
||||
if (ch->is_dead())
|
||||
ch->dies(levels[curr_level].get(), player.get());
|
||||
|
||||
msg += res.msg;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
game_status game::run() {
|
||||
game_result game::run() {
|
||||
player->start_turn();
|
||||
auto res = player->interpret_command(levels[curr_level].get(),
|
||||
in->get_command());
|
||||
@ -79,28 +81,40 @@ game_status game::run() {
|
||||
|
||||
switch (res.res) {
|
||||
case result::terminate:
|
||||
return terminated;
|
||||
return {terminated, ""};
|
||||
|
||||
case result::died:
|
||||
return game_status::dead;
|
||||
return {dead, "You died: killed by your own stupidity!"};
|
||||
|
||||
case result::go_down: {
|
||||
if (curr_level == max_level - 1)
|
||||
return game_status::won;
|
||||
return {won, "You won! You collected " +
|
||||
std::to_string(player->get_gold()) +
|
||||
" after " + std::to_string(curr_turn + 1) +
|
||||
" turns!"};
|
||||
|
||||
player->discard_level_effects();
|
||||
|
||||
++curr_level;
|
||||
|
||||
new_level();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case result::go_up: {
|
||||
if (curr_level == 0)
|
||||
return game_status::escaped;
|
||||
return {escaped, "You escaped the dungeon with " +
|
||||
std::to_string(player->get_gold()) +
|
||||
" after " + std::to_string(curr_turn + 1) +
|
||||
" turns! Coward!"};
|
||||
|
||||
player->discard_level_effects();
|
||||
|
||||
--curr_level;
|
||||
|
||||
player->set_pos(levels[curr_level]->get_down_stairs());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -109,13 +123,13 @@ game_status game::run() {
|
||||
break;
|
||||
|
||||
case restart_game:
|
||||
return restart;
|
||||
return {restart, ""};
|
||||
|
||||
case unknown:
|
||||
case fine:
|
||||
case applied_nothing:
|
||||
++curr_turn;
|
||||
return game_status::in_game;
|
||||
return {in_game, ""};
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -125,15 +139,20 @@ game_status game::run() {
|
||||
player->calc_effects();
|
||||
|
||||
if (player->is_dead())
|
||||
return game_status::dead;
|
||||
return {dead, "You died: killed by your own stupidity!"};
|
||||
|
||||
move_enemies();
|
||||
auto killer = move_enemies();
|
||||
|
||||
if (player->is_dead())
|
||||
return game_status::dead;
|
||||
if (player->is_dead()) {
|
||||
if (killer == nullptr)
|
||||
return {dead, "You died: killed by your own stupidity!"};
|
||||
|
||||
return {dead, (std::string)"You died: killed by a(n) " +
|
||||
killer->get_race_name()};
|
||||
}
|
||||
|
||||
++curr_turn;
|
||||
return game_status::in_game;
|
||||
return {in_game, ""};
|
||||
}
|
||||
|
||||
const position STATUS_RACE{0, 25};
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "characters.h"
|
||||
#include "level.h"
|
||||
#include "player.h"
|
||||
#include "result.h"
|
||||
|
||||
enum game_status : int;
|
||||
|
||||
@ -43,14 +44,14 @@ public:
|
||||
input *new_in,
|
||||
display *new_out,
|
||||
RNG *new_rng);
|
||||
game_status run();
|
||||
game_result run();
|
||||
size_t get_curr_level() const;
|
||||
size_t get_curr_turn() const;
|
||||
const character *get_player() const;
|
||||
void print();
|
||||
private:
|
||||
void new_level();
|
||||
void move_enemies();
|
||||
character *move_enemies();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -39,7 +39,7 @@ game_command console_input::get_command() {
|
||||
auto tmp = get_direction(cmd);
|
||||
|
||||
if (tmp != game_command_panic)
|
||||
return tmp;
|
||||
return (game_command)(tmp + move_north);
|
||||
}
|
||||
|
||||
return game_command_pass;
|
||||
|
36
src/level.cc
36
src/level.cc
@ -114,31 +114,31 @@ void level::gen_potions(RNG *rng, std::vector<position_list> &tiles) {
|
||||
void level::print(display *out) const {
|
||||
map.print(out);
|
||||
|
||||
for (auto ch : elist)
|
||||
ch->print(out);
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
plist[i]->print(out);
|
||||
|
||||
for (auto p : plist)
|
||||
p->print(out);
|
||||
for (size_t i = 0; i < glist.size(); ++i)
|
||||
out->print_char(glist[i].pos, 'G', COLOR_PAIR(COLOR_YELLOW));
|
||||
|
||||
for (auto gold : glist)
|
||||
out->print_char(gold.pos, 'G', COLOR_PAIR(COLOR_YELLOW));
|
||||
for (size_t i = 0; i < elist.size(); ++i)
|
||||
elist[i]->print(out);
|
||||
}
|
||||
|
||||
bool level::is_available(const position &pos, bool is_player) const {
|
||||
if (!map.is_available(pos))
|
||||
return false;
|
||||
|
||||
for (auto ch : elist)
|
||||
if (pos == ch->get_pos())
|
||||
for (size_t i = 0; i < elist.size(); ++i)
|
||||
if (pos == elist[i]->get_pos())
|
||||
return false;
|
||||
|
||||
if (!(enabled_features & FEATURE_WALK_OVER) && !is_player) {
|
||||
for (auto p : plist)
|
||||
if (pos == p->get_pos())
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
if (pos == plist[i]->get_pos())
|
||||
return false;
|
||||
|
||||
for (auto g : glist)
|
||||
if (pos == g.pos)
|
||||
for (size_t i = 0; i < glist.size(); ++i)
|
||||
if (pos == glist[i].pos)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -149,16 +149,16 @@ bool level::is_available_all(const position &pos) const {
|
||||
if (!map.is_available(pos))
|
||||
return false;
|
||||
|
||||
for (auto ch : elist)
|
||||
if (pos == ch->get_pos())
|
||||
for (size_t i = 0; i < elist.size(); ++i)
|
||||
if (pos == elist[i]->get_pos())
|
||||
return false;
|
||||
|
||||
for (auto p : plist)
|
||||
if (pos == p->get_pos())
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
if (pos == plist[i]->get_pos())
|
||||
return false;
|
||||
|
||||
for (auto g : glist)
|
||||
if (pos == g.pos)
|
||||
for (size_t i = 0; i < glist.size(); ++i)
|
||||
if (pos == glist[i].pos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -22,12 +22,11 @@ int main(int argc, char **argv) {
|
||||
return RETURN_FINE;
|
||||
}
|
||||
|
||||
// CC3K game_proc(enabled_features, *in, *out, *log, *rng);
|
||||
CC3K game_proc(enabled_features, in.get(), out.get(), rng.get());
|
||||
|
||||
// while (game_proc.run() != game_status::terminated) {
|
||||
// out->render();
|
||||
// out->clear();
|
||||
// }
|
||||
while (1)
|
||||
if (game_proc.run() == game_status::terminated)
|
||||
break;
|
||||
|
||||
return RETURN_FINE;
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ game_map::game_map(character *player, RNG *rng, const feature enabled_features):
|
||||
for (size_t i = 0; i < rooms_tile_list.size(); ++i)
|
||||
rooms_tile_list[i].shrink_to_fit();
|
||||
|
||||
rooms_tile_list.shrink_to_fit();
|
||||
while (rooms_tile_list[rooms_tile_list.size() - 1].size() == 0)
|
||||
rooms_tile_list.pop_back();
|
||||
|
||||
int player_room = rng->rand_under(room_data.size());
|
||||
player->set_pos(rng->get_rand_in_vector(rooms_tile_list[player_room]));
|
||||
@ -92,6 +93,9 @@ game_map::game_map(character *player, const std::string &map_data,
|
||||
rooms_tile_list[map_data[i] - '0'].push_back(remap_index(i));
|
||||
}
|
||||
|
||||
while (rooms_tile_list[rooms_tile_list.size() - 1].size() == 0)
|
||||
rooms_tile_list.pop_back();
|
||||
|
||||
for (int i = 0; i <= max_room_num; ++i)
|
||||
room_data.push_back({0, 0, 0, 0});
|
||||
|
||||
@ -99,7 +103,6 @@ game_map::game_map(character *player, const std::string &map_data,
|
||||
player->set_pos(rng->get_rand_in_vector(rooms_tile_list[player_room]));
|
||||
|
||||
gen_stairs(player_room, rng);
|
||||
|
||||
}
|
||||
|
||||
bool game_map::is_available(const position &pos) const {
|
||||
|
161
src/menu.cc
Normal file
161
src/menu.cc
Normal file
@ -0,0 +1,161 @@
|
||||
#include "menu.h"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
const int NORMAL_CNT = 5;
|
||||
const int EXTRA_CNT = 5;
|
||||
|
||||
const enum race RACES[EXTRA_CNT] = {
|
||||
rshade, rdrow, rgoblin, rvampire, rtroll
|
||||
};
|
||||
|
||||
const position RACE_POS[EXTRA_CNT] = {
|
||||
{4, 9}, {4, 11}, {4, 13}, {4, 15}, {4, 17}
|
||||
};
|
||||
|
||||
menu::menu(const feature enabled_features):
|
||||
enabled_features{enabled_features},
|
||||
cur{RACE_POS[0]} {}
|
||||
|
||||
const int UP_LIMIT = 9;
|
||||
const int DOWN_LIMIT = 17;
|
||||
const int LEFT_LIMIT = 4;
|
||||
const int RIGHT_LIMIT = 4;
|
||||
const int EXTRA_UP_LIMIT = 9;
|
||||
const int EXTRA_DOWN_LIMIT = 17;
|
||||
const int EXTRA_LEFT_LIMIT = 4;
|
||||
const int EXTRA_RIGHT_LIMIT = 4;
|
||||
const int X_INCRE = 37;
|
||||
const int Y_INCRE = 2;
|
||||
|
||||
const char *NORMAL_SCREEN =
|
||||
"+-----------------------------------------------------------------------------+\
|
||||
| ____ ____ _____ _ __ |\
|
||||
| / _\\/ _\\\\__ \\/ |/ / |\
|
||||
| | / | / / || / |\
|
||||
| | \\_ | \\_ _\\ || \\ |\
|
||||
| \\____/\\____//____/\\_|\\_\\ |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Choose your race | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Shade | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Drow | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Goblin | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Vampire | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Troll | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
+-----------------------------------------------------------------------------+";
|
||||
|
||||
const char *EXTRA_SCREEN =
|
||||
"+-----------------------------------------------------------------------------+\
|
||||
| ____ ____ _____ _ __ |\
|
||||
| / _\\/ _\\\\__ \\/ |/ / |\
|
||||
| | / | / / || / |\
|
||||
| | \\_ | \\_ _\\ || \\ |\
|
||||
| \\____/\\____//____/\\_|\\_\\ |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Choose your race | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Shade | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Drow | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Goblin | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Vampire | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| Troll | |\
|
||||
+-----------------------------------------------------------------------------+\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
+-----------------------------------------------------------------------------+";
|
||||
|
||||
int menu::run(input *in) {
|
||||
auto cmd = in->get_command();
|
||||
|
||||
int up_limit = UP_LIMIT;
|
||||
int down_limit = DOWN_LIMIT;
|
||||
int left_limit = LEFT_LIMIT;
|
||||
int right_limit = RIGHT_LIMIT;
|
||||
|
||||
if (enabled_features & FEATURE_EXTRA_STUFF) {
|
||||
up_limit = EXTRA_UP_LIMIT;
|
||||
down_limit = EXTRA_DOWN_LIMIT;
|
||||
left_limit = EXTRA_LEFT_LIMIT;
|
||||
right_limit = EXTRA_RIGHT_LIMIT;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case game_command::enter: {
|
||||
if (enabled_features & FEATURE_EXTRA_STUFF) {
|
||||
for (int i = 0; i < EXTRA_CNT; ++i)
|
||||
if (cur == RACE_POS[i])
|
||||
return RACES[i];
|
||||
|
||||
return -1;
|
||||
} else {
|
||||
for (int i = 0; i < NORMAL_CNT; ++i)
|
||||
if (cur == RACE_POS[i])
|
||||
return RACES[i];
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
case move_north: {
|
||||
if (cur.y != up_limit)
|
||||
cur.y -= Y_INCRE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case move_south: {
|
||||
if (cur.y != down_limit)
|
||||
cur.y += Y_INCRE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case move_east: {
|
||||
if (cur.x != left_limit)
|
||||
cur.x -= X_INCRE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case move_west: {
|
||||
if (cur.x != right_limit)
|
||||
cur.x += X_INCRE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case game_command_terminate:
|
||||
return -2;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void menu::print(display *out) {
|
||||
if (enabled_features & FEATURE_EXTRA_STUFF)
|
||||
out->print_str({0, 0}, NORMAL_SCREEN);
|
||||
else
|
||||
out->print_str({0, 0}, EXTRA_SCREEN);
|
||||
out->print_str(cur, "->", COLOR_PAIR(COLOR_BLUE));
|
||||
}
|
21
src/menu.h
Normal file
21
src/menu.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __MENU_H__
|
||||
#define __MENU_H__
|
||||
|
||||
#include "position.h"
|
||||
#include "display.h"
|
||||
#include "input.h"
|
||||
|
||||
typedef unsigned int feature;
|
||||
enum race : int;
|
||||
|
||||
class menu final {
|
||||
private:
|
||||
const feature enabled_features;
|
||||
position cur;
|
||||
public:
|
||||
menu(const feature enabled_features);
|
||||
int run(input *in);
|
||||
void print(display *out);
|
||||
};
|
||||
|
||||
#endif
|
45
src/result.cc
Normal file
45
src/result.cc
Normal file
@ -0,0 +1,45 @@
|
||||
#include "result.h"
|
||||
|
||||
|
||||
const char *WIN_SCREEN =
|
||||
"+-----------------------------------------------------------------------------+\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| ___________ |\
|
||||
| '._==_==_=_.' |\
|
||||
| .-\\: /-. |\
|
||||
| | (|:. |) | |\
|
||||
| '-|:. |-' |\
|
||||
| \\::. / |\
|
||||
| '::. .' |\
|
||||
| ) ( |\
|
||||
| _.' '._ |\
|
||||
| `.......` |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| > |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
| |\
|
||||
+-----------------------------------------------------------------------------+";
|
||||
|
||||
const position &MSG_START = {11, 24};
|
||||
|
||||
void game_result::run(input *in) {
|
||||
in->get_command();
|
||||
}
|
||||
|
||||
void game_result::print(display *out) {
|
||||
out->print_str({0, 0}, WIN_SCREEN);
|
||||
out->print_str(MSG_START, msg, COLOR_PAIR(COLOR_YELLOW));
|
||||
}
|
18
src/result.h
Normal file
18
src/result.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __RESULT_H__
|
||||
#define __RESULT_H__
|
||||
|
||||
#include <string>
|
||||
#include "display.h"
|
||||
#include "input.h"
|
||||
|
||||
enum game_status : int;
|
||||
|
||||
struct game_result final {
|
||||
game_status status;
|
||||
std::string msg;
|
||||
|
||||
void run(input *in);
|
||||
void print(display *out);
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user