1 #ifdef _WIN32
2 #include "windows.h"
3 #endif
4
5 #include "string.h"
6 #include "stdlib.h"
7
8 #include "stdio.h"
9 #include "math.h"
10
11 #include "GL/gl.h"
12 #include "GL/glu.h"
13 #include "GL/glut.h"
14 #include "SDL/SDL.h"
15 #include "SDL/SDL_mixer.h"
16
17 #include "list.h"
18 #include "vector.h"
19 #include "cmc.h"
20 #include "3dobject.h"
21 #include "shadow3dobject.h"
22 #include "piece3dobject.h"
23 #include "myglutaux.h"
24 #include "nether.h"
25
26 #include "glprintf.h"
27
28 extern int detaillevel;
29 extern int frames_per_sec;
30 extern bool fullscreen;
31 extern int shadows;
32 extern bool sound;
33 extern int up_key,down_key,left_key,right_key,fire_key,pause_key;
34 extern int level;
35 extern float MINY,MAXY,MINX,MAXX;
36
37
38 extern FILE *debug_fp;
39
cycle(unsigned char * keyboard)40 bool NETHER::cycle(unsigned char *keyboard)
41 {
42
43 #ifdef _WRITE_REPORT_
44 fprintf(debug_fp,"PLAY CYCLE STARTS\n");
45 fflush(debug_fp);
46 #endif
47
48 #ifdef _WRITE_REPORT_
49 fprintf(debug_fp,"Recomputing statistics\n");
50 fflush(debug_fp);
51 #endif
52
53 if (keyboard[SDLK_PAGEUP]) {
54 zoom*=1.1;
55 if (zoom>4) zoom=4;
56 } /* if */
57 if (keyboard[SDLK_PAGEDOWN]) {
58 zoom/=1.1;
59 if (zoom<0.5) zoom=0.5;
60 } /* if */
61
62 if (recomputestatistics) {
63 List<BUILDING> l;
64 BUILDING *b;
65
66 statistics[0][0]=0;
67 statistics[0][1]=0;
68 statistics[0][2]=0;
69 statistics[0][3]=0;
70 statistics[0][4]=0;
71 statistics[0][5]=0;
72 statistics[0][6]=0;
73 statistics[0][7]=0;
74 statistics[1][0]=0;
75 statistics[1][1]=0;
76 statistics[1][2]=0;
77 statistics[1][3]=0;
78 statistics[1][4]=0;
79 statistics[1][5]=0;
80 statistics[1][6]=0;
81 statistics[1][7]=0;
82
83 l.Instance(buildings);
84 l.Rewind();
85 while(l.Iterate(b)) {
86 if (b->type==B_WARBASE) {
87 if (b->owner==1) statistics[0][0]++;
88 if (b->owner==2) statistics[1][0]++;
89 } /* if */
90 if (b->type==B_FACTORY_ELECTRONICS) {
91 if (b->owner==1) statistics[0][1]++;
92 if (b->owner==2) statistics[1][1]++;
93 } /* if */
94 if (b->type==B_FACTORY_NUCLEAR) {
95 if (b->owner==1) statistics[0][2]++;
96 if (b->owner==2) statistics[1][2]++;
97 } /* if */
98 if (b->type==B_FACTORY_PHASERS) {
99 if (b->owner==1) statistics[0][3]++;
100 if (b->owner==2) statistics[1][3]++;
101 } /* if */
102 if (b->type==B_FACTORY_MISSILES) {
103 if (b->owner==1) statistics[0][4]++;
104 if (b->owner==2) statistics[1][4]++;
105 } /* if */
106 if (b->type==B_FACTORY_CANNONS) {
107 if (b->owner==1) statistics[0][5]++;
108 if (b->owner==2) statistics[1][5]++;
109 } /* if */
110 if (b->type==B_FACTORY_CHASSIS) {
111 if (b->owner==1) statistics[0][6]++;
112 if (b->owner==2) statistics[1][6]++;
113 } /* if */
114 } /* while */
115 recomputestatistics=false;
116 } /* if */
117
118 #ifdef _WRITE_REPORT_
119 fprintf(debug_fp,"Starting enemy AI\n");
120 fflush(debug_fp);
121 #endif
122
123 /* ENEMY Artificial Intelligence: */
124 if (second==0) {
125 if (level==0 && (hour&0x01)==0 && minute==0) AI_enemy();
126 if (level==1 && minute==0) AI_enemy();
127 if (level>=2 && (minute==0 || minute==30)) AI_enemy();
128 } /* if */
129
130 #ifdef _WRITE_REPORT_
131 fprintf(debug_fp,"Starting GAME CYCLE\n");
132 fflush(debug_fp);
133 #endif
134
135 /* GAME Cycle: */
136 {
137 shiplanded=false;
138
139 #ifdef _WRITE_REPORT_
140 fprintf(debug_fp,"Menu\n");
141 fflush(debug_fp);
142 #endif
143 switch(act_menu) {
144 case GENERAL_MENU:
145 /* Free movement of the ship through the map: */
146 {
147 float x[2],y[2];
148 float minz;
149 Vector old_shipp;
150
151 shipp.x=(int(shipp.x*8.0))/8.0;
152 shipp.y=(int(shipp.y*8.0))/8.0;
153 old_shipp=shipp;
154 x[0]=shipp.x;
155 x[1]=shipp.x+1.0;
156 y[0]=shipp.y;
157 y[1]=shipp.y+1.0;
158 minz=MapMaxZ(x,y);
159
160 if (ship_op==OP_RIGHT) if (shipp.x<map_w-1) {
161 shipp.x+=0.125;
162 if (ship_timemoving>=50 && (int(shipp.x*8)%2)==1) shipp.x+=0.125;
163 // if (ship_timemoving>=100 && (int(shipp.x*4)%2)==1) shipp.x+=0.25;
164 } /* if */
165 if (ship_op==OP_LEFT) if (shipp.x>0) {
166 shipp.x-=0.125;
167 if (ship_timemoving>=50 && (int(shipp.x*8)%2)==1) shipp.x-=0.125;
168 // if (ship_timemoving>=100 && (int(shipp.x*4)%2)==1) shipp.x-=0.25;
169 } /* if */
170 if (ship_op2==OP_FORWARD) if (shipp.y<map_h-1) {
171 shipp.y+=0.125;
172 if (ship_timemoving>=50 && (int(shipp.y*8)%2)==1) shipp.y+=0.125;
173 // if (ship_timemoving>=100 && (int(shipp.y*4)%2)==1) shipp.y+=0.25;
174 } /* if */
175 if (ship_op2==OP_BACKWARD) if (shipp.y>0) {
176 shipp.y-=0.125;
177 if (ship_timemoving>=50 && (int(shipp.y*8)%2)==1) shipp.y-=0.125;
178 // if (ship_timemoving>=100 && (int(shipp.y*4)%2)==1) shipp.y-=0.25;
179 } /* if */
180 if (ship_op3==OP_UP) if (shipp.z<5.0) shipp.z+=0.05;
181 if (ship_op3!=OP_UP && shipp.z>minz) shipp.z-=0.025;
182 if (shipp.z<minz) shipp.z=minz;
183
184 if (ship_op==OP_NONE && ship_op2==OP_NONE) {
185 ship_timemoving=0;
186 } else {
187 ship_timemoving++;
188 } /* if */
189
190 if (shipp!=old_shipp
191 // &&
192 // shipp==old_shipp
193 ) {
194 if (ShipCollision(ship,shipp.x,shipp.y,shipp.z)) {
195 ship_timemoving=0;
196 Vector p=shipp;
197 shipp.x=old_shipp.x;
198 shipp.y=old_shipp.y;
199 if (p.z!=old_shipp.z && ShipCollision(ship,shipp.x,shipp.y,shipp.z)) {
200 shipp.z=old_shipp.z;
201 shiplanded=true;
202 } else {
203 shipp.z=p.z;
204 } /* if */
205 shipp.x=p.x;
206 if (p.x!=old_shipp.x && ShipCollision(ship,shipp.x,shipp.y,shipp.z)) {
207 shipp.x=old_shipp.x;
208 } else {
209 shipp.x=p.x;
210 } /* if */
211 shipp.y=p.y;
212 if (p.y!=old_shipp.y && ShipCollision(ship,shipp.x,shipp.y,shipp.z)) {
213 shipp.y=old_shipp.y;
214 } else {
215 shipp.y=p.y;
216 } /* if */
217 } /* if */
218 } /* if */
219
220 if ((int(shipp.x*8)%4)==0) ship_op=OP_NONE;
221 if ((int(shipp.y*8)%4)==0) ship_op2=OP_NONE;
222 if ((int(shipp.z*8)%4)==0) ship_op3=OP_NONE;
223
224 if (keyboard[left_key]) {
225 ship_op=OP_LEFT;
226 } /* if */
227 if (keyboard[right_key]) {
228 ship_op=OP_RIGHT;
229 } /* if */
230 if (keyboard[up_key]) {
231 ship_op2=OP_FORWARD;
232 } /* if */
233 if (keyboard[down_key]) {
234 ship_op2=OP_BACKWARD;
235 } /* if */
236 if (keyboard[fire_key]) {
237 ship_op3=OP_UP;
238 } /* if */
239 }
240 break;
241
242 case ROBOT_MENU:
243 /* Browsing through the ROBOT MENU: */
244 {
245 int i;
246 int buttons[4]={ROBOT1_BUTTON,ROBOT2_BUTTON,ROBOT3_BUTTON,ROBOT4_BUTTON};
247 STATUSBUTTON *b;
248
249 if (keyboard[up_key] && !old_keyboard[up_key]) {
250 int j=-1;
251 for(i=0;i<4 && j==-1;i++) {
252 if (act_button==buttons[i]) {
253 j=i-1;
254 if (j<0) j+=4;
255 act_button=buttons[j];
256 } /* if */
257 } /* for */
258 redrawmenu=2;
259 } /* if */
260 if (keyboard[down_key] && !old_keyboard[down_key]) {
261 int j=-1;
262 for(i=0;i<4 && j==-1;i++) {
263 if (act_button==buttons[i]) {
264 j=i+1;
265 if (j>=4) j-=4;
266 act_button=buttons[j];
267 } /* if */
268 } /* for */
269 redrawmenu=2;
270 } /* if */
271
272 for(i=0;i<4;i++) {
273 b=getbutton(buttons[i]);
274 if (b!=0) {
275 b->r=0.0f;
276 b->g=0.0f;
277 b->b=0.8f;
278 } /* if */
279 } /* if */
280 b=getbutton(act_button);
281 if (b!=0) {
282 b->r=0.5f;
283 b->g=0.5f;
284 b->b=1.0f;
285 } /* if */
286
287 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
288 switch(act_button) {
289 case ROBOT1_BUTTON:
290 {
291 STATUSBUTTON *b;
292
293 b=getbutton(act_button);
294 if (b!=0) {
295 b->r=1.0f;
296 b->g=0.5f;
297 b->b=0.5f;
298 } /* if */
299
300 act_menu=DIRECTCONTROL_MENU;
301 redrawmenu=2;
302 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
303 }
304 break;
305 case ROBOT2_BUTTON:
306 {
307 killmenu(ROBOT_MENU);
308 newmenu(ORDERS_MENU);
309 act_button=ORDERS1_BUTTON;
310 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
311 }
312 break;
313 case ROBOT3_BUTTON:
314 {
315 killmenu(ROBOT_MENU);
316 newmenu(COMBATMODE_MENU);
317 act_button=COMBAT6_BUTTON;
318 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
319 }
320 break;
321 case ROBOT4_BUTTON:
322 /* Back to the general menu: */
323 controlled->electronics_state+=6;
324 controlled->shipover=false;
325 controlled=0;
326 killmenu(ROBOT_MENU);
327 newmenu(GENERAL_MENU);
328 ship_op3=OP_UP;
329 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
330 break;
331 } /* switch */
332 } /* if */
333 }
334 break;
335
336 case DIRECTCONTROL_MENU:
337 /* Direct control of a robot by the user: */
338 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
339 redrawmenu=2;
340 act_menu=ROBOT_MENU;
341 } /* if */
342 break;
343
344 case DIRECTCONTROL2_MENU:
345 /* Direct control of a robot by the user: */
346 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
347 redrawmenu=2;
348 act_menu=COMBATMODE_MENU;
349 } /* if */
350 break;
351
352 case COMBATMODE_MENU:
353 /* Browsing through the COMBAT MENU: */
354 {
355 int i;
356 int buttons[6]={COMBAT1_BUTTON,COMBAT2_BUTTON,COMBAT3_BUTTON,COMBAT4_BUTTON,COMBAT5_BUTTON,COMBAT6_BUTTON};
357 STATUSBUTTON *b;
358
359 if (keyboard[up_key] && !old_keyboard[up_key]) {
360 int j=-1;
361 for(i=0;i<6 && j==-1;i++) {
362 if (act_button==buttons[i]) {
363 j=i-1;
364 if (j<0) j+=6;
365 act_button=buttons[j];
366 } /* if */
367 } /* for */
368 redrawmenu=2;
369 } /* if */
370 if (keyboard[down_key] && !old_keyboard[down_key]) {
371 int j=-1;
372 for(i=0;i<6 && j==-1;i++) {
373 if (act_button==buttons[i]) {
374 j=i+1;
375 if (j>=6) j-=6;
376 act_button=buttons[j];
377 } /* if */
378 } /* for */
379 redrawmenu=2;
380 } /* if */
381
382 for(i=0;i<6;i++) {
383 b=getbutton(buttons[i]);
384 if (b!=0) {
385 b->r=0.0f;
386 b->g=0.0f;
387 b->b=0.8f;
388 } /* if */
389 } /* if */
390 b=getbutton(act_button);
391 if (b!=0) {
392 b->r=0.5f;
393 b->g=0.5f;
394 b->b=1.0f;
395 } /* if */
396
397 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
398 switch(act_button) {
399 case COMBAT1_BUTTON:
400 /* Fire Nuclear: */
401 if ((controlled->angle==0 || controlled->angle==90 ||
402 controlled->angle==180 || controlled->angle==270) &&
403 controlled->pieces[3] &&
404 controlled->firetimer==0) {
405 controlled->op=ROBOTOP_NUCLEAR;
406 } /* if */
407 break;
408 case COMBAT2_BUTTON:
409 /* Fire Phasers: */
410 if ((controlled->angle==0 || controlled->angle==90 ||
411 controlled->angle==180 || controlled->angle==270) &&
412 controlled->pieces[2] &&
413 controlled->op==ROBOTOP_NONE) {
414 controlled->op=ROBOTOP_PHASERS;
415 } /* if */
416 break;
417 case COMBAT3_BUTTON:
418 /* Fire Missiles: */
419 if ((controlled->angle==0 || controlled->angle==90 ||
420 controlled->angle==180 || controlled->angle==270) &&
421 controlled->pieces[1] &&
422 controlled->op==ROBOTOP_NONE) {
423 controlled->op=ROBOTOP_MISSILES;
424 } /* if */
425 break;
426 case COMBAT4_BUTTON:
427 /* Fire Canons: */
428 if ((controlled->angle==0 || controlled->angle==90 ||
429 controlled->angle==180 || controlled->angle==270) &&
430 controlled->pieces[0] &&
431 controlled->op==ROBOTOP_NONE) {
432 controlled->op=ROBOTOP_CANNONS;
433 } /* if */
434 break;
435 case COMBAT5_BUTTON:
436 {
437 STATUSBUTTON *b;
438
439 b=getbutton(act_button);
440 if (b!=0) {
441 b->r=1.0f;
442 b->g=0.5f;
443 b->b=0.5f;
444 } /* if */
445
446 act_menu=DIRECTCONTROL2_MENU;
447 redrawmenu=2;
448 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
449 }
450 break;
451 case COMBAT6_BUTTON:
452 /* Back to the robot menu: */
453 killmenu(COMBATMODE_MENU);
454 newmenu(ROBOT_MENU);
455 act_button=ROBOT3_BUTTON;
456 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
457 break;
458 } /* switch */
459 } /* if */
460 }
461 break;
462 case ORDERS_MENU:
463 /* Browsing through the ORDERS MENU: */
464 {
465 int i;
466 int buttons[5]={ORDERS1_BUTTON,ORDERS2_BUTTON,ORDERS3_BUTTON,ORDERS4_BUTTON,ORDERS5_BUTTON};
467 STATUSBUTTON *b;
468
469 if (keyboard[up_key] && !old_keyboard[up_key]) {
470 int j=-1;
471 for(i=0;i<5 && j==-1;i++) {
472 if (act_button==buttons[i]) {
473 j=i-1;
474 if (j<0) j+=5;
475 act_button=buttons[j];
476 } /* if */
477 } /* for */
478 redrawmenu=2;
479 } /* if */
480 if (keyboard[down_key] && !old_keyboard[down_key]) {
481 int j=-1;
482 for(i=0;i<5 && j==-1;i++) {
483 if (act_button==buttons[i]) {
484 j=i+1;
485 if (j>=5) j-=5;
486 act_button=buttons[j];
487 } /* if */
488 } /* for */
489 redrawmenu=2;
490 } /* if */
491
492 for(i=0;i<5;i++) {
493 b=getbutton(buttons[i]);
494 if (b!=0) {
495 b->r=0.0f;
496 b->g=0.0f;
497 b->b=0.8f;
498 } /* if */
499 } /* if */
500 b=getbutton(act_button);
501 if (b!=0) {
502 b->r=0.5f;
503 b->g=0.5f;
504 b->b=1.0f;
505 } /* if */
506
507 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
508 switch(act_button) {
509 case ORDERS1_BUTTON:
510 /* STOP & DEFEND: */
511 controlled->program=PROGRAM_STOPDEFEND;
512 controlled->program_goal=Vector(-1,-1,-1);
513
514 killmenu(ORDERS_MENU);
515 newmenu(ROBOT_MENU);
516 act_button=ROBOT2_BUTTON;
517 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
518 break;
519 case ORDERS2_BUTTON:
520 /* ADVANCE ?? MILES: */
521 controlled->program=PROGRAM_ADVANCE;
522 controlled->program_parameter=0;
523 controlled->program_goal=Vector(-1,-1,-1);
524
525 killmenu(ORDERS_MENU);
526 newmenu(SELECTDISTANCE_MENU);
527 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
528 break;
529 case ORDERS3_BUTTON:
530 /* RETREAT ?? MILES: */
531 controlled->program=PROGRAM_RETREAT;
532 controlled->program_parameter=0;
533 controlled->program_goal=Vector(-1,-1,-1);
534
535 killmenu(ORDERS_MENU);
536 newmenu(SELECTDISTANCE_MENU);
537 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
538 break;
539 case ORDERS4_BUTTON:
540 /* SEARCH AND DESTROY: */
541 killmenu(ORDERS_MENU);
542 newmenu(TARGETD_MENU);
543 act_button=TARGET1_BUTTON;
544 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
545 break;
546 case ORDERS5_BUTTON:
547 /* SEARCH AND CAPTURE: */
548 killmenu(ORDERS_MENU);
549 newmenu(TARGETC_MENU);
550 act_button=TARGET1_BUTTON;
551 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
552 break;
553 } /* switch */
554 } /* if */
555 }
556 break;
557
558 case SELECTDISTANCE_MENU:
559 {
560 if (keyboard[up_key] && !old_keyboard[up_key]) {
561 controlled->program_parameter+=10;
562 if (controlled->program_parameter>190) controlled->program_parameter=190;
563 controlled->program_goal=Vector(-1,-1,-1);
564
565 redrawmenu=2;
566 } /* if */
567 if (keyboard[down_key] && !old_keyboard[down_key]) {
568 controlled->program_parameter-=10;
569 if (controlled->program_parameter<0) controlled->program_parameter=0;
570 controlled->program_goal=Vector(-1,-1,-1);
571
572 redrawmenu=2;
573 } /* if */
574 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
575 if (controlled->program_parameter==0) controlled->program=PROGRAM_STOPDEFEND;
576 controlled->program_goal=Vector(-1,-1,-1);
577
578 killmenu(SELECTDISTANCE_MENU);
579 newmenu(ROBOT_MENU);
580 act_button=ROBOT2_BUTTON;
581 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
582 } /* if */
583 }
584 break;
585
586 case TARGETD_MENU:
587 /* Browsing through the SELECT TARGET FOR DESTROYING MENU: */
588 {
589 int i;
590 int buttons[3]={TARGET1_BUTTON,TARGET2_BUTTON,TARGET3_BUTTON};
591 STATUSBUTTON *b;
592
593 if (keyboard[up_key] && !old_keyboard[up_key]) {
594 int j=-1;
595 for(i=0;i<3 && j==-1;i++) {
596 if (act_button==buttons[i]) {
597 j=i-1;
598 if (j<0) j+=3;
599 act_button=buttons[j];
600 } /* if */
601 } /* for */
602 redrawmenu=2;
603 } /* if */
604 if (keyboard[down_key] && !old_keyboard[down_key]) {
605 int j=-1;
606 for(i=0;i<3 && j==-1;i++) {
607 if (act_button==buttons[i]) {
608 j=i+1;
609 if (j>=3) j-=3;
610 act_button=buttons[j];
611 } /* if */
612 } /* for */
613 redrawmenu=2;
614 } /* if */
615
616 for(i=0;i<3;i++) {
617 b=getbutton(buttons[i]);
618 if (b!=0) {
619 b->r=0.0f;
620 b->g=0.0f;
621 b->b=0.8f;
622 } /* if */
623 } /* if */
624 b=getbutton(act_button);
625 if (b!=0) {
626 b->r=0.5f;
627 b->g=0.5f;
628 b->b=1.0f;
629 } /* if */
630
631 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
632 switch(act_button) {
633 case TARGET1_BUTTON:
634 if (controlled->pieces[0] ||
635 controlled->pieces[1] ||
636 controlled->pieces[2]) {
637 killmenu(TARGETD_MENU);
638 newmenu(ROBOT_MENU);
639 act_button=ROBOT2_BUTTON;
640 controlled->program=PROGRAM_DESTROY;
641 controlled->program_parameter=P_PARAM_ROBOTS;
642 controlled->program_goal=Vector(-1,-1,-1);
643 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
644 } else {
645 /* The robot has no standard WEAPONS!: */
646 if (S_wrong!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_wrong,0),128);
647 } /* if */
648 break;
649 case TARGET2_BUTTON:
650 if (controlled->pieces[3]) {
651 killmenu(TARGETD_MENU);
652 newmenu(ROBOT_MENU);
653 act_button=ROBOT2_BUTTON;
654 controlled->program=PROGRAM_DESTROY;
655 controlled->program_parameter=P_PARAM_EFACTORIES;
656 controlled->program_goal=Vector(-1,-1,-1);
657 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
658 } else {
659 /* The robot has no NUCLEAR weapons: */
660 if (S_wrong!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_wrong,0),128);
661 } /* if */
662 break;
663 case TARGET3_BUTTON:
664 if (controlled->pieces[3]) {
665 killmenu(TARGETD_MENU);
666 newmenu(ROBOT_MENU);
667 act_button=ROBOT2_BUTTON;
668 controlled->program=PROGRAM_DESTROY;
669 controlled->program_parameter=P_PARAM_WARBASES;
670 controlled->program_goal=Vector(-1,-1,-1);
671 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
672 } else {
673 /* The robot has no NUCLEAR weapons: */
674 if (S_wrong!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_wrong,0),128);
675 } /* if */
676 break;
677 } /* switch */
678 } /* if */
679 }
680 break;
681
682 case TARGETC_MENU:
683 /* Browsing through the SELECT TARGET FOR CAPTURING MENU: */
684 {
685 int i;
686 int buttons[3]={TARGET1_BUTTON,TARGET2_BUTTON,TARGET3_BUTTON};
687 STATUSBUTTON *b;
688
689 if (keyboard[up_key] && !old_keyboard[up_key]) {
690 int j=-1;
691 for(i=0;i<3 && j==-1;i++) {
692 if (act_button==buttons[i]) {
693 j=i-1;
694 if (j<0) j+=3;
695 act_button=buttons[j];
696 } /* if */
697 } /* for */
698 redrawmenu=2;
699 } /* if */
700 if (keyboard[down_key] && !old_keyboard[down_key]) {
701 int j=-1;
702 for(i=0;i<3 && j==-1;i++) {
703 if (act_button==buttons[i]) {
704 j=i+1;
705 if (j>=3) j-=3;
706 act_button=buttons[j];
707 } /* if */
708 } /* for */
709 redrawmenu=2;
710 } /* if */
711
712 for(i=0;i<3;i++) {
713 b=getbutton(buttons[i]);
714 if (b!=0) {
715 b->r=0.0f;
716 b->g=0.0f;
717 b->b=0.8f;
718 } /* if */
719 } /* if */
720 b=getbutton(act_button);
721 if (b!=0) {
722 b->r=0.5f;
723 b->g=0.5f;
724 b->b=1.0f;
725 } /* if */
726
727 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
728 switch(act_button) {
729 case TARGET1_BUTTON:
730 killmenu(TARGETC_MENU);
731 newmenu(ROBOT_MENU);
732 act_button=ROBOT2_BUTTON;
733 controlled->program=PROGRAM_CAPTURE;
734 controlled->program_parameter=P_PARAM_NFACTORIES;
735 controlled->program_goal=Vector(-1,-1,-1);
736 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
737 break;
738 case TARGET2_BUTTON:
739 killmenu(TARGETC_MENU);
740 newmenu(ROBOT_MENU);
741 act_button=ROBOT2_BUTTON;
742 controlled->program=PROGRAM_CAPTURE;
743 controlled->program_parameter=P_PARAM_EFACTORIES;
744 controlled->program_goal=Vector(-1,-1,-1);
745 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
746 break;
747 case TARGET3_BUTTON:
748 killmenu(TARGETC_MENU);
749 newmenu(ROBOT_MENU);
750 act_button=ROBOT2_BUTTON;
751 controlled->program=PROGRAM_CAPTURE;
752 controlled->program_parameter=P_PARAM_WARBASES;
753 controlled->program_goal=Vector(-1,-1,-1);
754 if (S_select!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_select,0),128);
755 break;
756 } /* switch */
757 } /* if */
758 }
759 break;
760 } /* switch */
761
762
763 #ifdef _WRITE_REPORT_
764 fprintf(debug_fp,"Viewport\n");
765 fflush(debug_fp);
766 #endif
767
768 viewp.x=shipp.x+0.5;
769 viewp.y=shipp.y+0.5;
770 viewp.z=shipp.z-3*zoom;
771 if (viewp.z<0) viewp.z=0;
772 if (viewp.x<3*zoom) {
773 viewp.x=3*zoom;
774 if (viewp.x>map_w-3*zoom) viewp.x=map_w/2;
775 } else {
776 if (viewp.x>map_w-3*zoom) {
777 viewp.x=map_w-3*zoom;
778 if (viewp.x<3*zoom) viewp.x=map_w/2;
779 } /* if */
780 } /* if */
781 if (viewp.y<3*zoom) {
782 viewp.y=3*zoom;
783 if (viewp.y>map_h-3*zoom) viewp.y=map_h/2;
784 } else {
785 if (viewp.y>map_h-3*zoom) {
786 viewp.y=map_h-3*zoom;
787 if (viewp.y<3*zoom) viewp.y=map_h/2;
788 } /* if */
789 } /* if */
790
791 #ifdef _WRITE_REPORT_
792 fprintf(debug_fp,"Resources\n");
793 fflush(debug_fp);
794 #endif
795
796 {
797 STATUSBUTTON *timeb;
798
799 second+=5;
800 if (second>=60) {
801 second=0;
802 redrawmenu=2;
803 minute+=5;
804 if (minute>=60) {
805 minute=0;
806 hour++;
807 if (hour>=24) {
808 int i;
809
810 hour=0;
811 day++;
812 /* Resource actualization: */
813 resources[0][0]+=statistics[0][0]*5;
814 if (level==0) {
815 int bonus[5]={0,5,6,6,8};
816 if (statistics[1][0]<4) resources[1][0]+=bonus[statistics[1][0]];
817 else resources[1][0]+=statistics[1][0]*2;
818 } /* if */
819 if (level==1) {
820 int bonus[5]={0,5,8,9,12};
821 if (statistics[1][0]<4) resources[1][0]+=bonus[statistics[1][0]];
822 else resources[1][0]+=statistics[1][0]*3;
823 } /* if */
824 if (level==2) {
825 int bonus[5]={0,5,10,12,16};
826 if (statistics[1][0]<4) resources[1][0]+=bonus[statistics[1][0]];
827 else resources[1][0]+=statistics[1][0]*4;
828 } /* if */
829 if (level==3) {
830 int bonus[5]={0,5,10,15,20};
831 if (statistics[1][0]<4) resources[1][0]+=bonus[statistics[1][0]];
832 else resources[1][0]+=statistics[1][0]*5;
833 } /* if */
834 for(i=1;i<7;i++) {
835 resources[0][i]+=statistics[0][i]*2;
836 resources[1][i]+=statistics[1][i]*2;
837 } /* for */
838
839 } /* if */
840 } /* if */
841 timeb=getbutton(TIME_BUTTON);
842 if (timeb!=0) {
843 sprintf(timeb->text1,"Day: %i",day);
844 sprintf(timeb->text2,"Hour: %.2i:%.2i",hour,minute);
845 } /* if */
846 } /* if */
847 }
848
849 #ifdef _WRITE_REPORT_
850 fprintf(debug_fp,"Ship landing\n");
851 fflush(debug_fp);
852 #endif
853
854 /* Test if the ship has landed over a Factory: */
855 {
856 List<BUILDING> l;
857 BUILDING *b;
858
859 l.Instance(buildings);
860 l.Rewind();
861 while(l.Iterate(b)) {
862 if (b->type==B_WARBASE && b->owner==1 &&
863 shipp.x==b->pos.x && shipp.y==b->pos.y && shiplanded) {
864 game_state=STATE_CONSTRUCTION;
865 construction_pointer=0;
866 construction[0]=false;
867 construction[1]=false;
868 construction[2]=false;
869 construction[3]=false;
870 construction[4]=false;
871 construction[5]=false;
872 construction[6]=false;
873 construction[7]=false;
874 in_construction.traction=-1;
875 in_construction.pieces[0]=false;
876 in_construction.pieces[1]=false;
877 in_construction.pieces[2]=false;
878 in_construction.pieces[3]=false;
879 in_construction.pieces[4]=false;
880 in_construction.pos.x=b->pos.x+2.5;
881 in_construction.pos.y=b->pos.y+0.5;
882 in_construction.pos.z=b->pos.z;
883 } /* if */
884 } /* while */
885 }
886
887 /* Test if the ship has landed over a robot: */
888 if (act_menu==GENERAL_MENU &&
889 (int(shipp.x*8)%4)==0 &&
890 (int(shipp.y*8)%4)==0) {
891 List<ROBOT> l;
892 ROBOT *r;
893
894 l.Instance(robots[0]);
895 l.Rewind();
896 while(l.Iterate(r)) {
897 if (shipp.x==(r->pos.x-0.5) && shipp.y==(r->pos.y-0.5) && shiplanded) {
898 /* The ship has landed over a robot: */
899 r->shipover=true;
900 controlled=r;
901 if (controlled->op==ROBOTOP_FORWARD) controlled->op=ROBOTOP_NONE;
902 if (controlled->program==PROGRAM_FORWARD) controlled->program=PROGRAM_STOPDEFEND;
903 killmenu(GENERAL_MENU);
904 newmenu(ROBOT_MENU);
905 act_button=ROBOT4_BUTTON;
906 } /* while */
907 } /* while */
908 } /* if */
909
910 #ifdef _WRITE_REPORT_
911 fprintf(debug_fp,"Robots\n");
912 fflush(debug_fp);
913 #endif
914
915 /* Robot cycles: */
916 {
917 int i;
918 List<ROBOT> l,robotstodelete;
919 ROBOT *r;
920 float x[2],y[2],minz;
921 Vector old_pos;
922 int old_chassis_state;
923 int terrain;
924
925 for(i=0;i<2;i++) {
926
927 #ifdef _WRITE_REPORT_
928 fprintf(debug_fp,"Player %i robots\n",i);
929 fflush(debug_fp);
930 #endif
931
932 l.Instance(robots[i]);
933 l.Rewind();
934 while(l.Iterate(r)) {
935 /* Robot cycle: */
936
937 #ifdef _WRITE_REPORT_
938 fprintf(debug_fp,"START ROBOT\n");
939 fflush(debug_fp);
940 #endif
941
942 /* Animations: */
943 if (r->electronics_state!=0) {
944 r->electronics_state+=6;
945 if (r->electronics_state>=360) r->electronics_state=0;
946 } /* if */
947
948 /* Apply ROBOT operator: */
949 old_pos=r->pos;
950 old_chassis_state=r->chassis_state;
951 if (r->traction==2) {
952 r->chassis_state++;
953 } /* if */
954 x[0]=r->pos.x-0.5;
955 x[1]=r->pos.x+0.5;
956 y[0]=r->pos.y-0.5;
957 y[1]=r->pos.y+0.5;
958 minz=MapMaxZ(x,y);
959 terrain=WorseMapTerrain(x,y);
960
961 #ifdef _WRITE_REPORT_
962 fprintf(debug_fp,"Avoid robot deadlock\n");
963 fflush(debug_fp);
964 #endif
965
966 /* Avoid that a Robot can walk agains another and they both get stuck: */
967 if (r->op==ROBOTOP_FORWARD &&
968 (int(r->pos.x*256)%128)==0 &&
969 (int(r->pos.y*256)%128)==0) {
970 switch(r->angle) {
971 case 0:
972 if (AI_WorseMapTerrain(int((r->pos.x+0.5)/0.5),int((r->pos.y-0.5)/0.5),1,2)>T_HOLE) r->op=ROBOTOP_NONE;
973 break;
974 case 90:
975 if (AI_WorseMapTerrain(int((r->pos.x-0.5)/0.5),int((r->pos.y+0.5)/0.5),2,1)>T_HOLE) r->op=ROBOTOP_NONE;
976 break;
977 case 180:
978 if (AI_WorseMapTerrain(int((r->pos.x-1.0)/0.5),int((r->pos.y-0.5)/0.5),1,2)>T_HOLE) r->op=ROBOTOP_NONE;
979 break;
980 case 270:
981 if (AI_WorseMapTerrain(int((r->pos.x-0.5)/0.5),int((r->pos.y-1.0)/0.5),2,1)>T_HOLE) r->op=ROBOTOP_NONE;
982 break;
983 } /* switch */
984 } /* if */
985
986 #ifdef _WRITE_REPORT_
987 fprintf(debug_fp,"ROBOT COMMAND: %i\n",r->op);
988 fflush(debug_fp);
989 #endif
990 if (r->op==ROBOTOP_FORWARD) {
991 float speed=RobotSpeed(r->traction,terrain);
992
993 /* BIPOD ANIMATION: */
994 if (r->traction==0) {
995 r->chassis_state+=int(speed/0.00390625);
996 if (r->chassis_state>64) r->chassis_state=-63;
997 } /* if */
998
999 /* TRACKS PARTICLES: */
1000 if (r->traction==1) {
1001 if (detaillevel>=4) {
1002 int i;
1003 PARTICLE *p;
1004 Vector pos,sp1;
1005 float red,g,b;
1006
1007 for(i=0;i<2;i++) {
1008 pos.x=r->pos.x+float(rand()%10)/100.0;
1009 pos.y=r->pos.y+float(rand()%10)/100.0;
1010 pos.z=0;
1011 red=0.9F+float(rand()%21-10)/100.0;
1012 g=0.7F+float(rand()%21-10)/100.0;
1013 b=0.5F+float(rand()%21-10)/100.0;
1014 switch(r->angle) {
1015 case 0:sp1=Vector(-0.05,float(rand()%9-4)/200.0,0);
1016 pos.x-=0.25;
1017 pos.y+=((rand()%2)==0 ? -0.5 : 0.5);
1018 break;
1019 case 90:sp1=Vector(float(rand()%9-4)/200.0,-0.05,0);
1020 pos.y-=0.25;
1021 pos.x+=((rand()%2)==0 ? -0.5 : 0.5);
1022 break;
1023 case 180:sp1=Vector(0.05,float(rand()%9-4)/200.0,0);
1024 pos.x+=0.25;
1025 pos.y+=((rand()%2)==0 ? -0.5 : 0.5);
1026 break;
1027 case 270:sp1=Vector(float(rand()%9-4)/200.0,0.05,0);
1028 pos.y+=0.25;
1029 pos.x+=((rand()%2)==0 ? -0.5 : 0.5);
1030 break;
1031 } /* switch */
1032 p=new PARTICLE(pos,sp1,Vector(0,0,0.05),0,0.3, red,g,b, 1.0,0.0,20+(rand()%10));
1033 particles.Add(p);
1034 } /* for */
1035 } /* if */
1036 } /* if */
1037
1038 switch(r->angle) {
1039 case 0:if (r->pos.x<map_w-0.5) r->pos.x+=speed;
1040 break;
1041 case 90:if (r->pos.y>0.5) r->pos.y+=speed;
1042 break;
1043 case 180:if (r->pos.x>0.5) r->pos.x-=speed;
1044 break;
1045 case 270:if (r->pos.y<map_h-0.5) r->pos.y-=speed;
1046 break;
1047 } /* switch */
1048 } else {
1049 if (r->traction==0) r->chassis_state=0;
1050 } /* if */
1051
1052 if (r->op==ROBOTOP_LEFT) r->angle-=RobotRotationSpeed(r->traction,terrain);
1053 if (r->op==ROBOTOP_RIGHT) r->angle+=RobotRotationSpeed(r->traction,terrain);
1054 if (r->angle>=360) r->angle-=360;
1055 if (r->angle<0) r->angle+=360;
1056
1057 if (r->op==ROBOTOP_CANNONS && r->firetimer==0) {
1058 BULLET *b;
1059 Vector pos;
1060
1061 pos=r->pos;
1062 pos.z=r->piecez(0)+0.3f;
1063
1064 b=new BULLET(0,pos,r->angle,r);
1065 b->cmc=BulletCMC(b);
1066
1067 bullets.Add(b);
1068 if (S_shot!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_shot,0),SFX_volume(r->pos));
1069 } /* if */
1070
1071 if (r->op==ROBOTOP_MISSILES && r->firetimer==0) {
1072 BULLET *b;
1073 Vector pos;
1074
1075 pos=r->pos;
1076 pos.z=r->piecez(1)+0.2f;
1077
1078 b=new BULLET(1,pos,r->angle,r);
1079 b->cmc=BulletCMC(b);
1080
1081 bullets.Add(b);
1082 if (S_shot!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_shot,0),SFX_volume(r->pos));
1083 } /* if */
1084
1085 if (r->op==ROBOTOP_PHASERS && r->firetimer==0) {
1086 BULLET *b;
1087 Vector pos;
1088
1089 pos=r->pos;
1090 pos.z=r->piecez(2)+0.3f;
1091
1092 b=new BULLET(2,pos,r->angle,r);
1093 b->cmc=BulletCMC(b);
1094
1095 bullets.Add(b);
1096 if (S_shot!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_shot,0),SFX_volume(r->pos));
1097 } /* if */
1098
1099 if (r->op==ROBOTOP_CANNONS ||
1100 r->op==ROBOTOP_MISSILES ||
1101 r->op==ROBOTOP_PHASERS) r->firetimer++;
1102
1103 if (r->op==ROBOTOP_NUCLEAR) {
1104 EXPLOSION *n;
1105
1106 n=new EXPLOSION(r->pos,2);
1107 explosions.Add(n);
1108
1109 /* Robot destroyed: */
1110 if (r==controlled) {
1111 controlled->shipover=false;
1112 controlled=0;
1113 killmenu(act_menu);
1114 newmenu(GENERAL_MENU);
1115 } /* if */
1116
1117 /* Find Robots to destroy: */
1118 {
1119 List<ROBOT> l;
1120 ROBOT *r;
1121 int i;
1122 float distance;
1123
1124 for(i=0;i<2;i++) {
1125 l.Instance(robots[i]);
1126 l.Rewind();
1127 while(l.Iterate(r)) {
1128 distance=(r->pos-n->pos).norma();
1129 if (distance<=2.5f) robotstodelete.Add(r);
1130 } /* while */
1131 } /* for */
1132 }
1133
1134 /* Find buildings to destroy: */
1135 {
1136 List<BUILDING> l,todelete;
1137 BUILDING *b;
1138 float distance;
1139
1140 l.Instance(buildings);
1141 l.Rewind();
1142 while(l.Iterate(b)) {
1143 distance=(b->pos-(n->pos-Vector(0.5,0.5,0.5))).norma();
1144 if (distance<=2.5f) todelete.Add(b);
1145 } /* while */
1146
1147 while(!todelete.EmptyP()) {
1148 b=todelete.Extract();
1149 buildings.DeleteElement(b);
1150 AI_removebuilding(b->pos);
1151 delete b;
1152 } /* while */
1153 }
1154
1155 if (S_explosion!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_explosion,0),SFX_volume(r->pos));
1156 recomputestatistics=true;
1157 } /* if */
1158
1159 if (r!=0) {
1160 x[0]=r->pos.x-0.5;
1161 x[1]=r->pos.x+0.5;
1162 y[0]=r->pos.y-0.5;
1163 y[1]=r->pos.y+0.5;
1164 minz=MapMaxZ(x,y);
1165 terrain=WorseMapTerrain(x,y);
1166 r->pos.z=minz;
1167
1168 if (r->shipover) {
1169 shipp.x=r->pos.x-0.5;
1170 shipp.y=r->pos.y-0.5;
1171 shipp.z=r->pos.z+r->cmc.z[1];
1172 } /* if */
1173
1174 /* Collision: */
1175 if (RobotCollision(r,false) || !Walkable(r->traction,terrain)) {
1176 r->pos=old_pos;
1177 if (r->traction==0) r->chassis_state=old_chassis_state;
1178 if (r->shipover) {
1179 shipp.x=r->pos.x-0.5;
1180 shipp.y=r->pos.y-0.5;
1181 shipp.z=r->pos.z+r->cmc.z[1];
1182 } /* if */
1183 } else {
1184 AI_moverobot(old_pos,r->pos,i);
1185 } /* if */
1186
1187 if (r->op==ROBOTOP_FORWARD && (r->angle==0 || r->angle==180) && (int(r->pos.x*256)%128)==0) r->op=ROBOTOP_NONE;
1188 if (r->op==ROBOTOP_FORWARD && (r->angle==90 || r->angle==270) && (int(r->pos.y*256)%128)==0) r->op=ROBOTOP_NONE;
1189 if (r->op==ROBOTOP_LEFT && (r->angle%90)==0) r->op=ROBOTOP_NONE;
1190 if (r->op==ROBOTOP_RIGHT && (r->angle%90)==0) r->op=ROBOTOP_NONE;
1191 if (r->op==ROBOTOP_CANNONS && r->firetimer>=64) {
1192 r->op=ROBOTOP_NONE;
1193 r->firetimer=0;
1194 } /* if */
1195 if (r->op==ROBOTOP_MISSILES && r->firetimer>=64) {
1196 r->op=ROBOTOP_NONE;
1197 r->firetimer=0;
1198 } /* if */
1199 if (r->op==ROBOTOP_PHASERS && r->firetimer>=64) {
1200 r->op=ROBOTOP_NONE;
1201 r->firetimer=0;
1202 } /* if */
1203
1204 /* Follow ROBOT program: */
1205 if (r->op==ROBOTOP_NONE && !r->shipover) {
1206 #ifdef _WRITE_REPORT_
1207 fprintf(debug_fp,"Robot program: %i\n",r->program);
1208 fflush(debug_fp);
1209 #endif
1210 switch(r->program) {
1211 case PROGRAM_NONE:
1212 break;
1213 case PROGRAM_FORWARD:
1214 r->op=ROBOTOP_FORWARD;
1215 break;
1216 case PROGRAM_STOPDEFEND:
1217 r->op=AI_program_stopdefend(&(r->program_goal),r->pos,r->angle,r->traction,r->pieces[4],i+1,r->pieces);
1218 break;
1219 case PROGRAM_ADVANCE:
1220 r->op=AI_program_advance(r->program_parameter,r->pos,r->angle,r->traction,r->pieces[4],i+1,r->pieces);
1221 if (r->op==ROBOTOP_FORWARD && r->angle==90) r->program_parameter--;
1222 if (r->op==ROBOTOP_FORWARD && r->angle==270) r->program_parameter++;
1223 if (r->program_parameter==0) r->program=PROGRAM_STOPDEFEND;
1224 break;
1225 case PROGRAM_RETREAT:
1226 r->op=AI_program_retreat(r->program_parameter,r->pos,r->angle,r->traction,r->pieces[4],i+1,r->pieces);
1227 if (r->op==ROBOTOP_FORWARD && r->angle==270) r->program_parameter--;
1228 if (r->op==ROBOTOP_FORWARD && r->angle==90) r->program_parameter++;
1229 if (r->program_parameter==0) r->program=PROGRAM_STOPDEFEND;
1230 break;
1231 case PROGRAM_DESTROY:
1232 r->op=AI_program_destroy(r->program_parameter,&(r->program_goal),r->pos,r->angle,r->traction,r->pieces[4],i+1,r->pieces);
1233 // if (r->program_goal.x==-1) r->program=PROGRAM_STOPDEFEND;
1234 break;
1235 case PROGRAM_CAPTURE:
1236 r->op=AI_program_capture(r->program_parameter,&(r->program_goal),r->pos,r->angle,r->traction,r->pieces[4],i+1,r->pieces);
1237 // if (r->program_goal.x==-1) r->program=PROGRAM_STOPDEFEND;
1238 break;
1239 } /* switch */
1240 } /* if */
1241
1242 /* Follow USER's command: */
1243 if (r->op==ROBOTOP_NONE && r->shipover &&
1244 (act_menu==DIRECTCONTROL_MENU ||
1245 act_menu==DIRECTCONTROL2_MENU)) {
1246 #ifdef _WRITE_REPORT_
1247 fprintf(debug_fp,"User command\n",i);
1248 fflush(debug_fp);
1249 #endif
1250 if (keyboard[right_key]) {
1251 if (r->angle==0) {
1252 r->op=ROBOTOP_FORWARD;
1253 } else {
1254 if (r->angle==270) r->op=ROBOTOP_RIGHT;
1255 else r->op=ROBOTOP_LEFT;
1256 } /* if */
1257 } /* if */
1258 if (keyboard[left_key]) {
1259 if (r->angle==180) {
1260 r->op=ROBOTOP_FORWARD;
1261 } else {
1262 if (r->angle==90) r->op=ROBOTOP_RIGHT;
1263 else r->op=ROBOTOP_LEFT;
1264 } /* if */
1265 } /* if */
1266 if (keyboard[up_key]) {
1267 if (r->angle==90) {
1268 r->op=ROBOTOP_FORWARD;
1269 } else {
1270 if (r->angle==0) r->op=ROBOTOP_RIGHT;
1271 else r->op=ROBOTOP_LEFT;
1272 } /* if */
1273 } /* if */
1274 if (keyboard[down_key]) {
1275 if (r->angle==270) {
1276 r->op=ROBOTOP_FORWARD;
1277 } else {
1278 if (r->angle==180) r->op=ROBOTOP_RIGHT;
1279 else r->op=ROBOTOP_LEFT;
1280 } /* if */
1281 } /* if */
1282
1283 } /* if */
1284 } /* if */
1285 } /* while */
1286
1287 #ifdef _WRITE_REPORT_
1288 fprintf(debug_fp,"Deleting robots\n",i);
1289 fflush(debug_fp);
1290 #endif
1291 while(!robotstodelete.EmptyP()) {
1292 r=robotstodelete.Extract();
1293 AI_killrobot(r->pos);
1294 robots[0].DeleteElement(r);
1295 robots[1].DeleteElement(r);
1296 delete r;
1297 } /* while */
1298
1299 } /* for */
1300 }
1301
1302 #ifdef _WRITE_REPORT_
1303 fprintf(debug_fp,"Buildings\n");
1304 fflush(debug_fp);
1305 #endif
1306
1307 /* Buildings: */
1308 {
1309 List<BUILDING> l;
1310 BUILDING *b;
1311
1312 l.Instance(buildings);
1313 l.Rewind();
1314 while(l.Iterate(b)) {
1315 if (b->type==B_FACTORY_ELECTRONICS ||
1316 b->type==B_FACTORY_NUCLEAR ||
1317 b->type==B_FACTORY_PHASERS ||
1318 b->type==B_FACTORY_MISSILES ||
1319 b->type==B_FACTORY_CANNONS ||
1320 b->type==B_FACTORY_CHASSIS) {
1321 int robot=AI_robothere(b->pos+Vector(1,0,0));
1322 if (robot==0) {
1323 b->status=0;
1324 } else {
1325 if (robot==T_ROBOT) b->status++;
1326 if (robot==T_EROBOT) b->status--;
1327
1328 if (b->status>=12*12*12) {
1329 b->owner=1;
1330 b->status=0;
1331 recomputestatistics=true;
1332 } /* if */
1333
1334 if (b->status<=-12*12*12) {
1335 b->owner=2;
1336 b->status=0;
1337 recomputestatistics=true;
1338 } /* if */
1339 } /* if */
1340 } /* if */
1341
1342 if (b->type==B_WARBASE) {
1343 int robot=AI_robothere(b->pos+Vector(2,0,0));
1344 if (robot==0) {
1345 b->status=0;
1346 } else {
1347 if (robot==T_ROBOT) b->status++;
1348 if (robot==T_EROBOT) b->status--;
1349
1350 if (b->status>=12*12*12) {
1351 b->owner=1;
1352 b->status=0;
1353 recomputestatistics=true;
1354 } /* if */
1355
1356 if (b->status<=-12*12*12) {
1357 b->owner=2;
1358 b->status=0;
1359 recomputestatistics=true;
1360 } /* if */
1361 } /* if */
1362 } /* if */
1363
1364 } /* while */
1365 }
1366
1367 #ifdef _WRITE_REPORT_
1368 fprintf(debug_fp,"Bullets\n");
1369 fflush(debug_fp);
1370 #endif
1371
1372 /* Bullets: */
1373 {
1374 List<BULLET> l,todelete;
1375 BULLET *b;
1376 ROBOT *r;
1377 int persistence=CANNON_PERSISTENCE;
1378
1379 l.Instance(bullets);
1380 l.Rewind();
1381 while(l.Iterate(b)) {
1382 r=0;
1383
1384 if (b->angle==0) b->pos.x+=BULLET_SPEED;
1385 if (b->angle==90) b->pos.y+=BULLET_SPEED;
1386 if (b->angle==180) b->pos.x-=BULLET_SPEED;
1387 if (b->angle==270) b->pos.y-=BULLET_SPEED;
1388 b->step++;
1389
1390 if (b->type==1) persistence=MISSILE_PERSISTENCE;
1391 if (b->type==2) persistence=PHASER_PERSISTENCE;
1392 if (b->step>=persistence || BulletCollision(b,&r)) {
1393 todelete.Add(b);
1394 if (b->step<persistence) {
1395 EXPLOSION *n;
1396
1397 n=new EXPLOSION(b->pos,0);
1398 explosions.Add(n);
1399 } /* if */
1400 } /* if */
1401
1402 if (r!=0) {
1403 int damage=0;
1404 /* The bullet has collided with a robot: */
1405 if (!r->bullethit(b->type)) {
1406 /* Robot destroyed: */
1407 EXPLOSION *n;
1408
1409 n=new EXPLOSION(r->pos,1);
1410 explosions.Add(n);
1411
1412 if (S_explosion!=0 && sound) Mix_Volume(Mix_PlayChannel(-1,S_explosion,0),SFX_volume(r->pos));
1413 if (r==controlled) {
1414 controlled->shipover=false;
1415 controlled=0;
1416 killmenu(ALL_MENUS);
1417 newmenu(GENERAL_MENU);
1418 } /* if */
1419 AI_killrobot(r->pos);
1420 if (robots[0].MemberRefP(r)) robots[0].DeleteElement(r);
1421 else robots[1].DeleteElement(r);
1422 delete r;
1423 } /* if */
1424 } /* if */
1425
1426 } /* while */
1427
1428 while(!todelete.EmptyP()) {
1429 b=todelete.Extract();
1430 bullets.DeleteElement(b);
1431 delete b;
1432 } /* while */
1433 }
1434
1435 #ifdef _WRITE_REPORT_
1436 fprintf(debug_fp,"Nuclear explosions\n");
1437 fflush(debug_fp);
1438 #endif
1439
1440 /* Nuclear explosions: */
1441 {
1442 List<EXPLOSION> l,todelete;
1443 EXPLOSION *n;
1444
1445 l.Instance(explosions);
1446 l.Rewind();
1447 while(l.Iterate(n)) {
1448 if (n->size==0) n->step+=2;
1449 if (n->size==1) n->step++;
1450 n->step++;
1451 if (n->step>=128) todelete.Add(n);
1452 } /* while */
1453
1454 while(!todelete.EmptyP()) {
1455 n=todelete.Extract();
1456 explosions.DeleteElement(n);
1457 delete n;
1458 } /* while */
1459 }
1460
1461 #ifdef _WRITE_REPORT_
1462 fprintf(debug_fp,"Particles\n");
1463 fflush(debug_fp);
1464 #endif
1465
1466 /* Particles: */
1467 {
1468 List<PARTICLE> l,todelete;
1469 PARTICLE *p;
1470
1471 l.Instance(particles);
1472 l.Rewind();
1473 while(l.Iterate(p)) {
1474 if (!CycleParticle(p)) todelete.Add(p);
1475 } /* while */
1476
1477 while(!todelete.EmptyP()) {
1478 p=todelete.Extract();
1479 particles.DeleteElement(p);
1480 delete p;
1481 } /* while */
1482 }
1483
1484 }
1485
1486 #ifdef _WRITE_REPORT_
1487 fprintf(debug_fp,"Starting STATUS cycle\n");
1488 fflush(debug_fp);
1489 #endif
1490
1491 /* STATUS Cycle: */
1492 {
1493 List<STATUSBUTTON> l,todelete;
1494 STATUSBUTTON *b;
1495
1496 l.Instance(buttons);
1497 l.Rewind();
1498 while(l.Iterate(b)) {
1499 if (b->status!=0) {
1500 b->status++;
1501 redrawmenu=2;
1502 if (b->status>=16) {
1503 todelete.Add(b);
1504 } /* if */
1505 } /* if */
1506 } /* while */
1507
1508 while(!todelete.EmptyP()) {
1509 b=todelete.Extract();
1510 buttons.DeleteElement(b);
1511 delete b;
1512 } /* while */
1513 }
1514
1515 if (game_state==STATE_PLAYING && keyboard[pause_key] && !old_keyboard[pause_key]) {
1516 game_state=STATE_PAUSE;
1517 option_menu=0;
1518 } /* if */
1519
1520 if ((statistics[0][0]==0 || statistics[1][0]==0) && game_finished==0) {
1521 game_finished++;
1522 game_started=0;
1523 } /* if */
1524 if (game_finished>0) game_finished++;
1525 if (game_finished>=END_TIME) return false;
1526
1527 if (game_started>0) game_started--;
1528
1529 #ifdef _WRITE_REPORT_
1530 fprintf(debug_fp,"PLAY CYCLE ENDS\n");
1531 fflush(debug_fp);
1532 #endif
1533
1534 return true;
1535 } /* NETHER::cycle */
1536
1537