-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtypes.h
374 lines (319 loc) · 12.5 KB
/
types.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#ifndef TYPES_H_
#define TYPES_H_
#include "header.h"
// TODO need to add a queue<pair<int,int>>
// pair<float,float>
// used for recording dynamically changing coordinate
typedef struct {
float first, second;
} FloatPair;
FloatPair make_FloatPair(float f1, float f2) { return (FloatPair){f1, f2}; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pair<int,int>
// used for saving coordinates
typedef struct {
int first, second;
} IntPair; // FIXME not using, should be removed or used
IntPair make_IntPair(int i1, int i2) { return (IntPair){i1, i2}; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct __INT_PAIR_NODE__ {
IntPair data;
struct __INT_PAIR_NODE__ *next;
} IntPairNode; // FIXME not using, should be removed or used
// list<pair<int,int>>
// used for saving coordinates
/// TODO remove it and rewrite it in a better way
typedef struct {
IntPairNode *head, *rear;
int size;
} IntPairList; // FIXME not using, should be removed or used
IntPairList *new_IntPairList() {
IntPairList *l = malloc(sizeof(IntPairList));
*l = (IntPairList){NULL, NULL, 0};
return l;
}
void IntPairList_push(IntPairList *l, IntPair p) {
if (!l->size) l->head = malloc(sizeof(IntPairNode)), l->rear = l->head;
else l->rear->next = malloc(sizeof(IntPairNode)), l->rear = l->rear->next;
*(l->rear) = (IntPairNode){p, NULL}, l->size++;
}
void IntPairList_clear(IntPairList *l) {
IntPairNode *ptr = l->head, *tmp;
while (ptr != NULL) {
tmp = ptr;
ptr = ptr->next;
free(tmp);
}
free(l);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// triple<int,int,int>
typedef struct {
int first, second, third;
} IntTriple;
IntTriple make_IntTriple(int i1, int i2, int i3) { return (IntTriple){i1, i2, i3}; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct __INT_TRIPLE_NODE__ {
IntTriple data;
struct __INT_TRIPLE_NODE__ *next;
} IntTripleNode;
// stack<triple<int, int, int>>
typedef struct {
IntTripleNode *top;
int size;
} IntTripleStack;
IntTripleStack *new_IntTripleStack() {
IntTripleStack *s = malloc(sizeof(IntTripleStack));
*s = (IntTripleStack){NULL, 0};
return s;
}
IntTriple IntTripleStack_top(IntTripleStack *s) { return s->size > 0 ? s->top->data : make_IntTriple(-1, -1, -1); }
void IntTripleStack_push(IntTripleStack *s, IntTriple t) {
IntTripleNode *tmp = malloc(sizeof(IntTripleNode));
*tmp = (IntTripleNode){t, s->top};
s->top = tmp, s->size++;
}
void IntTripleStack_pop(IntTripleStack *s) {
if (s->size <= 0) return;
IntTripleNode *tmp = s->top;
s->top = s->top->next;
free(tmp);
s->size--;
}
void IntTripleStack_clear(IntTripleStack *s) {
IntTripleNode *ptr = s->top, *tmp;
while (ptr != NULL) {
tmp = ptr;
ptr = ptr->next;
free(tmp);
}
free(s);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
char *data;
int front, size;
} CharArray;
CharArray *new_CharArray(int n) {
if (n <= 0) return NULL;
CharArray *a = malloc(sizeof(CharArray));
*a = (CharArray){malloc((unsigned)n * sizeof(char)), 0, 0};
return a;
}
void CharArray_push_back(CharArray *a, char c) { a->data[a->front + a->size++] = c; }
char CharArray_pop_front(CharArray *a) {
a->size--;
return a->data[a->front++];
}
void CharArray_clear(CharArray *a) {
free(a->data);
free(a);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
char **data;
// @ wall
//' ' path
// 0 +HP
// 1 -HP
// 2 +ATK
// 3 -ATK
// 4 +DEF
// 5 -DEF
// 6 enemy
// 7 watchtower
// 8 gain item
// 9 -
// P player
// B boss
int row, col, path, walked;
} Map;
Map *new_Map(int r, int c) {
if (r <= 0 || c <= 0) return NULL;
Map *m = malloc(sizeof(Map));
char **tmp = malloc((unsigned)r * sizeof(char *));
for (int i = 0; i < r; i++) tmp[i] = memset(malloc((unsigned)c * sizeof(char)), '@', (unsigned)c * sizeof(char));
*m = (Map){tmp, r, c, (r * c - r - c - 1) / 2, 0};
return m;
}
void Map_clear(Map *m) {
for (int i = 0; i < m->row; i++) free(m->data[i]);
free(m->data);
free(m);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
int life, hp, max_hp;
int atk, def, crit, dir;
int watchTowerCnt;
bool sheild_enabled;
IntPair pos;
int backpack[ITEM_TYPES];
// item
// 0 teleport: randomly teleport to another place
// 1 blood++: use in battle, heal you life by 5
// 2 defense: use in battle, 90% chance ignore next monster's attack
// 3 Magic compass: see items on the map
} PlayerData;
PlayerData *new_PlayerData() {
PlayerData *p = malloc(sizeof(PlayerData));
p->life = 5;
p->hp = 10;
p->max_hp = 10;
p->atk = 3;
p->def = 3;
p->crit = 10;
p->watchTowerCnt = 0;
p->sheild_enabled = false;
#ifdef DEBUG
p->life = 99;
p->hp = 15;
p->max_hp = 15;
p->atk = 999;
p->def = 999;
p->crit = 99;
p->watchTowerCnt = 0;
p->sheild_enabled = false;
#endif
for (unsigned i = 0; i < ITEM_TYPES; i++) p->backpack[i] = 0; // currently 4 types of item
#ifdef DEBUG
for (unsigned i = 0; i < ITEM_TYPES; i++) p->backpack[i] = 50;
#endif
p->dir = 0;
return p;
}
void PlayerData_clear(PlayerData *p) { free(p); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
int boss_state; // TODO decide boss states
// 0 not boss
// 1
// 2
int atk;
int def;
int hp;
int max_hp;
int crit;
float move_ratio[3];
} Enemy;
Enemy *new_Enemy(PlayerData *p, bool boss) {
Enemy *e = malloc(sizeof(Enemy));
e->boss_state = boss;
if (boss) {
e->atk = rand_between(p->hp / 4 + 1, p->hp / 3 + 1);
e->def = rand_between(p->atk / 7 + 1, p->atk / 2 + 1);
e->hp = p->max_hp + 20;
e->max_hp = e->hp;
e->crit = rand_between(40, 80);
} else {
e->atk = rand_between(p->hp / 10 + 1, p->hp / 3 + 1);
e->def = rand_between(p->atk / 7 + 1, p->atk / 2 + 1);
e->hp = p->max_hp + rand_between(-5, 5);
e->max_hp = e->hp;
e->crit = rand_between(0, 10);
}
// prob of paper, sccisor, stone
// TODO maybe switch to a better way to generate the ratio
float sum = 0;
for (int i = 0; i < 3; i++) e->move_ratio[i] = (float)rand() / (float)RAND_MAX, sum += e->move_ratio[i];
for (int i = 0; i < 3; i++) e->move_ratio[i] /= sum; // normalize to make the sum = 1
return e;
}
void Enemy_clear(Enemy *e) { free(e); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
int frames;
int row;
int col;
char ***data;
} Animation;
/// @note test on null pointer is not sufficient to indicate that the animation is loaded correctly (important)
Animation *new_Animation(const char *filename) { // FIXME const
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Failed to open file: %s\n", filename);
fclose(file);
return NULL;
}
Animation *ani = malloc(sizeof(Animation));
if (fscanf(file, "%d", &(ani->frames)) == EOF || fscanf(file, "%d", &(ani->row)) == EOF || fscanf(file, "%d", &(ani->col)) == EOF || fgetc(file) != '\n') {
printf("%s: file is incomplete!\n", filename);
free(ani);
fclose(file);
return NULL;
}
// allocate memory & read from file
ani->data = malloc((unsigned)ani->frames * sizeof(char **));
for (int i = 0; i < ani->frames; i++) {
ani->data[i] = malloc((unsigned)ani->row * sizeof(char *));
for (int j = 0; j < ani->row; j++) {
ani->data[i][j] = malloc((unsigned)(ani->col + 1) * sizeof(char)); // +1 for null terminator
if (fgets(ani->data[i][j], ani->col + 1, file) == NULL) printf("%s: file is incomplete! can't fix now, plz clear it\n", filename);
else ani->data[i][j][strcspn(ani->data[i][j], "\n")] = '\0'; // remove trailing newline
#ifdef DEBUG
printf("frame: %-3d line: %-3d content: %s\n", i, j, ani->data[i][j]);
#endif
}
}
fclose(file);
return ani;
}
void Animation_clear(Animation *ani) {
if (ani == NULL) return;
for (int i = 0; i < ani->frames; i++) {
for (int j = 0; j < ani->row; j++) {
free(ani->data[i][j]);
}
free(ani->data[i]);
}
free(ani->data);
free(ani);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct {
int watchTowerCnt;
int status;
int round;
bool *items_enabled;
bool isCrit;
float damage;
bool input_locked;
bool is_boss;
int gained_item;
char event;
int last_enemy_move;
int last_player_move;
IntPairList *playerPath;
} Game;
Game *new_Game() {
Game *g = malloc(sizeof(Game));
g->status = 0;
g->round = 0;
// 0: menu
// 1: instruction?
// 2: map
// 3: fight
// 8: win
// 9: game over?
g->event = '9';
g->input_locked = false;
g->is_boss = false;
g->items_enabled = malloc(sizeof(bool) * (sizeof(items_ratio) / sizeof(float)));
for (unsigned i = 0; i < sizeof(items_ratio) / sizeof(float); i++) g->items_enabled[i] = false;
return g;
}
void Game_clear(Game *g) {
free(g->items_enabled);
free(g);
}
#endif