We should follow the HandBook
[tuxanci.git] / src / modules / modAI.c
blob5790d55cb97392f894e37964bc162c52ffa96040
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
6 #include "main.h"
7 #include "modules.h"
8 #include "tux.h"
9 #include "shot.h"
10 #include "list.h"
11 #include "gun.h"
12 #include "space.h"
14 #ifndef PUBLIC_SERVER
15 #include "interface.h"
16 #include "image.h"
17 #else
18 #include "publicServer.h"
19 #endif
21 static export_fce_t *export_fce;
23 typedef struct alternative_struct {
24 int first;
25 int route;
26 int step;
27 int x, y;
28 } alternative_t;
30 static alternative_t *newAlternative(int route, int x, int y)
32 alternative_t *new;
34 new = malloc(sizeof(alternative_t));
35 new->first = route;
36 new->route = route;
37 new->x = x;
38 new->y = y;
39 new->step = 0;
41 return new;
44 static alternative_t *cloneAlternative(alternative_t *p, int route, int x, int y)
46 alternative_t *new;
48 assert(p != NULL);
50 UNUSED(x);
51 UNUSED(y);
53 new = newAlternative(route, p->x, p->y);
54 new->first = p->first;
55 new->step = p->step;
57 return new;
60 static void forkAlternative(list_t *list, alternative_t *p, int w, int h)
62 int x, y;
64 assert(list != NULL);
65 assert(p != NULL);
67 x = p->x;
68 y = p->y;
70 switch (p->route) {
71 case TUX_UP:
72 list_add(list, cloneAlternative(p, TUX_RIGHT, x + (w + 5), y));
73 list_add(list, cloneAlternative(p, TUX_LEFT, x - (w + 5), y));
74 break;
75 case TUX_RIGHT:
76 list_add(list, cloneAlternative(p, TUX_UP, x, y - (h + 5)));
77 list_add(list, cloneAlternative(p, TUX_DOWN, x, y + (h + 5)));
78 break;
79 case TUX_LEFT:
80 list_add(list, cloneAlternative(p, TUX_UP, x, y - (h + 5)));
81 list_add(list, cloneAlternative(p, TUX_DOWN, x, y + (h + 5)));
82 break;
83 case TUX_DOWN:
84 list_add(list, cloneAlternative(p, TUX_RIGHT, x + (w + 5), y));
85 list_add(list, cloneAlternative(p, TUX_LEFT, x - (w + 5), y));
86 break;
91 static void moveAlternative(alternative_t *p, int offset)
93 assert(p != NULL);
95 p->step++;
97 /*printf("move %d %d %d\n", p->x, p->y, p->step);*/
99 switch (p->route) {
100 case TUX_UP:
101 p->y -= offset;
102 break;
103 case TUX_RIGHT:
104 p->x += offset;
105 break;
106 case TUX_LEFT:
107 p->x -= offset;
108 break;
109 case TUX_DOWN:
110 p->y += offset;
111 break;
115 static void destroyAlternative(alternative_t *p)
117 assert(p != NULL);
118 free(p);
121 static void cmd_ai(char *line)
123 UNUSED(line);
126 static int init(export_fce_t *p)
128 export_fce = p;
130 return 0;
133 #ifndef PUBLIC_SERVER
134 static int draw(int x, int y, int w, int h)
136 UNUSED(x);
137 UNUSED(y);
138 UNUSED(w);
139 UNUSED(h);
141 return 0;
143 #endif
145 static tux_t *findOtherTux(space_t *space)
147 int i;
149 for (i = 0; i < space_get_count(space); i++) {
150 tux_t *thisTux;
152 thisTux = space_get_item(space, i);
154 if (thisTux->control != TUX_CONTROL_AI) {
155 return thisTux;
159 return NULL;
162 static void shotTux(arena_t *arena, tux_t *tux_ai, tux_t *tux_rival)
164 const int limit = 20;
165 int x_ai, y_ai;
166 int x_rival, y_rival;
167 int w, h;
169 UNUSED(arena);
171 export_fce->fce_tux_get_proportion(tux_ai, &x_ai, &y_ai, &w, &h);
172 export_fce->fce_tux_get_proportion(tux_rival, &x_rival, &y_rival, &w, &h);
174 if (y_rival < y_ai && x_rival > x_ai && x_rival < x_ai + limit) {
175 export_fce->fce_tux_action(tux_ai, TUX_UP);
176 export_fce->fce_tux_action(tux_ai, TUX_SHOT);
179 if (x_rival > x_ai && y_rival > y_ai && y_rival < y_ai + limit) {
180 export_fce->fce_tux_action(tux_ai, TUX_RIGHT);
181 export_fce->fce_tux_action(tux_ai, TUX_SHOT);
184 if (x_rival < x_ai && y_rival > y_ai && y_rival < y_ai + limit) {
185 export_fce->fce_tux_action(tux_ai, TUX_LEFT);
186 export_fce->fce_tux_action(tux_ai, TUX_SHOT);
189 if (y_rival > y_ai && x_rival > x_ai && x_rival < x_ai + limit) {
190 export_fce->fce_tux_action(tux_ai, TUX_DOWN);
191 export_fce->fce_tux_action(tux_ai, TUX_SHOT);
195 static void tux_eventAI(tux_t *tux)
197 arena_t *arena;
198 tux_t *rivalTux;
200 list_t *listAlternative;
201 list_t *listDst;
202 list_t *listFork;
204 int x, y, w, h;
205 int rival_x, rival_y;
206 int i, my_index;
208 int countFork = 0;
209 int countDel = 0;
210 int countLimit = 0;
211 int countDo = 0;
213 export_fce->fce_tux_get_proportion(tux, &x, &y, &w, &h);
214 /*printf("tux AI %d %d\n", x, y);*/
216 arena = export_fce->fce_arena_get_current();
218 rivalTux = findOtherTux(arena->spaceTux);
220 if (rivalTux == NULL || rivalTux->status != TUX_STATUS_ALIVE) {
221 return;
224 listAlternative = list_new();
225 listDst = list_new();
226 listFork = list_new();
228 shotTux(arena, tux, rivalTux);
230 export_fce->fce_tux_get_proportion(rivalTux, &rival_x, &rival_y, NULL, NULL);
231 /*printf("tux rival %d %d\n", rival_x, rival_y);*/
233 list_add(listAlternative, newAlternative(TUX_UP, x, y - (h + 10)));
234 list_add(listAlternative, newAlternative(TUX_RIGHT, x + (w + 10), y));
235 list_add(listAlternative, newAlternative(TUX_LEFT, x - (w + 10), y));
236 list_add(listAlternative, newAlternative(TUX_DOWN, x, y + (h + 10)));
238 my_index = -1;
239 while (1) {
240 alternative_t *this;
242 my_index++;
243 if (my_index < 0 || my_index >= listAlternative->count) {
245 int j;
247 /*printf("listFork->count = %d\n", listFork->count);*/
249 for (j = 0; j < listFork->count; j++) {
250 list_add(listAlternative, listFork->list[j]);
253 list_do_empty(listFork);
255 my_index = 0;
258 if (listAlternative->count == 0) {
259 break;
262 this = (alternative_t *) listAlternative->list[my_index];
264 if (++countDo == 100)
265 break;
267 if (this->step > 100) {
268 list_del_item(listAlternative, my_index, destroyAlternative);
269 countLimit++;
270 my_index--;
271 continue;
274 moveAlternative(this, w * 2);
276 if (export_fce->fce_arena_is_free_space(arena, this->x, this->y, w, h) == 1) {
277 forkAlternative(listFork, this, 2 * w, 2 * h);
278 countFork++;
279 continue;
282 if (export_fce->
283 fce_arena_conflict_space(this->x, this->y, w, h, rival_x, rival_y, w,
284 h)) {
285 /*printf("this->step = %d\n", this->step);*/
287 list_del(listAlternative, my_index);
288 list_add(listDst, this);
289 my_index--;
290 /*continue;*/
291 break;
294 if (export_fce->fce_arena_is_free_space(arena, this->x, this->y, w, h) == 0) {
295 /*forkAlternative(listFork, this, w*2, h*2);*/
296 list_del_item(listAlternative, my_index, destroyAlternative);
297 my_index--;
298 countDel++;
300 continue;
305 int minStep = 1000;
306 int recRoute = 0;
308 /*printf("------------\n");*/
309 for (i = 0; i < listDst->count; i++) {
310 alternative_t *this;
312 this = (alternative_t *) listDst->list[i];
314 /*printf("XXX step %d route = %d\n", this->step, this->first);*/
315 if (this->step < minStep) {
316 minStep = this->step;
317 recRoute = this->first;
321 if (recRoute != 0) {
322 export_fce->fce_tux_action(tux, recRoute);
325 list_destroy_item(listFork, destroyAlternative);
326 list_destroy_item(listAlternative, destroyAlternative);
327 list_destroy_item(listDst, destroyAlternative);
329 printf("countFork = %d\n", countFork);
330 printf("countDel = %d\n", countDel);
331 printf("countLimit = %d\n", countLimit);
332 printf("countDo = %d\n", countDo);
336 static void action_tuxAI(space_t *space, tux_t *tux, void *p)
338 UNUSED(space);
339 UNUSED(p);
341 if (tux->control == TUX_CONTROL_AI && tux->status == TUX_STATUS_ALIVE) {
342 tux_eventAI(tux);
346 static int event()
348 static my_time_t lastEvent = 0;
349 my_time_t curentTime;
350 arena_t *arena;
351 int countTuxAI;
352 /*int i;*/
354 if (lastEvent == 0) {
355 lastEvent = export_fce->fce_timer_get_current_time();
358 curentTime = export_fce->fce_timer_get_current_time();
360 if (curentTime - lastEvent < 25) {
361 return 0;
364 lastEvent = export_fce->fce_timer_get_current_time();
365 /*printf("event AI\n");*/
367 arena = export_fce->fce_arena_get_current();
369 if (arena == NULL) {
370 return 0;
373 countTuxAI = 0;
375 space_action(arena->spaceTux, action_tuxAI, NULL);
377 for( i = 0 ; i < arena->spaceTux->list->count ; i++ )
379 tux_t *thisTux;
381 thisTux = arena->spaceTux->list->list[i];
383 if( thisTux->control == TUX_CONTROL_AI &&
384 thisTux->status == TUX_STATUS_ALIVE )
386 tux_event(thisTux);
387 countTuxAI = 0;
391 return 0;
394 static int isConflict(int x, int y, int w, int h)
396 UNUSED(x);
397 UNUSED(y);
398 UNUSED(w);
399 UNUSED(h);
401 return 0;
404 static void cmdArena(char *line)
406 if (strncmp(line, "ai", 2) == 0)
407 cmd_ai(line);
410 static void recvMsg(char *msg)
412 UNUSED(msg);
415 static int destroy()
417 return 0;
420 mod_sym_t modai_sym = { &init,
421 #ifndef PUBLIC_SERVER
422 &draw,
423 #else
425 #endif
426 &event,
427 &isConflict,
428 &cmdArena,
429 &recvMsg,
430 &destroy };