#ifndef GAME_H #define GAME_H #include #include #include #include #include #define MAXITEMS 10 extern unsigned m_id; enum objtype {NOOBJ = 0, MONSTER, ITEM, WALL, TARGET}; enum itemtype {NOITEM = 0, EQUIP, USE}; struct equip { unsigned hp; unsigned dmg; bool isequipped; }; struct use { unsigned restorehp; }; struct item { const char *name; enum itemtype type; union { struct equip e; struct use u; }u; }; struct monster { const char *name; unsigned id; unsigned current_hp; unsigned max_hp; unsigned dmg; unsigned level; unsigned xp; darray(struct item) items; bool isplayer; }; static inline size_t item_len(const struct monster *m) { for(size_t i = 0; i < MAXITEMS; i++) { if(darray_item(m->items, i).type == NOITEM) return i; } return MAXITEMS; } struct object { enum objtype type; char symbol; union { struct monster m; struct item i; } u; }; struct game { struct object *map; size_t xs, ys; }; static inline struct object *game_at(const struct game *g, struct point p) { return &g->map[p.y * g->xs + p.x]; } static inline struct game create_game(size_t y, size_t x) { struct game ret; ret.map = xmalloc(x * y * sizeof * ret.map); ret.xs = x; ret.ys = y; return ret; } static inline void delete_game(struct game *g) { for(size_t y = 0; y < g->ys; y++) { for(size_t x = 0; x < g->xs; x++) { if(game_at(g, (struct point){y,x})->type == MONSTER) darray_free(game_at(g, (struct point){y,x})->u.m.items); } } free(g->map); } enum action {MOVE, SPAWN, QUIT, INVENTORY, REDRAW, INVALID}; enum direction {UP,DOWN,LEFT,RIGHT}; struct choice { enum action a; union { enum direction d; }u; }; #define MAX(x,y) (x >= y ? x : y) #define MIN(x,y) (x <= y ? x : y) #define ORC (struct object)\ {\ .type = MONSTER,\ .symbol = 'O',\ .u.m = {"Zog Zog", m_id++, 10, 10, 1, 5 , 0, darray_new(), false}\ } #define EMPTYFIELD (struct object)\ {\ .type = NOOBJ,\ .symbol = ' ',\ } #define WALLFIELD (struct object)\ {\ .type = WALL,\ .symbol = '#',\ } static inline struct point relative(struct point p, enum direction d) { switch(d) { case UP: return (struct point){p.y - 1, p.x}; case DOWN: return (struct point){p.y + 1, p.x}; case LEFT: return (struct point){p.y, p.x - 1}; case RIGHT: return (struct point){p.y, p.x + 1}; default: assert(false); } } static inline bool in_bounds(struct game *g, struct point p) { if(p.y >= 0 && p.y < g->ys && p.x >= 0 && p.x < g->xs) return true; else return false; } static inline void spawn_enemy(struct game *g) { while(true) { struct point p = {randrange(0, g->ys), randrange(0, g->xs)}; if(in_bounds(g, p) && game_at(g, p)->type == NOOBJ) { *game_at(g, p) = ORC; break; } } } #endif