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