Mercurial > MadButterfly
annotate examples/tank/enemy.c @ 1102:dbea3e42bf93
Initial random number generator for tank
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Sun, 05 Dec 2010 13:47:07 +0800 |
parents | fb79175e6cc3 |
children | 2b8b6deb35c8 |
rev | line source |
---|---|
1100 | 1 #include <stdio.h> |
1102
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
2 #include <time.h> |
1100 | 3 #include <stdlib.h> |
4 #include <string.h> | |
5 #include "tank.h" | |
6 | |
7 struct _enemy { | |
8 tank_rt_t *tank_rt; | |
9 tank_t *tank; | |
10 int memory[4]; | |
11 }; | |
12 typedef struct _enemy enemy_t; | |
13 | |
14 /* \brief Fire and move to the target tank if they are in a row or column. | |
15 */ | |
16 static int | |
17 try_fire(tank_t *me, tank_t *target, tank_rt_t *tank_rt) { | |
18 int x, y; | |
19 int *tracer = NULL; | |
20 int target_value; | |
21 int target_dir; | |
22 | |
23 if(me->map_x == target->map_x) { /* In a row */ | |
24 tracer = &y; | |
25 target_value = target->map_y; | |
26 if(me->map_y < target->map_y) | |
27 target_dir = TD_DOWN; | |
28 else | |
29 target_dir = TD_UP; | |
30 } | |
31 if(me->map_y == target->map_y) { /* In a column */ | |
32 tracer = &x; | |
33 target_value = target->map_x; | |
34 if(me->map_x < target->map_x) | |
35 target_dir = TD_RIGHT; | |
36 else | |
37 target_dir = TD_LEFT; | |
38 } | |
39 | |
40 if(tracer == NULL) | |
41 return 0; /* Not in a row or column */ | |
42 | |
43 /* Check obstacles between tanks */ | |
44 x = me->map_x; | |
45 y = me->map_y; | |
46 if(*tracer < target_value) { | |
47 while(++*tracer < target_value) { | |
48 if(map[y][x] != MUD) | |
49 break; | |
50 } | |
51 } else { | |
52 while(--*tracer > target_value) { | |
53 if(map[y][x] != MUD) | |
54 break; | |
55 } | |
56 } | |
57 | |
58 if(*tracer == target_value) { /* No any obstacle between tanks */ | |
59 /* Fire and move to target */ | |
60 if(me->direction == target_dir && me->bullet == NULL) | |
61 tank_fire_bullet(tank_rt, me); | |
62 tank_move(me, target_dir, tank_rt); | |
63 return 1; | |
64 } | |
65 | |
66 return 0; /* Find one or more obstacles */ | |
67 } | |
68 | |
69 #define NOTHING 0 | |
70 #define SOMETHING 1 | |
71 | |
72 static void | |
73 move_tank(enemy_t *enemy, tank_rt_t *tank_rt) { | |
74 tank_t *me; | |
75 tank_t **tanks, *tank; | |
76 static const int shift_xy[4][2] = { | |
77 {1, 0}, {0, 1}, | |
78 {-1, 0}, {0, -1}}; | |
79 int status[4]; | |
80 int x, y; | |
81 int i, tank_i; | |
82 int dir, chk_dir; | |
83 int possibles; | |
84 int which_dir; | |
85 | |
86 me = enemy->tank; | |
87 tanks = tank_rt->tanks; | |
88 | |
89 /* Collect status */ | |
90 for(i = 0; i < 4; i++) { | |
91 x = me->map_x + shift_xy[i][0]; | |
92 y = me->map_y + shift_xy[i][1]; | |
93 | |
94 /* Check obstacles */ | |
95 if(x == -1 || y == -1 || x >= MAP_W || y >= MAP_H) { | |
96 /* Out of range */ | |
97 status[i] = SOMETHING; | |
98 continue; | |
99 } | |
100 if(map[y][x] == MUD) | |
101 status[i] = NOTHING; | |
102 else | |
103 status[i] = SOMETHING; | |
104 | |
105 /* Check tanks */ | |
106 for(tank_i = 0; tank_i < tank_rt->n_tanks; tank_i++) { | |
107 tank = tanks[tank_i]; | |
108 if(tank->map_x == x && tank->map_y == y) { | |
109 status[i] = SOMETHING; | |
110 break; | |
111 } | |
112 } | |
113 } | |
114 | |
115 /* Try the same direction if status is not changed. */ | |
116 for(i = 0; i < 4; i++) { | |
117 if(status[i] != enemy->memory[i]) | |
118 break; | |
119 } | |
120 if(i == 4) { /* Status is not changed */ | |
121 tank_move(me, me->direction, tank_rt); | |
122 return; | |
123 } | |
124 | |
125 memcpy(enemy->memory, status, sizeof(int) * 4); | |
126 | |
127 /* Check possible directions except backward. */ | |
128 switch(me->direction) { | |
129 case TD_UP: | |
130 dir = 3; | |
131 break; | |
132 case TD_RIGHT: | |
133 dir = 0; | |
134 break; | |
135 case TD_DOWN: | |
136 dir = 1; | |
137 break; | |
138 case TD_LEFT: | |
139 dir = 2; | |
140 break; | |
141 } | |
142 | |
143 possibles = 0; | |
144 for(i = 0; i < 3; i++) { | |
145 chk_dir = (dir - 1 + i) % 4; | |
146 if(status[chk_dir] == NOTHING) | |
147 possibles++; | |
148 } | |
149 | |
150 if(possibles == 0) { /* Only can move backward */ | |
151 switch(me->direction) { | |
152 case TD_UP: | |
153 tank_move(me, TD_DOWN, tank_rt); | |
154 break; | |
155 case TD_RIGHT: | |
156 tank_move(me, TD_LEFT, tank_rt); | |
157 break; | |
158 case TD_DOWN: | |
159 tank_move(me, TD_UP, tank_rt); | |
160 break; | |
161 case TD_LEFT: | |
162 tank_move(me, TD_RIGHT, tank_rt); | |
163 break; | |
164 } | |
165 return; | |
166 } | |
167 | |
168 which_dir = rand() % possibles; | |
169 for(i = 0; i < 3; i++) { | |
170 chk_dir = (dir - 1 + i) % 4; | |
171 if(status[chk_dir] == NOTHING) { | |
172 if(which_dir == 0) | |
173 break; | |
174 which_dir--; | |
175 } | |
176 } | |
177 switch(chk_dir) { | |
178 case 0: | |
179 tank_move(me, TD_RIGHT, tank_rt); | |
180 break; | |
181 case 1: | |
182 tank_move(me, TD_DOWN, tank_rt); | |
183 break; | |
184 case 2: | |
185 tank_move(me, TD_LEFT, tank_rt); | |
186 break; | |
187 case 3: | |
188 tank_move(me, TD_UP, tank_rt); | |
189 break; | |
190 } | |
191 } | |
192 | |
193 static void | |
194 _drive_enemy_tank(enemy_t *enemy) { | |
195 tank_rt_t *tank_rt; | |
196 tank_t *me, *tank1, *tank2; | |
197 int r; | |
198 | |
199 tank_rt = enemy->tank_rt; | |
200 tank1 = tank_rt->tank1; | |
201 tank2 = tank_rt->tank2; | |
202 me = enemy->tank; | |
203 | |
204 r = try_fire(me, tank1, tank_rt); | |
205 if(r) | |
206 return; | |
207 r = try_fire(me, tank2, tank_rt); | |
208 if(r) | |
209 return; | |
210 | |
211 move_tank(enemy, tank_rt); | |
212 } | |
213 | |
214 static enemy_t *enemies = NULL; | |
215 static mb_timer_man_t *timer_man; | |
216 | |
217 /*! \brief Drive every enemy tanks. | |
218 */ | |
219 static void | |
220 enemy_tank_driver(int hdl, const mb_timeval_t *tmo, | |
221 const mb_timeval_t *now, void *data) { | |
222 tank_rt_t *tank_rt = (tank_rt_t *)data; | |
1102
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
223 enemy_t *enemy; |
1100 | 224 int n_enemy; |
225 mb_timeval_t timeout, addend; | |
226 int i; | |
227 | |
228 n_enemy = tank_rt->n_enemy; | |
229 for(i = 0; i < n_enemy; i++) { | |
1102
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
230 enemy = enemies + i; |
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
231 if(enemy->tank->progm == NULL) |
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
232 _drive_enemy_tank(enemy); |
1100 | 233 } |
234 | |
235 get_now(&timeout); | |
236 MB_TIMEVAL_SET(&addend, 0, 300000); | |
237 MB_TIMEVAL_ADD(&timeout, &addend); | |
238 mb_timer_man_timeout(timer_man, &timeout, enemy_tank_driver, tank_rt); | |
239 } | |
240 | |
241 /*! \brief Start a timer for enemy tank driver. | |
242 */ | |
243 static void | |
244 start_enemy_tank_timer(tank_rt_t *tank_rt) { | |
245 mb_timeval_t timeout, addend; | |
246 | |
247 timer_man = mb_runtime_timer_man(tank_rt->mb_rt); | |
248 | |
249 get_now(&timeout); | |
250 MB_TIMEVAL_SET(&addend, 0, 300000); | |
251 MB_TIMEVAL_ADD(&timeout, &addend); | |
252 mb_timer_man_timeout(timer_man, &timeout, enemy_tank_driver, tank_rt); | |
253 } | |
254 | |
255 void | |
256 init_enemies(tank_rt_t *tank_rt) { | |
257 int n_enemy; | |
258 tank_t **tank_enemies; | |
259 tank_t *tank; | |
260 int i, j; | |
261 | |
262 n_enemy = tank_rt->n_enemy; | |
263 tank_enemies = tank_rt->tank_enemies; | |
264 | |
265 enemies = (enemy_t *)malloc(sizeof(enemy_t) * n_enemy); | |
266 | |
267 for(i = 0; i < n_enemy; i++) { | |
268 tank = tank_enemies[i]; | |
269 enemies[i].tank_rt = tank_rt; | |
270 enemies[i].tank = tank; | |
271 for(j = 0; j < 4; j++) | |
272 enemies[i].memory[j] = SOMETHING; | |
273 } | |
274 | |
1102
dbea3e42bf93
Initial random number generator for tank
Thinker K.F. Li <thinker@codemud.net>
parents:
1100
diff
changeset
|
275 srand(time(NULL)); |
1100 | 276 start_enemy_tank_timer(tank_rt); |
277 } |