source: golgotha/src/golg/objs/ai_joe.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 11.3 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "team_api.hh"
10#include "memory/array.hh"
11#include "math/random.hh"
12#include "math/angle.hh"
13#include "math/trig.hh"
14#include "time/profile.hh"
15#include "objs/stank.hh"
16#include "objs/goal.hh"
17
18//(OLI) hack for reloading this AI
19extern w16 ai_joe_dll_ref;
20
21char *unit_name[] =
22{
23  "stank",                      //0
24  "peon_tank",                  //1
25  "electric_car",               //2
26  "rocket_tank",                //3
27  "",
28  "",
29//  "helicopter",                 //4
30//  "jet",                        //5
31  "engineer",                   //6
32  "trike"                       //7
33};
34const int num_unit_types=sizeof(unit_name)/sizeof(char*);
35w16 unit_type[num_unit_types];
36
37char *goodies_name[] =
38{
39  "takeover_pad",               //1
40  "factory_pad"                 //2
41};
42const int num_goodies_types=sizeof(goodies_name)/sizeof(char*);
43w16 goodies_type[num_goodies_types];
44
45char *formation[] =
46//{{{
47{
48  "      "
49  "      "
50  "121212"
51  "      "
52  "1 63 1"
53  "  33  ", // stock
54
55  "222222"
56  "      "
57  "      "
58  "      "
59  "      "
60  "      ", // electric brigade
61
62  "  11  "
63  " 1221 "
64  "123321"
65  "      "
66  "      "
67  "      ", // hole puncher
68
69  "12221 "
70  "23632 "
71  "      "
72  "      "
73  "      "
74  "      ", // armored convoy
75
76  "      "
77  "      "
78  "1 1 1 "
79  " 1 1 1"
80  "7 7 7 "
81  " 7 7 7", // gene's checker
82
83  "  1   "
84  " 161  "
85  "1   1 "
86  "      "
87  "      "
88  "      ", // peon V
89
90  "  4   "
91  " 4 4  "
92  "      "
93  "      "
94  "      "
95  "      ", // heli hell
96
97  "111111"
98  " 3663 "
99  " 3333 "
100  "      "
101  "      "
102  "      ", // rockets R us
103
104  "22    "
105  "66    "
106  "      "
107  "      "
108  "      "
109  "      ", // small band
110
111  "22    "
112  "36    "
113  "      "
114  "      "
115  "      "
116  "      ", // yet another small band
117
118  "33    "
119  "66    "
120  "      "
121  "      "
122  "      "
123  "      ", // yet another small band
124
125  "6     "
126  "      "
127  "      "
128  "      "
129  "      "
130  "      ", // long shot
131
132  "2222  "
133  "3333  "
134  "      "
135  "      "
136  "      "
137  "      ", // ouch!
138};
139//}}}
140const int num_formations=sizeof(formation)/sizeof(char*);
141
142enum eDir
143{
144  N, E, S, W
145};
146
147sw16 dirx[] = {0, 1, 0, -1};
148sw16 diry[] = {1, 0, -1, 0};
149
150
151i4_profile_class pf_ai_joe_setup_production("ai_joe_setup_production");
152i4_profile_class pf_ai_joe_setup_new_pieces("ai_joe_setup_new_pieces");
153i4_profile_class pf_ai_joe_cleanup("ai_joe_cleanup");
154i4_profile_class pf_ai_joe_next_spot("ai_joe_next_spot");
155i4_profile_class pf_ai_joe_guide_hero("ai_joe_guide_hero");
156i4_profile_class pf_ai_joe_think("ai_joe_think");
157
158class ai_joe : public g1_team_api_class
159{
160public:
161  enum eBuildMode
162  { INIT, INITWAIT, IDLE, BUILDWAIT, BUILD, WAITFORPIECE, FORMANDMOVE, RESURRECT };
163
164  i4_float tx,ty;
165  sw16 bx,by;
166  i4_float prodx,prody;
167  eDir dir1, dir2;
168
169  i4_array<unit_class> troop;
170  i4_array<sw32> time;
171  i4_array<unit_class> build;
172  i4_array<object_class> goal;
173  int form, place, formation_size;
174  int build_count;
175  int build_wait, retry;
176  eBuildMode build_mode;
177
178  w16 goal_type;
179
180  int reload;  // supertank is going to reload ammo
181
182  ai_joe(g1_loader_class *f=0)
183    : troop(100,20), time(50,20), build(18,0), goal(20,10)
184  //{{{
185  {
186    build_mode = INIT;
187    form = -1;
188    place = 0;
189  }
190  //}}}
191
192  ~ai_joe()
193  //{{{
194  {
195  }
196  //}}}
197
198  void setup_production(i4_float _prodx,i4_float _prody)
199  //{{{
200  {
201    pf_ai_joe_setup_production.start();
202    // setup around production site at location
203
204    prodx = _prodx;
205    prody = _prody;
206
207    int
208      dx = int(prodx - map_width()/2),
209      dy = int(prody - map_height()/2);
210
211    int num=0;
212
213    num |= (dx<0)  ?0:8;
214    num |= (dy<0)  ?0:4;
215    num |= (dx<dy) ?0:2;
216    num |= (dx<-dy)?0:1;
217
218    switch (num)
219    {
220      case  5:  //N quadrant
221      case 13:  dir1 = S;  break;
222      case 15:  //E quadrant
223      case 11:  dir1 = W;  break;
224      case 10:  //S quadrant
225      case  2:  dir1 = N;  break;
226      case  0:  //W quadrant
227      case  4:  dir1 = E;  break;
228    }
229    dir2 = eDir((dir1+1)%4);
230
231    reload=0;
232    pf_ai_joe_setup_production.stop();
233  }
234  //}}}
235
236  virtual void init()
237  //{{{
238  {
239    int i;
240
241    troop.clear();
242    time.clear();
243    build.clear();
244
245    for (i=0; i<num_unit_types; i++)
246      unit_type[i] = object_type(unit_name[i]);
247    for (i=0; i<num_goodies_types; i++)
248      goodies_type[i] = object_type(goodies_name[i]);
249    goal = object_type("goal");
250
251    build_mode = INIT;
252    form = -1;
253    place = 0;
254
255    dir1 = eDir(g1_rand(20)%4);
256    dir2 = eDir((dir1+1)%4);
257  }
258  //}}}
259
260  void cleanup()
261  //{{{
262  {
263    pf_ai_joe_cleanup.start();
264    int i;
265   
266    for (i=troop.size()-1; i>=0; i--)
267      if (!troop[i].alive())
268        troop.remove(i);
269    pf_ai_joe_cleanup.stop();
270  }
271  //}}}
272
273  int next_spot()
274  //{{{ sets next formation spot.. returns false if no more left
275  {
276    pf_ai_joe_next_spot.start();
277
278    while (place<6*6 && formation[form][place]==' ')
279      place++;
280
281    if (place==6*6)
282    {
283      pf_ai_joe_next_spot.stop();
284      return 0;
285    }
286
287    int x=(place%6)*2-5, y=5-(place/6)*2;
288
289    bx = (5 + dirx[dir1]*y + dirx[dir2]*x)/2;
290    by = (5 + diry[dir1]*y + diry[dir2]*x)/2;
291
292    pf_ai_joe_next_spot.stop();
293    return 1;
294  }
295  //}}}
296
297  void guide_hero()
298  //{{{
299  {
300    pf_ai_joe_guide_hero.start();
301
302    if (health()<=0)
303    {
304#if 0
305      if (build_mode == IDLE)
306        build_mode = RESURRECT;
307#endif     
308      pf_ai_joe_cleanup.stop();
309      return;
310    }
311
312    if (ammo1()==0 && ammo2()==0 && ammo3()==0 && !reload)
313    {
314      /*
315        jc fixme : send supertank to home base
316      tx = map()->player_pad_info[player->get_player_num()].bases[0].x;
317      ty = map()->player_pad_info[player->get_player_num()].bases[0].y;
318
319     
320      send_convoy(commander()->convoy->global_id, tx, ty);
321      reload = 1;
322      */
323    }
324   
325    if (reload)
326    {
327      if (full1() && full2() && full3())
328        reload=0;
329
330      pf_ai_joe_cleanup.stop();
331      return;
332    }
333
334    if (!commander()->attack_target.valid())
335    {
336      commander()->find_target();
337      if (!commander()->attack_target.valid())
338      {
339        tx = g1_rand(50)%map_width()  + 0.5;
340        ty = g1_rand(60)%map_height() + 0.5;
341
342        deploy_unit(commander()->global_id, tx, ty);
343      }
344    }
345    else
346    {
347      g1_object_class *mp = commander()->attack_target.get();
348
349      if (mp)
350      {
351
352        i4_float dx,dy,angle, adiff;
353       
354        //this will obviously only be true if me->attack_target.ref != NULL   
355        dx = (mp->x - (commander()->x+commander()->turet->x));
356        dy = (mp->y - (commander()->y+commander()->turet->y));
357       
358        //aim the turet
359       
360        angle = i4_atan2(dy,dx);
361        i4_normalize_angle(angle);   
362        adiff = i4_angle_diff(commander()->base_angle, angle);
363
364        if (adiff<0.04)
365          if (mp->id == g1_supertank_type)
366            fire2() || fire1() || fire3();
367          else
368            fire1() || fire3();
369        if (angle>commander()->base_angle)
370          turn(adiff);
371        else
372          turn(-adiff);
373        strafe(0.4);
374      }
375    }
376   
377    pf_ai_joe_guide_hero.stop();
378  }
379  //}}}
380
381  void guide_units()
382  //{{{
383  {
384    for (int i=0; i<time.size(); i++)
385    {
386      if (time[i]>0)
387        time[i]--;
388      else
389      {
390        int went=0;
391
392        if (goal.size()>0)
393        {
394          tx = g1_rand(70)%(map_width()-10) + 5.5;
395          ty = g1_rand(80)%(map_height()-10) + 5.5;
396          deploy_unit(group[i].id(), tx,ty);
397          time[i]=g1_rand(9)%500+500;
398        }
399
400        tx = g1_rand(90)%(map_width()-10) + 5.5;
401        ty = g1_rand(100)%(map_height()-10) + 5.5;
402        deploy_unit(group[i].id(), tx,ty);
403        time[i]=g1_rand5()%500+500;
404      }
405    }
406  }
407  //}}}
408
409  virtual void object_built(w32 id)
410  //{{{
411  {
412    g1_team_api_class::object_built(id);
413
414    build.add(unit(id));
415  }
416  //}}}
417 
418  virtual void object_added(w32 id)
419  //{{{
420  {
421    object_class obj(object(id));
422    unit_class u(unit(id));
423    int i;
424
425    if (obj.alive())
426    {
427      if (obj.id()==goodies_type[0])
428        goal.add(obj);
429      else if (u.alive())
430      {
431        for (i=0; i<num_unit_types && obj.id()!=unit_type[i]; i++) ;
432
433        if (i<num_unit_types)
434        {
435          troop.add(u);
436          for (i=0; i<group.size() && group[i].id()!=u.convoy_id(); i++) ;
437
438          if (i==group.size() && !u.built())
439          {
440            group.add(convoy(u.convoy_id()));
441            time.add(0);
442          }
443        }
444      }
445    }
446  }
447  //}}}
448
449  virtual void think()
450  //{{{
451  {
452    pf_ai_joe_think.start();
453
454    cleanup();
455
456    if (form<0)
457    {
458      // determine next formation
459      form = g1_rand(99)%num_formations;
460      place = 0;
461      build_count = 0;
462      build.clear();
463    }
464
465    guide_units();
466
467    guide_hero();
468
469    switch (build_mode)
470    {
471      case INIT:
472        //{{{
473      {
474        /* jc fixme
475        w32 p = build_unit(unit_names[3]);  // rocket sentinel
476
477        if (p)
478        {
479          int i=troop.add(unit(p));
480          setup_production(troop[i].x(), troop[i].y());
481          int c=group.add(convoy(built_convoy_id()));
482          time.add(-1);
483
484          bx = prodx - dirx[dir1]*3;
485          by = prody - diry[dir1]*3;
486          send_convoy(built_convoy_id(), bx, by);
487          build_mode = INITWAIT;
488          build_wait = 50;
489        } */
490        build_mode = INITWAIT;
491        build_wait = 50;
492      } break;
493      //}}}
494      case INITWAIT:
495        //{{{
496        if (--build_wait<=0)
497          build_mode = IDLE;
498        break;
499        //}}}
500      case IDLE:
501        //{{{
502      {
503        if (troop.size()<50)
504          build_mode = BUILD;
505      } break;
506        //}}}
507      case BUILDWAIT:
508        //{{{
509        if (--build_wait<=0)
510          build_mode = BUILD;
511        break;
512        //}}}
513      case BUILD:
514        //{{{
515        if (build_unit(unit_type[formation[form][place] - '0'], bx, by) == G1_BUILD_OK)
516          build_count++;
517        place++;
518        break;
519        //}}}
520      case WAITFORPIECE:
521        //{{{
522        // wait for object_build or build_error to complete
523        break;
524        //}}}
525      case FORMANDMOVE:     // jc:fixme
526        build_mode=INITWAIT;
527        build_wait=g1_rand(103)%500+100;
528        break;
529
530      case RESURRECT:
531        //{{{
532        build_unit(unit_type[0],0,0);
533        build_wait=20;
534        build_mode=INITWAIT;
535        break;
536        //}}}
537    }
538   
539    pf_ai_joe_think.stop();
540  }
541  //}}}
542};
543
544g1_team_api_definer<ai_joe> ai_joe_def("ai_joe");
545
546
547// AI joe is now chosen as the default through (g1_set_deault_ai "joe") in scheme/start.scm
548
549//{{{ Emacs Locals
550// Local Variables:
551// folded-file: t
552// End:
553//}}}
554
Note: See TracBrowser for help on using the repository browser.