Skip to content
Snippets Groups Projects
Commit 6e7f72ce authored by Jake Feddersen's avatar Jake Feddersen
Browse files

Stuff with monsters mostly done

parent 315f6b02
No related branches found
No related tags found
No related merge requests found
Showing with 888 additions and 752 deletions
File added
......@@ -56,3 +56,9 @@
4/2: Parse the rest of the fields
Add error handling for duplicate fields, missing fields
Fix memory leaks and reference errors
4/5: Import Dr. Sheaffer's code for monster and object parsing
4/6: Finally get Dr. Sheaffer's code integrated with my own
Implement generating monsters from descriptions
Update map rendering to include colors
Implement flickering colors for multicolor monsters
Implement generation restrictions for unique monsters
#include <ncurses.h>
#include <cstdint>
#include <iostream>
#include <cstdlib>
......@@ -17,41 +18,51 @@ static int32_t character_turn_cmp(const void *key, const void *with) {
char characteristics_symbols[] = "0123456789abcdef";
character::character(uint8_t x, uint8_t y) {
pos.x = x;
pos.y = y;
character::character(int speed, char symbol, int hitpoints) {
pos.x = 0;
pos.y = 0;
speed = 0;
this->speed = speed;
seq_num = 0;
next_turn = 0;
alive = 1;
symbol = ' ';
this->symbol = symbol;
this->hitpoints = hitpoints;
}
character::~character() { }
bool character::is_player() {
return false;
}
int character::has_characteristic(int bit) {
return 0;
}
monster::monster(uint8_t x, uint8_t y) : character(x, y) {
monster::monster(uint8_t x, uint8_t y, monster_description *desc, int speed, uint32_t abilities, int hitpoints, dice *damage, char symbol) : character(speed, symbol, hitpoints) {
this->desc = desc;
desc->instances++;
static int next_seq = 1;
uint32_t characteristics = rand() & 0x0000000f;
this->characteristics = abilities;
this->characteristics = characteristics;
seq_num = next_seq++;
symbol = characteristics_symbols[characteristics];
this->damage = damage;
// Initialize the starting "last seen" position to the position of the monster
// This will keep smart monsters from moving until they actually see the player
color_index = 0;
pos.x = x;
pos.y = y;
last_seen.x = x;
last_seen.y = y;
speed = randrange(5, 20);
seq_num = next_seq++;
symbol = characteristics_symbols[characteristics];
}
monster::~monster() {
desc->instances--;
}
void monster::die() {
desc->invalidate();
}
int monster::next_color() {
color_index++;
color_index = (color_index % desc->color.size());
return desc->color[color_index];
}
bool monster::is_player() {
......@@ -170,10 +181,9 @@ position monster::monster_move(dungeon &d) {
return pos;
}
player_character::player_character(uint8_t x, uint8_t y) : character(x, y){
speed = 10;
seq_num = 0;
symbol = '@';
player_character::player_character(uint8_t x, uint8_t y) : character(10, '@', 100) {
pos.x = x;
pos.y = y;
}
bool player_character::is_player() {
......@@ -184,6 +194,10 @@ int player_character::has_characteristic(int bit) {
return 0;
}
int player_character::next_color() {
return COLOR_WHITE;
}
void init_character_turn_heap(heap_t *h) {
heap_init(h, character_turn_cmp, NULL);
}
......@@ -3,6 +3,7 @@
#include <cstdint>
#include "dice.h"
#include "heap.h"
#include "util.h"
......@@ -17,6 +18,7 @@
#define NPC_PASS_WALL 0x00000100
class dungeon;
class monster_description;
class character {
public:
......@@ -26,25 +28,33 @@ class character {
int next_turn;
int alive;
char symbol;
character(uint8_t x, uint8_t y);
int hitpoints;
character(int speed, char symbol, int hitpoints);
virtual ~character();
virtual bool is_player();
virtual int has_characteristic(int bit);
virtual bool is_player() = 0;
virtual int has_characteristic(int bit) = 0;
virtual int next_color() = 0;
};
class player_character : public character {
public:
player_character(uint8_t x, uint8_t y);
bool is_player();
bool is_player();
int has_characteristic(int bit);
int next_color();
};
class monster : public character {
private:
monster_description *desc;
dice *damage;
uint32_t characteristics;
position last_seen;
int color_index;
position next_monster_move_tunnel_erratic(dungeon &d);
position next_monster_move_erratic(dungeon &d);
......@@ -52,13 +62,18 @@ class monster : public character {
position next_monster_move_dumb(dungeon &d);
public:
monster(uint8_t x, uint8_t y);
monster(uint8_t x, uint8_t y, monster_description *desc, int speed, uint32_t abilities, int hitpoints, dice *damage, char symbol);
~monster();
bool is_player();
int has_characteristic(int bit);
position monster_move(dungeon &d);
void init_position(uint8_t x, uint8_t y);
int next_color();
void die();
};
void init_character_turn_heap(heap_t *h);
......
......@@ -116,6 +116,18 @@ extern const char object_symbol[] = {
'%', /* objtype_CONTAINER */
};
void monster_description::invalidate() {
valid = false;
}
monster *monster_description::make_monster(uint8_t x, uint8_t y) {
if (!valid) return 0;
if ((abilities & NPC_UNIQ) && instances > 0) return 0;
if (randrange(0, 99) >= (int)rarity) return 0;
return new monster(x, y, this, speed.roll(), abilities, hitpoints.roll(), &damage, symbol);
}
static inline void eat_whitespace(std::ifstream &f)
{
while (isspace(f.peek())) {
......
......@@ -12,6 +12,7 @@
# define OBJECT_DESC_FILE "object_desc.txt"
class dungeon;
class monster;
uint32_t parse_descriptions(dungeon &d);
uint32_t print_descriptions(dungeon &d);
......@@ -43,17 +44,19 @@ typedef enum object_type {
extern const char object_symbol[];
class monster_description {
private:
public:
std::string name, description;
char symbol;
std::vector<uint32_t> color;
int instances;
private:
char symbol;
uint32_t abilities;
dice speed, hitpoints, damage;
uint32_t rarity;
bool valid;
public:
monster_description() : name(), description(), symbol(0), color(0),
abilities(0), speed(), hitpoints(), damage(),
rarity(0)
monster_description() : name(), description(), color(0), instances(0), symbol(0),
abilities(0), speed(), hitpoints(), damage(), rarity(0), valid(true)
{
}
void set(const std::string &name,
......@@ -67,6 +70,9 @@ class monster_description {
const uint32_t rarity);
std::ostream &print(std::ostream &o);
char get_symbol() { return symbol; }
monster *make_monster(uint8_t x, uint8_t y);
void invalidate();
};
class object_description {
......@@ -114,6 +120,8 @@ class object_description {
inline const dice &get_speed() const { return speed; }
inline const dice &get_attribute() const { return attribute; }
inline const dice &get_value() const { return value; }
//object *make_object();
};
std::ostream &operator<<(std::ostream &o, monster_description &m);
......
......@@ -61,67 +61,97 @@ const char *lose_string[] = {
};
void init_screen() {
// Initialize ncurses screen
initscr();
set_escdelay(0);
// Unbuffered input
// Initialize ncurses screen
initscr();
start_color();
init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
timeout(100);
set_escdelay(0);
// Unbuffered input
cbreak();
// Don't echo back characters that are typed
// Don't echo back characters that are typed
noecho();
// Hide the cursor
curs_set(0);
nonl();
intrflush(stdscr, FALSE);
// Make it so keypad characters do what we expect
keypad(stdscr, TRUE);
// Clear the screen
// Hide the cursor
curs_set(0);
nonl();
intrflush(stdscr, FALSE);
// Make it so keypad characters do what we expect
keypad(stdscr, TRUE);
// Clear the screen
clear();
}
void destroy_screen() {
endwin();
endwin();
}
void display_message(const char *fmt, ...) {
move(0, 0);
clrtoeol();
move(0, 0);
va_list args;
va_start(args, fmt);
vwprintw(stdscr, fmt, args);
va_end(args);
attron(COLOR_PAIR(COLOR_WHITE));
move(0, 0);
clrtoeol();
move(0, 0);
va_list args;
va_start(args, fmt);
vwprintw(stdscr, fmt, args);
va_end(args);
attroff(COLOR_PAIR(COLOR_WHITE));
}
void refresh_screen() {
refresh();
refresh();
}
const char *instruction = "Press any key to exit.";
void display_win() {
int i;
clear();
for (i = 0; i < 23; i++) {
mvaddstr(i, 0, win_string[i]);
}
mvaddstr(23, (80 - strlen(instruction)) / 2, instruction);
refresh();
getch();
void display_win() {
attron(COLOR_PAIR(COLOR_WHITE));
int i;
clear();
for (i = 0; i < 23; i++) {
mvaddstr(i, 0, win_string[i]);
}
mvaddstr(23, (80 - strlen(instruction)) / 2, instruction);
refresh();
while(getch()==-1);
attroff(COLOR_PAIR(COLOR_WHITE));
}
void display_lose() {
attron(COLOR_PAIR(COLOR_WHITE));
int i;
for (i = 0; i < 23; i++) {
mvaddstr(i, 0, lose_string[i]);
}
mvaddstr(23, (80 - strlen(instruction)) / 2, instruction);
refresh();
while(getch()==-1);
attroff(COLOR_PAIR(COLOR_WHITE));
}
void display_lose() {
int i;
for (i = 0; i < 23; i++) {
mvaddstr(i, 0, lose_string[i]);
}
mvaddstr(23, (80 - strlen(instruction)) / 2, instruction);
refresh();
getch();
void print_char(char c, int color) {
attron(COLOR_PAIR(color));
addch(c);
attroff(COLOR_PAIR(color));
}
\ No newline at end of file
......@@ -17,5 +17,6 @@ void refresh_screen();
void destroy_screen();
void display_win();
void display_lose();
void print_char(char c, int color);
#endif
This diff is collapsed.
......@@ -17,72 +17,72 @@ class character;
class room {
public:
uint8_t x;
uint8_t y;
uint8_t w;
uint8_t h;
room();
uint8_t x;
uint8_t y;
uint8_t w;
uint8_t h;
room();
};
class dungeon {
public:
uint8_t hardness[MAP_HEIGHT][MAP_WIDTH];
bool hardness_dirty;
std::vector<monster_description> monster_descriptions;
std::vector<object_description> object_descriptions;
uint8_t pc_sight[MAP_HEIGHT][MAP_WIDTH];
char terrain[MAP_HEIGHT][MAP_WIDTH];
char remembered_terrain[MAP_HEIGHT][MAP_WIDTH];
uint16_t room_count;
room* room_list;
uint16_t upstair_count;
position* upstair_list;
uint16_t downstair_count;
position* downstair_list;
uint8_t hardness[MAP_HEIGHT][MAP_WIDTH];
bool hardness_dirty;
std::vector<monster_description> monster_descriptions;
std::vector<object_description> object_descriptions;
uint8_t pc_sight[MAP_HEIGHT][MAP_WIDTH];
char terrain[MAP_HEIGHT][MAP_WIDTH];
char remembered_terrain[MAP_HEIGHT][MAP_WIDTH];
uint16_t room_count;
room* room_list;
uint16_t upstair_count;
position* upstair_list;
uint16_t downstair_count;
position* downstair_list;
position player_pos;
character *characters[MAP_HEIGHT][MAP_WIDTH];
private:
bool fog_of_war;
uint8_t fow_map[MAP_HEIGHT][MAP_WIDTH];
bool target_mode;
position targeting_pointer;
void generate_rooms();
void generate_corridors();
void connect_rooms(int room1, int room2);
void init_dungeon_hardness();
void generate_stairs();
char get_map_char(int y, int x);
bool fog_of_war;
uint8_t fow_map[MAP_HEIGHT][MAP_WIDTH];
bool target_mode;
position targeting_pointer;
void generate_rooms();
void generate_corridors();
void connect_rooms(int room1, int room2);
void init_dungeon_hardness();
void generate_stairs();
void draw_map_char(int y, int x);
public:
dungeon();
~dungeon();
void gen_random_dungeon();
void init_turn_heap(heap_t *h);
void gen_monsters(int nummon);
void draw();
void free_data();
void toggle_fog_of_war();
void update_fog_of_war();
int targeting_mode();
int display_monster_list();
dungeon();
~dungeon();
void gen_random_dungeon();
void init_turn_heap(heap_t *h);
void gen_monsters(int nummon);
void draw();
void free_data();
void toggle_fog_of_war();
void update_fog_of_war();
int targeting_mode();
int display_monster_list();
};
#endif
==7914== Memcheck, a memory error detector
==7914== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7914== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7914== Command: ./rlg327
==7914== Parent PID: 2447
==7914==
==7914==
==7914== HEAP SUMMARY:
==7914== in use at exit: 76,570 bytes in 333 blocks
==7914== total heap usage: 47,529 allocs, 47,196 frees, 2,483,347 bytes allocated
==7914==
==7914== LEAK SUMMARY:
==7914== definitely lost: 0 bytes in 0 blocks
==7914== indirectly lost: 0 bytes in 0 blocks
==7914== possibly lost: 0 bytes in 0 blocks
==7914== still reachable: 76,570 bytes in 333 blocks
==7914== suppressed: 0 bytes in 0 blocks
==7914== Rerun with --leak-check=full to see details of leaked memory
==7914==
==7914== For counts of detected and suppressed errors, rerun with: -v
==7914== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
......@@ -6,7 +6,6 @@
#include "character.h"
#include "dungeon.h"
#include "descriptions.h"
#include "draw_dungeon.h"
#include "distance_map.h"
#include "line_of_sight.h"
......@@ -25,15 +24,7 @@ void regen_dungeon(dungeon &d, heap_t *h, int nummon) {
calc_line_of_sight(d);
}
int main(int argc, char* argv[]) {
dungeon d;
parse_descriptions(d);
print_descriptions(d);
destroy_descriptions(d);
return 0;
int main(int argc, char* argv[]) {
int i;
args args;
......@@ -41,6 +32,8 @@ int main(int argc, char* argv[]) {
srand(args.seed);
dungeon d;
if (args.load) {
load_dungeon(d);
} else {
......@@ -76,6 +69,7 @@ int main(int argc, char* argv[]) {
game_won = 0;
break;
} else {
((monster *)c)->die();
delete c;
if (h.size == 1) {
// Only one character left and the game isn't over, the player must have won
......@@ -100,6 +94,12 @@ int main(int argc, char* argv[]) {
while(!handled_move) {
key = getch();
if (key == -1) {
d.draw();
refresh_screen();
continue;
}
if (key == 'Q' || key == 'q') {
game_won = -1;
break;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment