added game restart

AuthorKonata <konata@posteo.jp>
Date
Commit0994cd0eb149aed8e3d4819aa3d57aaeaccfad5a
Parentdf62e72
7 files changed, 75 insertions(+), 73 deletions(-)
▾Minclude/algorithm.h
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <game.h>
//creates a game, fills it with walls and empty fields
struct game make_maze(size_t y, size_t x);
typedef darray(struct point) pointarr;
▾Minclude/game.h
@@ -141,6 +141,7 @@ struct choice
}u;
};
//returns a point that is relative to p in the direction d
static inline struct point relative(struct point p, enum direction d)
{
switch(d)
@@ -166,7 +167,8 @@ static inline bool in_bounds(struct game *g, struct point p)
return false;
}
static inline void spawn_enemy(struct game *g)
//randomly puts an enemy in an empty spot on the map
static inline void spawn_enemy(struct game *g)
{
while(true)
{
@@ -179,5 +181,6 @@ static inline void spawn_enemy(struct game *g)
}
}
void loop(); //main game loop
#endif
▾Dinclude/loop.h
-7
@@ -1,7 +0,0 @@
#ifndef LOOP_H
#define LOOP_H
void loop(struct game *g);
#endif //LOOP_H
▾Minclude/tui.h
@@ -6,9 +6,9 @@
#include <stddef.h>
bool setup(); //setups screens, doesn't redaw contents
void printlog();
void printlog(); //clears & reprints the log window
void logstr(const char *format, ...); //echoes printf string to the logwindow TODO: fix multiline log
void charclear();
void charclear(); //clears the character screen
void charprint(const char *format, ...); //echoes printf string to the charwindow
void log_scroll(enum direction d); //scrolls the log up or down
void draw_map(const struct game *g, struct point p); //draws the map around the player
@@ -18,8 +18,4 @@ typedef bool(itemselectfn)(struct monster *m, size_t i); //returns true if curso
void itemselect(struct monster *m, itemselectfn f); //provides an inventory screen, calls f when the space is pressed on an item
//TODO: create general select screen
extern size_t logindex;
extern size_t loglength;
extern char **logs;
#endif //TUI_H
▾Msrc/algorithm.c
@@ -31,10 +31,10 @@ static bool maze_in_bounds(size_t ys, size_t xs, struct point p)
struct game make_maze(size_t y, size_t x)
{
bool yeven = (y%2 == 0);
bool xeven = (x%2 == 0);
y += yeven; //it must be an uneven number to look fine
x += xeven;
assert(y >= 5);
assert(y >= 5);
y += (y%2 == 0); //it must be an uneven number to look fine
x += (x%2 == 0);
struct game g = create_game(y, x);
char *maze = xmalloc(y * x + 1);
▾Msrc/loop.c
@@ -14,12 +14,13 @@
#include <tui.h>
#include <algorithm.h>
#include <config.h>
#include <items.h>
#define NOOBJ_OBJECT (struct object){.type = NOOBJ, .symbol = ' '}
unsigned m_id = 0;
struct choice get_input(void)
static struct choice get_input(void)
{
struct choice c;
@@ -69,6 +70,7 @@ start:;
return c;
}
//adds xp to m, increases stats and opens a messagebox
static void addxp(struct monster *m, unsigned xp)
{
m->xp += xp;
@@ -83,8 +85,11 @@ static void addxp(struct monster *m, unsigned xp)
}
}
//inflicts src's damage to target, removes targets monster if hp goes to zero
//gives src xp if target is killed
static void attack(struct monster *src, struct field *target)
{
assert(target->has_monster);
if(src->isplayer)
logstr("%s hit %s for %d damage", src->name, target->m.name, src->dmg);
@@ -104,6 +109,7 @@ static void attack(struct monster *src, struct field *target)
}
}
//returns true if adding was successful, otherwise false
static bool additem(struct monster *m, struct item *it)
{
darray_append(m->items, *it);
@@ -115,7 +121,9 @@ static void rmvitem(struct monster *m, size_t i)
darray_remove(m->items, i);
}
bool inventorycallback(struct monster *m, size_t i)
//called by itemselect, uses an item if its usable
//equips it and does stat recalculation if its an equip
static bool inventorycallback(struct monster *m, size_t i)
{
struct item *it = &darray_item(m->items,i);
if(it->type == USE) {
@@ -138,16 +146,17 @@ bool inventorycallback(struct monster *m, size_t i)
return false;
}
void inventory(struct monster *m)
static void inventory(struct monster *m)
{
itemselect(m, inventorycallback);
}
//moves the object in src to target if target is empty
//puts an item in the inventory of src if src is a monster and target contains an item
//TODO: player moves on target, create new map
struct point move_object(struct game *g, struct point src, struct point target)
static struct point move_object(struct game *g, struct point src, struct point target)
{
if(game_at(g, target)->u->ground.type == NOOBJ && !game_at(g, target)->has_monster) {
if((game_at(g, target)->u->ground.type == NOOBJ || game_at(g, target)->u->ground.type == TARGET) && !game_at(g, target)->has_monster) {
game_at(g, target)->has_monster = true;
game_at(g, target)->m = game_at(g, src)->m;
game_at(g, src)->has_monster = false;
@@ -180,7 +189,7 @@ static inline struct point attack_move(struct game *g, struct point src, struct
return src;
}
void run_ai(struct game *g, struct point player)
static void run_ai(struct game *g, struct point player)
{
darray(unsigned) checked = darray_new();
for(size_t y = 0; y < g->ys; y++)
@@ -219,19 +228,12 @@ void run_ai(struct game *g, struct point player)
darray_free(checked);
}
void loop(struct game *g)
//creates game and spawns loot and enemies
static struct game setup_game()
{
/*
"\
███████╗██████╗ ██╗ ██╗ ███╗ ██╗███████╗ ██████╗██╗ ██╗ █████╗ ██████╗ ██████╗ ███████╗███╗ ███╗██╗ ██╗███████╗███╗ ██╗██████╗ \n\
██╔════╝██╔══██╗██║ ██║ ████╗ ██║██╔════╝██╔════╝██║ ██╔╝██╔══██╗██╔══██╗██╔════╝ ██╔════╝████╗ ████║██║ ██║██╔════╝████╗ ██║██╔══██╗\n\
███████╗██████╔╝███████║ ██╔██╗ ██║█████╗ ██║ █████╔╝ ███████║██████╔╝██║ ███╗█████╗ ██╔████╔██║██║ ██║█████╗ ██╔██╗ ██║██║ ██║\n\
╚════██║██╔══██╗██╔══██║ ██║╚██╗██║██╔══╝ ██║ ██╔═██╗ ██╔══██║██╔══██╗██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██║\n\
███████║██║ ██║██║ ██║ ██║ ╚████║███████╗╚██████╗██║ ██╗██║ ██║██║ ██║╚██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝███████╗██║ ╚████║██████╔╝\n\
"
*/
game_at(g, (struct point){1,1})->m = (struct monster)
struct game g = make_maze(randrange(GAME_MIN_Y, GAME_MAX_Y), randrange(GAME_MIN_X, GAME_MAX_X));
game_at(&g, (struct point){1,1})->m = (struct monster) //TODO: keep player between levels
{
.symbol = 'P',
.id = -1,
@@ -244,7 +246,27 @@ void loop(struct game *g)
.items = darray_new(),
.isplayer = true
};
game_at(g, (struct point){1,1})->has_monster = true;
game_at(&g, (struct point){1,1})->has_monster = true;
size_t num_enemies = randrange(MIN_ENEMIES, MAX_ENEMIES);
for(size_t i = 0; i < num_enemies; i++)
{
spawn_enemy(&g);
}
size_t num_items = randrange(MIN_LOOT, MAX_LOOT);
for(size_t i = 0; i < num_items; i++)
{
spawn_item(&g);
}
return g;
}
void loop()
{
struct game g = setup_game();
struct point player = {1,1};
@@ -252,12 +274,12 @@ void loop(struct game *g)
{
charclear();
charprint("(づ。◕‿‿◕。)づ");
charprint("Name: %s", game_at(g, player)->m.name);
charprint("HP : %u/%u", game_at(g, player)->m.current_hp, game_at(g, player)->m.max_hp);
charprint("DMG: %u", game_at(g, player)->m.dmg);
charprint("LVL: %u", game_at(g, player)->m.level);
charprint("XP : %u", game_at(g, player)->m.xp);
draw_map(g, player);
charprint("Name: %s", game_at(&g, player)->m.name);
charprint("HP : %u/%u", game_at(&g, player)->m.current_hp, game_at(&g, player)->m.max_hp);
charprint("DMG: %u", game_at(&g, player)->m.dmg);
charprint("LVL: %u", game_at(&g, player)->m.level);
charprint("XP : %u", game_at(&g, player)->m.xp);
draw_map(&g, player);
struct choice c = get_input();
switch(c.a)
@@ -266,23 +288,30 @@ void loop(struct game *g)
logstr("Invalid input, try again");
continue;
case QUIT:
delete_game(&g);
return;
case MOVE:;
struct point targetpos = relative(player, c.u.d);
if(!in_bounds(g, targetpos)) {
if(!in_bounds(&g, targetpos)) {
logstr("Target not in bounds");
continue;
}
player = attack_move(g, player, targetpos);
run_ai(g, player);
player = attack_move(&g, player, targetpos);
if(game_at(&g, player)->u->ground.type == TARGET)
{
delete_game(&g);
loop();
return;
}
run_ai(&g, player);
break;
case SPAWN:
spawn_enemy(g);
spawn_enemy(&g);
break;
case INVENTORY:
inventory(&game_at(g, player)->m);
inventory(&game_at(&g, player)->m);
break;
case REDRAW:
setup();
▾Msrc/main.c
@@ -7,18 +7,11 @@
#include <locale.h>
#include <time.h>
#include <helper.h>
#include <tui.h>
#include <loop.h>
#include <game.h>
#include <algorithm.h>
#include <config.h>
#include <items.h>
#include <unistd.h>
int main()
{
srand(time(NULL));
@@ -26,20 +19,7 @@ int main()
setup();
logstr("Game started");
struct game g = make_maze(randrange(GAME_MIN_Y, GAME_MAX_Y), randrange(GAME_MIN_X, GAME_MAX_X));
size_t num_enemies = randrange(MIN_ENEMIES, MAX_ENEMIES);
for(size_t i = 0; i < num_enemies; i++)
{
spawn_enemy(&g);
}
size_t num_items = randrange(MIN_LOOT, MAX_LOOT);
for(size_t i = 0; i < num_items; i++)
{
spawn_item(&g);
}
loop(&g);
delete_game(&g);
loop();
}