Newer
Older
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
#include "input_manager.h"
extern int defeat;
extern int win;
//return 1 if the value given in parameter is in the list.
int in_list(int value, int *list, int len){
for (int i = 0; i<len; i++){
if (list[i]==value){
return 1;
}
}
return 0;
}
// apply the movement from (y,x) and to direction d1 first then d2 if possible.
void make_move(monsters* mon, map* m, int y, int x, direction d1, direction d2){
int y1=y, x1=x;
switch (d1)
{
case DIR_UP:
y1 = y - 1;
break;
case DIR_DOWN:
y1 = y + 1;
break;
case DIR_RIGHT:
x1 = x + 1;
break;
case DIR_LEFT:
x1 = x - 1;
break;
default:
break;
}
int y2=y1, x2=x1;
switch (d2){
case DIR_UP: y2 = y1-1; break;
case DIR_DOWN: y2 = y1+1; break;
case DIR_RIGHT: x2 = x1+1; break;
case DIR_LEFT: x2 = x1-1; break;
default : break;
}
update_monster(mon,m,y,x,y1,x1);
//apply_events(game);
if (d2 != DIR_UNKNOWN){
update_monster(mon,m,y1,x1,y2,x2);
}
}
// verify if a move is possible and apply it if so
int ok_move(monsters* mon, map* m, int y, int x, direction d1, direction d2){
int y1 = y, x1 = x;
switch (d1){
case DIR_UP: y1 = y-1; break;
case DIR_DOWN: y1 = y+1; break;
case DIR_RIGHT: x1 = x+1; break;
case DIR_LEFT: x1 = x-1; break;
default : break;
}
int y2=y1, x2=x1;
switch (d2){
case DIR_UP: y2 = y1-1; break;
case DIR_DOWN: y2 = y1+1; break;
case DIR_RIGHT: x2 = x1+1; break;
case DIR_LEFT: x2 = x1-1; break;
default : break;
}
if (d2 == DIR_UNKNOWN){
if (!is_obstacle(m->tiles[y1][x1])){
make_move(mon,m,y,x,d1,d2);
return 1;
}
} else if (!is_obstacle(m->tiles[y1][x1]) && !is_obstacle(m->tiles[y2][x2])){
make_move(mon,m,y,x,d1,d2);
return 1;
} else if (!is_obstacle(m->tiles[y1][x1])){
make_move(mon,m,y,x,d1,DIR_UNKNOWN);
return 1;
}
return 0;
}
// move the monster to the right or the left depending on the player's position
int move_up_or_down(monsters* mon, map* m, int y_monster, int x_monster, int y_player){
if (y_monster > y_player)
return ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_UP);
else if (y_monster < y_player)
return ok_move(mon, m, y_monster,x_monster, DIR_DOWN, DIR_DOWN);
return 0;
}
// move the monster to the right or the left depending on the player's position
int move_left_or_right(monsters* mon, map* m, int y_monster, int x_monster, int x_player){
if (x_monster > x_player)
return ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_LEFT);
else if (x_monster < x_player)
return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_RIGHT);
return 0;
}
// move the monster to one of the four corners
int move_to_corner(monsters* mon, map* m, int y_monster, int x_monster, int y_player, int x_player){
if (x_monster > x_player && y_monster > y_player)
return ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_LEFT) || ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_UP);
else if (x_monster > x_player && x_monster < y_player)
return ok_move(mon, m, y_monster,y_player, DIR_DOWN, DIR_LEFT) || ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_DOWN);
else if (x_monster < x_player && y_monster > y_player)
return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_UP) || ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_RIGHT);
else if (x_monster < x_player && y_monster < y_player)
return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_DOWN) || ok_move(mon, m, y_monster,x_monster, DIR_DOWN, DIR_RIGHT);
return 0;
}
int follow_player(monsters* mon, map* m, int * y, int * x){
int y_monster = *y;
int x_monster = *x;
int y_player = m->player_y, x_player = m->player_x;
if (x_player == x_monster){ // same column
return move_up_or_down(mon, m, y_monster, x_monster, y_player);
} else if (y_monster==y_player){ // same line
return move_left_or_right(mon, m, y_monster, x_monster, x_player);
} else if ((x_player==x_monster+1 || x_player==x_monster-1) && (y_player==y_monster+1 || y_player==y_monster-1)){ // corners
return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player);
} else if (x_player==x_monster+1 || x_player==x_monster-1){ // one tile to the left or the right
#ifdef line_first
return move_up_or_down(mon, m, y_monster, x_monster, x_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player);
#else
return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player);
#endif
} else if (y_player==y_monster+1 || y_player==y_monster-1){ // one tile upper or lower
#ifdef line_first
return move_left_or_right(mon, m, y_monster, x_monster, x_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player);
#else
return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_left_or_right(mon, m, y_monster, x_monster, x_player);
#endif
} else {
#ifdef line_first
return move_left_or_right(mon, m, y_monster, x_monster, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player);
#else
#endif
return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player) || move_left_or_right(mon, m, y_monster, x_monster, x_player);
}
}
void circle(monsters* mon, map* m, int y, int x) {
if (y == 6 && x != 6 && m->tiles[y][x-1] != 'M')
update_monster(mon,m,y,x,y,x-1); // left
else if (y == 4 && x!=10 && m->tiles[y][x+1] != 'M')
update_monster(mon,m,y,x,y,x+1); //right
else if(x == 6 && y!=4 && m->tiles[y-1][x] != 'M')
update_monster(mon,m,y,x,y-1,x); //up
else if(x == 10 && y!=6 && m->tiles[y+1][x] != 'M')
update_monster(mon,m,y,x,y+1,x); //down
}
int search_monster(monsters* mon, map* m, int y, int x) {
for (int i = 0; i < mon->length; i++)
{
if (mon->info[i].x == x && mon->info[i].y == y)
return i;
}
return -1;
}
void come_and_go(monsters* mon, map * m, int y, int x){
int monster_id = search_monster(mon, m, y, x);
if (monster_id == -1)
return;
int dir = mon->info[monster_id].dir;
if(x==m->width-2 || m->tiles[y][x+1] == '@' || m->tiles[y][x+1] == 'M') {
mon->info[monster_id].dir = DIR_LEFT;
update_monster(mon,m,y,x,y,x-1);
}
else if (x == 2 || m->tiles[y][x-1] == 'M') {
mon->info[monster_id].dir = DIR_RIGHT;
update_monster(mon,m,y,x,y,x+1);
}
else if (dir == DIR_RIGHT)
update_monster(mon,m,y,x,y,x+1);
else if (dir == DIR_LEFT)
update_monster(mon,m,y,x,y,x-1);
else if (dir == DIR_DOWN) {
mon->info[monster_id].dir = DIR_LEFT;
update_monster(mon,m,y,x,y,x-1);
}
}
// verify if the player is seen by the monster
void is_player_seen(monsters* mon, map * m, int y, int x){
int monster_id = search_monster(mon, m, y, x);
if (monster_id == -1)
return;
int dir = mon->info[monster_id].dir;
#ifndef BUG
if (dir == DIR_RIGHT && m->player_x > x && m->player_y == y)
#else
if (dir == DIR_RIGHT && m->player_y == y)
#endif
mon->info[monster_id].player_seen = true;
#ifndef BUG
else if (dir == DIR_LEFT && m->player_x < x && m->player_y == y)
#else
else if (dir == DIR_LEFT && m->player_y == y)
#endif
mon->info[monster_id].player_seen = true;
#ifndef BUG
else if (dir == DIR_UP && m->player_y < y && m->player_x == x)
#else
else if (dir == DIR_UP && m->player_x == x)
#endif
mon->info[monster_id].player_seen = true;
}
// move the monster to the player's position
void catch_player(monsters* mon, map * m, int y, int x){
int monster_id = search_monster(mon, m, y, x);
if (y < m->player_y && !is_obstacle(m->tiles[y+1][x]) && m->tiles[y+1][x] != 'M' && m->tiles[y+1][x] != '@') {
mon->info[monster_id].dir = DIR_DOWN;
update_monster(mon,m,y,x,y+1,x);
} else if (y > m->player_y && !is_obstacle(m->tiles[y-1][x]) && m->tiles[y-1][x] != 'M' && m->tiles[y-1][x] != '@') {
mon->info[monster_id].dir = DIR_UP;
update_monster(mon,m,y,x,y-1,x);
} else if (x < m->player_x && !is_obstacle(m->tiles[y][x+1]) && m->tiles[y][x+1] != 'M' && m->tiles[y][x+1] != '@') {
mon->info[monster_id].dir = DIR_RIGHT;
update_monster(mon,m,y,x,y,x+1);
} else if (x > m->player_x && !is_obstacle(m->tiles[y][x-1]) && m->tiles[y][x-1] != 'M' && m->tiles[y][x-1] != '@') {
mon->info[monster_id].dir = DIR_LEFT;
update_monster(mon,m,y,x,y,x-1);
}
}
// move the monster once and verify to not move twice a monster.
void move_monsters(monsters* mon, map * m){
int done[8], len = 0;
for (int y = 0; y < m->height; y++){
for (int x = 0; x < m->width; x++){
if (m->tiles[y][x] == 'M'){
int id = search_monster(mon, m, y, x);
if (id != -1 && !in_list(id, done, len)){
if (strcmp(m->name, "third_room") != 0)
is_player_seen(mon,m,y,x);
if (mon->info[id].player_seen && strcmp(m->name, "third_room") != 0)
catch_player(mon,m,y,x);
else if (!strcmp(m->name, "first_room"))
come_and_go(mon,m,y,x);
else if (!strcmp(m->name, "second_room"))
circle(mon,m,y,x);
else if (!strcmp(m->name, "third_room"))
follow_player(mon,m,&y,&x);
done[len] = id;
len++;
}
}
}
}
}