game.h
Raw
1#ifndef GAME_H
2#define GAME_H
3#include <stddef.h>
4#include <stdbool.h>
5#include <assert.h>
6#include <helper.h>
7#include <darray.h>
8
9#define MAX(x,y) (x >= y ? x : y)
10#define MIN(x,y) (x <= y ? x : y)
11
12#define ORC (struct monster)\
13 {\
14 .symbol = 'O',\
15 .name = "Zog Zog", \
16 .id = m_id++, .current_hp = 10, .max_hp = 10, .dmg = 1,\
17 .level = 5 , .xp = 0, .items = darray_new(), .isplayer = false\
18 }
19
20#define EMPTYFIELD (struct object)\
21 {\
22 .type = NOOBJ,\
23 .symbol = ' ',\
24 }
25#define WALLFIELD (struct object)\
26 {\
27 .type = WALL,\
28 .symbol = '#',\
29 }
30
31extern unsigned m_id;
32
33enum objtype {NOOBJ = 0, MONSTER, ITEM, WALL, TARGET};
34enum itemtype {NOITEM = 0, EQUIP, USE};
35
36struct equip
37{
38 unsigned hp;
39 unsigned dmg;
40 bool isequipped;
41};
42
43struct use
44{
45 unsigned restorehp;
46};
47
48struct object
49{
50 enum objtype type;
51 char symbol;
52};
53
54struct item
55{
56 struct object o;
57 const char *name;
58 enum itemtype type;
59 union
60 {
61 struct equip e;
62 struct use u;
63 }u;
64};
65
66
67struct monster
68{
69 char symbol;
70 const char *name;
71 unsigned id;
72 unsigned current_hp;
73 unsigned max_hp;
74 unsigned dmg;
75 unsigned level;
76 unsigned xp;
77 darray(struct item) items;
78 bool isplayer;
79};
80
81struct field
82{
83 union
84 {
85 struct object ground;
86 struct item it;
87 } *u;
88 struct monster m;
89 bool has_monster;
90};
91
92struct game
93{
94 struct field *map;
95 size_t xs, ys;
96};
97
98static inline struct field *game_at(const struct game *g, struct point p)
99{
100 return &g->map[p.y * g->xs + p.x];
101}
102
103static inline struct game create_game(size_t y, size_t x)
104{
105 struct game ret;
106 ret.map = xmalloc(x * y * sizeof(*ret.map));
107 for(size_t i = 0; i < x*y; i++)
108 {
109 ret.map[i].u = xmalloc(sizeof(*ret.map[i].u));
110 ret.map[i].has_monster = false;
111 }
112 ret.xs = x;
113 ret.ys = y;
114
115 return ret;
116}
117
118static inline void delete_game(struct game *g)
119{
120 for(size_t y = 0; y < g->ys; y++)
121 {
122 for(size_t x = 0; x < g->xs; x++)
123 {
124 if(game_at(g, (struct point){y,x})->has_monster)
125 darray_free(game_at(g, (struct point){y,x})->m.items);
126 free(game_at(g, (struct point){y,x})->u);
127 }
128 }
129 free(g->map);
130}
131
132enum action {MOVE, SPAWN, QUIT, INVENTORY, REDRAW, INVALID};
133enum direction {UP,DOWN,LEFT,RIGHT};
134
135struct choice
136{
137 enum action a;
138 union
139 {
140 enum direction d;
141 }u;
142};
143
144//returns a point that is relative to p in the direction d
145static inline struct point relative(struct point p, enum direction d)
146{
147 switch(d)
148 {
149 case UP:
150 return (struct point){p.y - 1, p.x};
151 case DOWN:
152 return (struct point){p.y + 1, p.x};
153 case LEFT:
154 return (struct point){p.y, p.x - 1};
155 case RIGHT:
156 return (struct point){p.y, p.x + 1};
157 default:
158 assert(false);
159 }
160}
161
162static inline bool in_bounds(struct game *g, struct point p)
163{
164 if(p.y >= 0 && p.y < g->ys && p.x >= 0 && p.x < g->xs)
165 return true;
166 else
167 return false;
168}
169
170//randomly puts an enemy in an empty spot on the map
171static inline void spawn_enemy(struct game *g)
172{
173 while(true)
174 {
175 struct point p = {randrange(0, g->ys), randrange(0, g->xs)};
176 if(in_bounds(g, p) && game_at(g, p)->u->ground.type != WALL && !game_at(g, p)->has_monster) {
177 game_at(g, p)->m = ORC;
178 game_at(g, p)->has_monster = true;
179 break;
180 }
181 }
182}
183
184void loop(); //main game loop
185
186#endif
187