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 size_t res = y * x;
106 if (y != 0 && res / y != x) {
107 assert(false);
108 }
109 struct game ret;
110 ret.map = xmalloc(x * y * sizeof(*ret.map));
111 ret.xs = x;
112 ret.ys = y;
113
114 for(size_t i = 0; i < x*y; i++)
115 {
116 ret.map[i].u = xmalloc(sizeof(*ret.map[i].u));
117 ret.map[i].has_monster = false;
118 }
119
120 return ret;
121}
122
123static inline void delete_game(struct game *g)
124{
125 for(size_t y = 0; y < g->ys; y++)
126 {
127 for(size_t x = 0; x < g->xs; x++)
128 {
129 if(game_at(g, (struct point){y,x})->has_monster)
130 darray_free(game_at(g, (struct point){y,x})->m.items);
131 free(game_at(g, (struct point){y,x})->u);
132 }
133 }
134 free(g->map);
135}
136
137enum action {MOVE, SPAWN, QUIT, INVENTORY, REDRAW, INVALID};
138enum direction {UP,DOWN,LEFT,RIGHT};
139
140struct choice
141{
142 enum action a;
143 union
144 {
145 enum direction d;
146 }u;
147};
148
149//returns a point that is relative to p in the direction d
150static inline struct point relative(struct point p, enum direction d)
151{
152 switch(d)
153 {
154 case UP:
155 return (struct point){p.y - 1, p.x};
156 case DOWN:
157 return (struct point){p.y + 1, p.x};
158 case LEFT:
159 return (struct point){p.y, p.x - 1};
160 case RIGHT:
161 return (struct point){p.y, p.x + 1};
162 default:
163 assert(false);
164 }
165}
166
167static inline bool in_bounds(struct game *g, struct point p)
168{
169 if(p.y >= 0 && (size_t)p.y < g->ys && p.x >= 0 && (size_t)p.x < g->xs)
170 return true;
171 else
172 return false;
173}
174
175//randomly puts an enemy in an empty spot on the map
176static inline void spawn_enemy(struct game *g)
177{
178 while(true)
179 {
180 struct point p = {randrange(0, g->ys), randrange(0, g->xs)};
181 if(in_bounds(g, p) && game_at(g, p)->u->ground.type != WALL && !game_at(g, p)->has_monster) {
182 game_at(g, p)->m = ORC;
183 game_at(g, p)->has_monster = true;
184 break;
185 }
186 }
187}
188
189void loop(); //main game loop
190
191#endif
192