1 /*****************************************************************************
2  **  This is part of the SpaceZero program
3  **  Copyright(C) 2006-2013  MRevenga
4  **
5  **  This program is free software; you can redistribute it and/or modify
6  **  it under the terms of the GNU General Public License (version 3), or
7  **  (at your option) any later version, as published by the Free Software
8  **  Foundation.
9  **
10  **  This program is distributed in the hope that it will be useful,
11  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  **  GNU General Public License for more details.
14  **
15  **  You should have received a copy of the GNU General Public License
16  **  along with this program; if not, write to the Free Software
17  **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ******************************************************************************/
19 
20 /*************  SpaceZero  M.R.H. 2006-2013 ******************
21 		Author: MRevenga
22 		E-mail: mrevenga at users.sourceforge.net
23 		version 0.86 December 2013
24 **************************************************************/
25 
26 #include <stdlib.h>
27 #include <math.h>
28 #include <stdio.h>
29 #include <time.h>
30 #include <string.h>
31 #include <pthread.h>
32 #include <semaphore.h>
33 #include <signal.h>
34 #include <sys/time.h>
35 #include <fcntl.h>
36 #include "objects.h"
37 #include "spacezero.h"
38 #include "players.h"
39 #include "functions.h"
40 #include "spacecomm.h"
41 #include "sound.h"
42 #include "locales.h"
43 #include "graphics.h"
44 #include "ai.h"
45 #include "save.h"
46 #include "clock.h"
47 #include "shell.h"
48 #include "planetnames.h"
49 #include "randomnamegen.h"
50 #include "sectors.h"
51 #include "snow.h"
52 
53 
54 extern int g_objid;  /* id of the objects */
55 extern struct Global glocal;
56 extern GtkWidget *d_a;
57 extern GtkWidget *win_main;
58 extern GdkFont *gfont;
59 extern GdkPixmap *pixmap;
60 extern GdkPixmap *pixmap_stat;
61 extern GdkGC *gcolors[];
62 
63 int gdrawmenu=TRUE;
64 struct Draw gdraw;
65 
66 
67 int actual_player,actual_player0;
68 
69 int record=0;
70 int nav_mode=RELATIVE;
71 
72 int p_time=0;
73 int g_nobjsend=0;
74 int g_nshotsend=0;
75 int g_nobjmaxsend=0;
76 int g_nobjtype[6]={0,0,0,0,0,0};
77 int gameover=FALSE;
78 int observeenemies=FALSE;
79 
80 char version[64]={"0.86.00"};
81 char copyleft[]="";
82 char TITLE[64]="SpaceZero  ";
83 char last_revision[]={"Dec 2013"};
84 
85 
86 Object *ship_c; /* ship controled by keyboard */
87 Object *cv;     /* coordinates center */
88 int fobj[4];
89 sem_t sem_barrier,sem_barrier1;
90 
91 
92 int g_cont;
93 time_t gtime0;
94 double fps; /* frames / second*/
95 
96 int order2thread;
97 
98 int *cell;
99 static struct timeval init_time;
100 
101 extern struct Buffer buffer1,buffer2;      /* buffers used in comm. */
102 
103 extern struct HeadObjList listheadobjs;    /* list of all objects */
104 struct HeadObjList listheadplanets;        /* list of all planets */
105 struct HeadObjList *listheadcontainer;     /* lists of objects that contain objects: free space and planets*/
106 struct HeadObjList *listheadkplanets;      /* lists of planets known by players */
107 struct HeadObjList listheadplayer;         /* list of objects of each player */
108 
109 struct CharListHead gameloglist;           /* list of all game messages */
110 struct Window windowgamelog;
111 
112 struct TextMessageList listheadtext;
113 extern struct Parametres param;
114 Vector r_rel;
115 
116 struct Habitat habitat;
117 
118 
119 char clientname[MAXTEXTLEN];
120 
121 
122 /*  sound */
123 int soundenabled=TRUE;
124 /* -- sound */
125 
126 char *savefile;
127 char *recordfile;
128 char *optionsfile;
129 char *keyboardfile;
130 
131 struct MenuHead *menuhead;
132 
133 
134 /*void signal_handler(int ,siginfo_t *,void *);*/
135 void int_handler(int);
136 void segfault_handler(int);
137 
138 
139 
main(int argc,char * argv[])140 int main(int argc,char *argv[]){
141   /*
142     version 2
143     TODO reorganized this
144   */
145 
146   GtkWidget *drawing_area;
147 
148   char title[64]="";
149   int state;
150   struct sigaction sa;
151   int width,height;
152 
153   srand(time(NULL));
154 
155   /******** signals ***********/
156   /*
157     sa.sa_sigaction=signal_handler;
158     sigemptyset(&sa.sa_mask);
159     sa.sa_flags=SA_SIGINFO;
160     if(sigaction(SIGNAL0,&sa,NULL)){
161     perror("sigaction");
162     exit(-1);
163     }
164   */
165 
166   sa.sa_handler=int_handler;
167   sigemptyset(&sa.sa_mask);
168   sa.sa_flags=0;
169   if(sigaction(SIGINT,&sa,NULL)){
170     perror("sigaction");
171     exit(-1);
172   }
173 
174   /* sa.sa_handler=segfault_handler; */
175   /* sigemptyset(&sa.sa_mask); */
176   /* sa.sa_flags=0; */
177   /* if(sigaction(SIGSEGV,&sa,NULL)){ */
178   /*   perror("sigaction"); */
179   /*   exit(-1); */
180   /* } */
181 
182   /******** --signals ***********/
183 
184   sem_init(&sem_barrier,0,0);
185   sem_init(&sem_barrier1,0,0);
186 
187   MemUsed(MRESET,0);
188 
189 
190   Keystrokes(RESET,NULL,NULL);
191 
192   PrintWarnings(version);
193   optionsfile=CreateOptionsFile();
194   recordfile=CreateRecordFile();
195   keyboardfile=CreateKeyboardFile();
196 
197   /*********** read options file and checking command line options *************/
198   state=Arguments(argc,argv,optionsfile);
199   if(state){
200     Usage(version,last_revision);
201     exit(-1);
202   }
203 
204   /****** checking file options *********/
205   if(CheckArgs()){
206     fprintf(stderr,"ERROR in arguments, exiting...\n");
207     exit(-1);
208   }
209 
210   PrintArguments("Game arguments:");
211 
212   /* locales*/
213   GetLocales(param.lang);
214 
215   if(GameParametres(GET,GNET,0)){
216     printf("NET: yes\n");
217   }
218   else{
219     printf("NET: no\n");
220   }
221 
222   /***** set game options ******/
223 
224   GameParametres(SET,GULX,param.ul);
225   GameParametres(SET,GCOOPERATIVE,param.cooperative);
226   GameParametres(SET,GCOMPCOOPERATIVE,param.compcooperative);
227   GameParametres(SET,GQUEEN,param.queen);
228   GameParametres(SET,GPIRATES,param.pirates);
229   GameParametres(SET,GENEMYKNOWN,param.enemyknown);
230   GameParametres(SET,GNGALAXIES,param.ngalaxies);
231   GameParametres(SET,GNPLAYERS,param.nplayers);
232   GameParametres(SET,GNPLANETS,param.nplanets);
233 
234 
235   /***** user defined keys ****/
236 
237   printf("Setting default user keys\n");
238   SetDefaultUserKeys();
239   printf("Loading user keys\n");
240   LoadUserKeys(keyboardfile);
241 
242   Clock(0,CL_CLEAR);
243   Clock(0,CL_START);
244 
245   /********** Graphics initialization **********/
246   gtk_init(&argc,&argv);
247 
248   MakeTitle(param,title);
249   GetGeom(param.geom,&width,&height);
250   printf("W: %d H: %d \n",  width,height);
251   drawing_area=InitGraphics(title,optionsfile,
252    			    width,height,param);
253 
254   printf("W: %d H: %d \n", drawing_area->allocation.width,
255 	 drawing_area->allocation.height);
256 
257   SetDefaultKeyValues(1);
258 
259   menuhead=CreateMenu();
260   menuhead->active=TRUE;
261 
262   if(param.fontlist){
263     printf("==============\n");
264     printf("system font list:\n");
265     PrintFontNames(10000);
266     printf("==============\n");
267   }
268 
269   /********** --Graphics initialization *********/
270 
271 
272 
273 #if SOUND
274   /********* sound initialization *********/
275   soundenabled=TRUE;
276   if(InitSound()!=0){
277     fprintf(stderr,"Error initializing sound, sound disabled Error id:%d\n",state);
278     soundenabled=FALSE;
279     param.sound=0;
280     param.music=0;
281     GameParametres(SET,GMUSIC,param.sound);
282     GameParametres(SET,GSOUND,param.music);
283     Play(NULL,-1,0); /* disable sound */
284   }
285 
286   if(soundenabled==TRUE){
287     float master=0;
288     float music=0,sound=0;
289 
290     if(param.soundvol>param.musicvol){
291       master=(float)param.soundvol/100;
292       sound=1.0;
293       music=(float)param.musicvol/param.soundvol;
294     }
295     else{
296       master=(float)param.musicvol/100;
297       music=1.0;
298       sound=(float)param.soundvol/param.musicvol;
299     }
300 
301     SetMasterVolume(master,VOLSET);
302 
303     SetSoundVolume(sound,VOLSET);
304     PlaySound(MUSIC,SLOOP,1);
305     if(param.music){
306       SetMusicVolume(music,VOLSET);
307     }
308     else{
309       Sound(SSTOP,MUSIC);
310       printf("Music is off\n");
311     }
312   }
313 
314   /********* --sound initialization *********/
315 #endif
316 
317 
318   /******** what stuff to draw *********/
319   gdraw.main=FALSE;
320   gdraw.menu=TRUE;
321   gdraw.map=FALSE;
322   gdraw.shiplist=FALSE;
323   gdraw.stats=FALSE;
324   gdraw.order=FALSE;
325   gdraw.info=FALSE;
326   gdraw.crash=FALSE;
327   gdraw.volume=FALSE;
328 
329   /******** --what stuff to draw *********/
330 
331   /***** game log initialization *****/
332 
333   gameloglist.n=0;
334   gameloglist.max=200;
335   gameloglist.first=0;
336   gameloglist.next=NULL;
337 
338   windowgamelog.type=0;
339   windowgamelog.active=0;
340   windowgamelog.x=0;
341   windowgamelog.y=0;
342   windowgamelog.width=0;
343   windowgamelog.height=0;
344   windowgamelog.scrollbar.active=1;
345   windowgamelog.scrollbar.width=15;
346   windowgamelog.scrollbar.pos=0;
347   windowgamelog.scrollbar.n=0;
348   windowgamelog.data=&gameloglist;
349 
350 
351   gtk_timeout_add((int)(DT*50),MenuLoop,(gpointer)drawing_area);  /* 42 DT=0.42 in general.h*/
352 
353   gtk_timeout_add((int)(DT*100),MainLoop,(gpointer)drawing_area);  /* 42 DT=0.42 in general.h*/
354 
355 
356   gettimeofday(&init_time,NULL);
357   gtk_main();
358 
359 
360   /********* game resume **********/
361   {
362     struct Player *player=NULL;
363     if(GameParametres(GET,GNPLAYERS,0)>0){
364 
365       player=GetPlayers();
366       printf("\ntotal points: %d record: %d\n",player[1].points,record);
367     }
368     printf("******************************************************\n");
369     printf("%sversion %s  %s\n",TITLE,version,last_revision);
370     printf("Please, send bugs and suggestions to: mrevenga at users dot sourceforge dot net\n");
371     printf("Homepage:  http://spacezero.sourceforge.net/\n");
372 
373     SaveRecord(recordfile,player,record);
374   }
375   return 0;
376 } /*  --main */
377 
378 
MenuLoop(gpointer data)379 gint MenuLoop(gpointer data){
380   struct MenuHead *actualmenu;
381   GdkRectangle update_rect;
382   GtkWidget *drawing_area=(GtkWidget *) data;
383   int x,y;
384   int width,height;
385   char point[128];
386 
387   int status;
388   static int cont=0;
389   static GdkFont *font,*fontmenu;
390   static int swfont=0;
391   int swexit=0;
392   int swsaveoptions=0;
393 
394   if(gdraw.menu==FALSE)return(TRUE);
395 
396   if(cont==0){
397     SetDefaultKeyValues(1);
398   }
399   cont++;
400 
401   if((cont%20)==0){
402     gdrawmenu=TRUE;
403   }
404 
405   if(!gdrawmenu)return(TRUE);
406   gdrawmenu=FALSE;
407 
408   key_eval();
409 
410   width=GameParametres(GET,GWIDTH,0);
411   height=GameParametres(GET,GHEIGHT,0);
412 
413   if(swfont==0){
414     font=InitFontsMenu("");
415     swfont++;
416   }
417   if(height<400)fontmenu=gfont;
418   else fontmenu=font;
419 
420   /* clear window */
421 
422   gdk_draw_rectangle(pixmap,
423 		     GetColor(BLACK),
424 		     TRUE,
425 		     0,0,
426 		     drawing_area->allocation.width,
427 		     drawing_area->allocation.height);
428 
429   /* printf something */
430 
431   DrawStars(pixmap,nav_mode,0,0);
432 
433   x=width/2;
434   y=height/9;
435   sprintf(point,"SpaceZero");
436   DrawMessageBox(pixmap,font,point,x,y,MBOXDEFAULT);
437 
438 
439   menuhead->active=TRUE;
440   actualmenu=SelectMenu(menuhead);
441   status=UpdateMenu(menuhead,actualmenu);
442 
443   x=width/8;
444   y=(1.0/3)*height;
445 
446   XPrintMenuHead(pixmap,fontmenu,actualmenu,x,y);
447   /* show window */
448 
449   update_rect.x=0;
450   update_rect.y=0;
451   update_rect.width=drawing_area->allocation.width;
452   update_rect.height=drawing_area->allocation.height;
453   gtk_widget_draw(drawing_area,&update_rect); /*  deprecated */
454 
455   switch(status){
456   case 0:
457     break;
458   case ITEM_start:
459     swsaveoptions=1;
460     swexit=1;
461     break;
462   case ITEM_quit:
463     SetGameParametres(param);
464     GameParametres(SET,GQUIT,2);
465     gdraw.menu=FALSE;
466     gdraw.main=TRUE;
467     Keystrokes(RESET,NULL,NULL);
468     SetDefaultKeyValues(1);
469     return(TRUE);
470     break;
471   case ITEM_default:
472     printf("loading default \n");
473     SetDefaultParamValues();
474     SetDefaultUserKeys();
475     break;
476   case ITEM_server:
477     param.server=TRUE;
478     param.client=FALSE;
479     swsaveoptions=1;
480     swexit=1;
481     printf("start server....\n");
482     break;
483   case ITEM_client:
484     param.server=FALSE;
485     param.client=TRUE;
486     swexit=1;
487     printf("start client....\n");
488     break;
489   case MENUESC:
490     break;
491   default:
492     break;
493   }
494 
495   if(param.menu==FALSE)swexit++;
496 
497   if(swexit){
498     char title[64]="";
499     gdraw.menu=FALSE;
500     gdraw.main=TRUE;
501     Keystrokes(RESET,NULL,NULL);
502     printf("saving game param...\n");
503     SetGameParametres(param);
504     MakeTitle(param,title);
505     gtk_window_set_title(GTK_WINDOW(win_main),title);
506     if(swsaveoptions){
507       printf("saving options...\n");
508       SaveParamOptions(optionsfile,&param);
509       SaveUserKeys(keyboardfile);
510     }
511     /* activating sound ??*/
512 
513 
514     if(soundenabled==TRUE){
515       float master=0;
516       float music=0,sound=0;
517 
518       if(param.soundvol>param.musicvol){
519 	master=(float)param.soundvol/100;
520 	sound=1.0;
521 	music=(float)param.musicvol/param.soundvol;
522       }
523       else{
524 	master=(float)param.musicvol/100;
525 	music=1.0;
526 	sound=(float)param.soundvol/param.musicvol;
527       }
528 
529       SetMasterVolume(master,VOLSET);
530       SetSoundVolume(sound,VOLSET);
531       if(param.music){
532 	SetMusicVolume(music,VOLSET);
533       }
534       else{
535 	Sound(SSTOP,MUSIC);
536 	printf("Music is off\n");
537       }
538     }
539 
540     printf("exiting menu...\n");
541   }
542   return(TRUE);
543 }
544 
545 
546 
MainLoop(gpointer data)547 gint MainLoop(gpointer data){
548   /*
549     Main gtk loop. executed 24 times by second.
550 
551   */
552   int i,j;
553   int drawmap=FALSE;
554   static int cont=0;
555   float x0,y0;
556   static int lasttimepirates=2000;
557   static int lasttimeasteroids=0;
558   int timenow;
559   Object *cv0;     /* coordinates center */
560   GtkWidget *drawing_area=(GtkWidget *) data;
561   GdkRectangle update_rect;
562   static int paused=0;
563   static int swpaused=0;
564   int gwidth,gheight;
565   static int ulx,uly;
566   int proc;
567   int swcomm=0; /* TRUE if in time step has communication */
568   int swmess=0; /* show a message */
569   char point[128];
570   char pointmess[128];
571   int loadsw =0;
572   static int sw=0;
573   int nx,ny;
574 
575   double fpst=0;
576   static double fpstt=0;
577   static int fpscont=0;
578   static struct timeval time0,time1;
579 
580   struct Player *plyr;
581   struct Keys *key;
582 
583   static int stat_sw=0;
584   static char shellcad[MAXTEXTLEN]="";
585 
586 
587   if(gdraw.main==FALSE)return(TRUE);
588 
589   gettimeofday(&time0,NULL);
590   timenow=GetTime();
591   Clock(2,CL_CLEAR);
592   Clock(2,CL_START);
593 
594   if(gtime0==0){
595     gtime0=time(NULL);
596   }
597 
598   if(!sw){   /* firsttime */
599     savefile=CreateSaveFile(param.server,param.client);
600 
601     fprintf(stdout,"save file: %s\n",savefile);
602     fprintf(stdout,"record file: %s\n",recordfile);
603     fprintf(stdout,"options file: %s\n",optionsfile);
604 
605     printf("init game vars...\n");
606     InitGameVars(); /* */
607 
608     printf("... init game vars\n");
609     if(GameParametres(GET,GQUIT,0)==2 ){
610       Quit(NULL,NULL);
611     }
612 
613     gfont=InitFonts(param.font);
614     if(gfont==NULL){
615       GameParametres(SET,GPANEL,PANEL_HEIGHT);
616     }
617     else{
618       GameParametres(SET,GPANEL,2*gdk_text_height(gfont,"pL",2));
619     }
620     GameParametres(SET,GHEIGHT,GameParametres(GET,GHEIGHT,0)-GameParametres(GET,GPANEL,0));
621 
622     gwidth=GameParametres(GET,GWIDTH,0);
623     gheight=GameParametres(GET,GHEIGHT,0);
624 
625     GameParametres(GET,GPANEL,0);
626 #ifndef GTK12
627     gtk_window_resize(GTK_WINDOW(win_main),gwidth,gheight+GameParametres(GET,GPANEL,0));
628 #endif
629     GameParametres(SET,GHEIGHT,drawing_area->allocation.height-GameParametres(GET,GPANEL,0));
630     GameParametres(SET,GWIDTH,drawing_area->allocation.width);
631 
632     gdraw.menu=FALSE;
633 
634     /* statistics */
635     InitStatistics();
636 
637     /* snow */
638 
639     CreateSnow(LXFACTOR,LYFACTOR);
640 
641     sw++;
642   }
643 
644   plyr=GetPlayers();
645 
646   /***** fps *****/
647   Clock(0,CL_STOP);
648   fpst=Clock(0,CL_READ);
649   fpstt+=fpst;
650   fpscont++;
651   Clock(0,CL_CLEAR);
652   Clock(0,CL_START);
653   fps=fpscont/fpstt;
654   if(fpscont==20){
655     fpscont=10;
656     fpstt/=2;
657   }
658 
659   /***** --fps *****/
660 
661 
662   ulx=GameParametres(GET,GULX,0);
663   uly=GameParametres(GET,GULY,0);
664 
665   gwidth=GameParametres(GET,GWIDTH,0);
666   gheight=GameParametres(GET,GHEIGHT,0);
667 
668   proc=GetProc();
669 
670   /*****CELLON*****/
671 
672   nx=GameParametres(GET,GULX,0)/2000;
673   ny=GameParametres(GET,GULY,0)/2000;
674   for(i=0;i<nx*ny;i++){
675     cell[i]=0;
676   }
677   UpdateCell(&listheadobjs,cell);
678 
679   /*****--CELLON*****/
680 
681 
682   key_eval();
683 
684   /* Create some lists */
685   {
686     int pmodified=0;
687     static int lasttimeupdate=0;
688 
689     if(lasttimeupdate>60){
690       lasttimeupdate=0;
691       pmodified++;
692     }
693 
694 
695     for(i=0;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
696       if(plyr[i].status==PLAYERMODIFIED){
697 	pmodified++;
698       }
699     }
700 
701     if(listheadplayer.update){
702       DestroyObjList(&listheadplayer);
703       listheadplayer.list=NULL;
704       listheadplayer.n=0;
705       CreatePlayerList(listheadobjs,&listheadplayer,actual_player);
706       listheadplayer.update=0;
707     }
708 
709     if(pmodified){
710 
711       lasttimeupdate=0;
712       /* update createplayerlist only if necesary HERE  9.44% CPU*/
713       /*
714 	the list must be update when a ship is created or destroyed : mandatory
715 	if habitat changes. no mandatory
716 	HERE actualizar al cambiar habitat
717       */
718 
719       for(i=0;i<GameParametres(GET,GNPLANETS,0)+1;i++){
720 	DestroyObjList(&listheadcontainer[i]);
721 	listheadcontainer[i].list=NULL;
722 	listheadcontainer[i].n=0;
723       }
724 
725       for(i=0;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
726 	DestroyObjList(&listheadkplanets[i]);
727 	listheadkplanets[i].list=NULL;
728 	listheadkplanets[i].n=0;
729       }
730       CreateContainerLists(&listheadobjs,listheadcontainer);
731       CreatekplanetsLists(&listheadobjs,listheadkplanets);
732 
733       for(i=0;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
734 	if(plyr[i].status>=PLAYERACTIVE)plyr[i].status=PLAYERACTIVE;
735       }
736     }
737     lasttimeupdate++;
738   }
739   /* --Create some lists */
740 
741 
742   /* messages */
743   swmess=0;
744 
745 
746   /* GAME OVER */
747 
748   if(GameParametres(GET,GPAUSED,0)==FALSE){
749 
750     /*    if(GameOver(&listheadplayer,players,actual_player)){
751 	  gameover=TRUE;
752 	  observeenemies=TRUE;
753 	  }
754     */
755     if(plyr[actual_player].status==PLAYERDEAD) {
756       gameover=TRUE;
757       observeenemies=TRUE;
758     }
759     else{
760       gameover=FALSE;
761       /* observeenemies=FALSE; */
762     }
763   }
764 
765   if(gameover==TRUE){
766     sprintf(pointmess,"GAME OVER");
767     swmess++;
768   }
769 
770   /* game paused */
771   if(GameParametres(GET,GPAUSED,0)==TRUE){
772     sprintf(pointmess,"PAUSED    (press p to continue)");
773     swmess++;
774   }
775 
776   /* game quit */
777   if(GameParametres(GET,GQUIT,0)==1){
778     sprintf(pointmess,"Really QUIT?  ( y/n )");
779     swmess++;
780   }
781 
782   if(swmess){
783     DrawMessageBox(pixmap,gfont,pointmess,gwidth/2,0.3*gheight,MBOXBORDER);
784   }
785 
786   if(GameParametres(GET,GPAUSED,0)==TRUE){
787     int x,y,width,height;
788     int textw,texth;
789 
790     /* update window */
791     if(swmess){
792       if(gfont!=NULL){
793 	textw=gdk_text_width(gfont,pointmess,strlen(pointmess));
794 	texth=gdk_text_height(gfont,pointmess,strlen(pointmess));
795       }
796       else{
797 	texth=12;
798 	textw=12;
799       }
800       width=textw+2*texth+1;
801       height=2*texth;
802 
803       x=gwidth/2-width/2;
804       y=0.3*gheight-height/2;
805       if(x<10)x=10;
806 
807       update_rect.x=x;
808       update_rect.y=y;
809       update_rect.width=width;
810       update_rect.height=height;
811       gtk_widget_draw(drawing_area,&update_rect);
812     }
813     if(swpaused>=NETSTEP){
814       return(TRUE);   /* savepause */
815     }
816     if(GameParametres(GET,GNET,0)==TRUE){
817       sprintf(point,"Game PAUSED");
818       SendTextMessage(point);
819     }
820     swpaused++;
821   }
822   else{
823     swpaused=0;
824   }
825 
826   /****************** if not paused *****************/
827 
828   drawmap=FALSE;
829   if(!(cont%2))drawmap=TRUE;
830 
831   /* ai */
832 
833   for(i=1;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
834     if(plyr[i].control==COMPUTER && proc==plyr[i].proc){
835       ControlCenter(&listheadobjs,&plyr[i]);
836     }
837   }
838 
839   UpdateObjs();                     /* new positions */
840   for(i=1;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
841     if(proc==plyr[i].proc){
842       plyr[i].ttl--;
843       if(plyr[i].ttl<=0)plyr[i].modified=SENDPLAYERMOD;
844     }
845   }
846 
847   for(i=0;i<GameParametres(GET,GNPLANETS,0)+1;i++){
848     Collision(&listheadcontainer[i]);         /* interact among objects */
849   }
850 
851   GetGold();
852 
853   /**** create pirates *****/
854   if(GameParametres(GET,GPIRATES,0)==TRUE){
855     if( (plyr[GameParametres(GET,GNPLAYERS,0)+1].nplanets<5)){
856       if(proc==plyr[GameParametres(GET,GNPLAYERS,0)+1].proc){/*  Send TO ai */
857 	if(lasttimepirates>timenow){
858 	  lasttimepirates=timenow;
859 	}
860 	if(timenow-lasttimepirates>2000){/* 2000 */
861 	  if(((20000.0*rand())/RAND_MAX)<=1){
862     	    char text[MAXTEXTLEN];
863 	    float level=0;
864 	    int np=4;
865 	    level=timenow/30000.0; /* increase every 20 min */
866 	    lasttimepirates=timenow;
867 	    x0=ulx*Random(-1)-ulx/2;
868 	    y0=uly*Random(-1)-uly/2;
869 	    np=4+(int)level;
870 	    np=np>12?12:np;
871 	    CreatePirates(&listheadobjs,np,x0,y0,level);
872 
873 	    snprintf(text,MAXTEXTLEN,"%s: %d %d",
874 		     GetLocale(L_PIRATESATSECTOR),
875 		     (int)(x0/SECTORSIZE),(int)(y0/SECTORSIZE));
876 
877 	    if(!Add2TextMessageList(&listheadtext,text,0,-1,0,100,0)){
878 	      Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
879 	    }
880 	    if(GameParametres(GET,GNET,0)==TRUE){
881 	      SendTextMessage(text);
882 	    }
883 	  }
884 	}
885       }
886     }
887   }
888   /**** --create pirates *****/
889 
890   /**** create asteroids *****/
891   if(proc==plyr[GameParametres(GET,GNPLAYERS,0)+1].proc){/*  Send TO ai */
892 
893     lasttimeasteroids=lasttimeasteroids>timenow?timenow:lasttimeasteroids;
894     if(timenow-lasttimeasteroids>3000){
895       if(((11000.0*rand())/RAND_MAX)<=1){ /* every 10 minutes */
896 	char text[MAXTEXTLEN];
897 	float factor;
898 
899 	factor=(float)GameParametres(GET,GULX,0)/100000.0;
900 	factor*=factor;
901 	factor=2*(factor+1);
902 	lasttimeasteroids=timenow;
903 	for(i=0;i<factor;i++){
904 	  x0=ulx*Random(-1)-ulx/2;
905 	  y0=uly*Random(-1)-uly/2;
906 	  /* Only create asteroids close to a ship */
907 	  if(Distance2NearestShip(&listheadobjs,-1,x0,y0)<MAXASTEROIDDISTANCE2){ /* 20 sectors */
908 	    CreateAsteroids(&listheadobjs,6,x0,y0);
909 
910 	    for(j=1;j<GameParametres(GET,GNPLAYERS,0)+2;j++){
911 
912 	      if(Distance2NearestShipLessThan(&listheadobjs,j,x0,y0,MAXASTEROIDDISTANCE2)){
913 		snprintf(text,MAXTEXTLEN,"%s: %d %d",
914 			 GetLocale(L_ASTEROIDSATSECTOR),
915 			 (int)(x0/SECTORSIZE),(int)(y0/SECTORSIZE));
916 		if(!Add2TextMessageList(&listheadtext,text,0,j,0,100,0)){
917 		  Add2CharListWindow(&gameloglist,text,1,&windowgamelog);
918 		}
919 		if(GameParametres(GET,GNET,0)==TRUE){
920 		  SendTextMessage(text);
921 		}
922 	      }
923 	    }
924 	  }
925 	}
926       }
927     }
928   }
929 
930   /**** --create asteroids *****/
931 
932 
933   if(swpaused==TRUE){
934     printf("PAUSED\n");
935     fflush(NULL);
936   }
937 
938 
939   /*** check for cargo objects ****/
940   /*   CargoCheck(&listheadobjs,cv); */
941   /*** --check for cargo objects ****/
942 
943   /* synchronization with comm threads */
944 
945   swcomm=FALSE;
946   if(GameParametres(GET,GNET,0)==TRUE){
947 
948     if( !(cont%NETSTEP)){
949       CargoCheck(&listheadobjs,cv);
950       CheckModifiedPre(&listheadobjs,proc);
951       Setttl0(&listheadobjs);
952 
953       NetComm();     /* net communication */
954 
955       CheckModifiedPost(&listheadobjs,proc);
956       Setttl(&listheadobjs,-1);
957       swcomm=TRUE;
958     }
959   }
960   else{
961     swcomm=TRUE;
962   }
963 
964   if(swcomm==TRUE){
965     GetPoints(&listheadobjs,proc,plyr);/* points and experience */
966   }
967 
968   if(GameParametres(GET,GKPLANETS,0)==FALSE){
969     UpdateSectors(listheadobjs);
970   }
971 
972   key=GetKeys();
973 
974 
975   if(key->load==TRUE && swcomm==TRUE){
976     key->load=FALSE;
977     key->save=FALSE;
978 
979     DestroyObjList(&listheadplayer);  /* HERE verify with DestroyAllObjs() in execload() */
980     listheadplayer.n=0;
981     listheadplayer.list=NULL;
982 
983     if(ExecLoad(savefile)==0){
984       printf("EXECLOAD() done\n");
985       loadsw=1;
986       plyr=GetPlayers();
987       p_time=timenow;
988       gameover=FALSE;
989       observeenemies=FALSE;
990 
991       CreatePlanetList(listheadobjs,&listheadplanets);
992       /*      Density(); */
993 
994       { /* deleting the message list */
995 	struct TextMessageList *lh;
996 	lh=&listheadtext;
997 	while(lh->next!=NULL){
998 	  lh->next->info.duration=0;
999 	  lh=lh->next;
1000 	}
1001       }
1002       DestroyCharList(&gameloglist);
1003       CheckGame("Checking game after load...",1);
1004       printf("done\n");
1005     }
1006     CreatePlayerList(listheadobjs,&listheadplayer,actual_player);
1007     listheadplayer.update=0;
1008     PrintGameOptions();
1009     /* print teams */
1010     PrintTeams();
1011   }  /* if(key->load==TRUE && swcomm==TRUE){ */
1012 
1013 
1014   if(key->save==TRUE && swcomm==TRUE){ /* savepause */
1015     char text[MAXTEXTLEN];
1016     key->load=FALSE;
1017     key->save=FALSE;
1018 
1019     {  /* cargo lists */
1020       struct ObjList *ls;
1021       int cargomass=0;
1022       ls=listheadobjs.list;
1023       i=0;
1024       while(ls!=NULL){
1025 	if(ls->obj->cargo.n>0){
1026 	  cargomass=ls->obj->cargo.mass;
1027 	  CargoBuild(ls->obj);
1028 	  ls->obj->cargo.mass=cargomass;
1029 	}
1030 	ls=ls->next;
1031       }
1032     }  /* --cargo lists */
1033 
1034     CheckGame("Checking game before save...",1);
1035     printf("done\n");
1036 
1037     if(ExecSave(listheadobjs,savefile)==0){
1038       snprintf(text,MAXTEXTLEN,"%s.",GetLocale(L_GAMESAVED));
1039       if(!Add2TextMessageList(&listheadtext,text,0,-1,0,100,0)){
1040 	Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
1041       }
1042       if(GameParametres(GET,GNET,0)==TRUE){
1043 	SendTextMessage(text);
1044       }
1045     }
1046     else{
1047       fprintf(stderr,"Error in MainLoop(): I can't open %s\n",savefile);
1048     }
1049   }
1050 
1051   if(cv!=NULL){
1052     if(nav_mode==RELATIVE){
1053       r_rel.x=cv->x;
1054       r_rel.y=cv->y;
1055     }
1056     else{
1057       if(cv->x - r_rel.x>gwidth/2)
1058 	r_rel.x+=gwidth;
1059       if(cv->x - r_rel.x <-gwidth/2)
1060 	r_rel.x-=gwidth;
1061 
1062       if(cv->y - r_rel.y>gheight/2)
1063 	r_rel.y+=gheight;
1064       if(cv->y - r_rel.y <-gheight/2)
1065 	r_rel.y-=gheight;
1066     }
1067   }
1068 
1069 
1070   /* Drawing window */
1071 
1072   /*  what to draw */
1073   if(key->esc==TRUE){
1074     key->f5=FALSE;
1075     key->f6=FALSE;
1076     key->f7=FALSE;
1077     gdraw.shiplist=FALSE;
1078     gdraw.gamelog=FALSE;
1079     gdraw.stats=FALSE;
1080   }
1081 
1082   if(key->f5==TRUE){
1083     key->f7=FALSE;
1084     gdraw.shiplist=TRUE;
1085     gdraw.gamelog=FALSE;
1086   }
1087   else{
1088     gdraw.shiplist=FALSE;
1089   }
1090   if(key->f6==TRUE){
1091     gdraw.stats=TRUE;
1092   }
1093   else{
1094     gdraw.stats=FALSE;
1095   }
1096 
1097   if(key->f7==TRUE){
1098     windowgamelog.active=TRUE;
1099     gdraw.gamelog=TRUE;
1100     gdraw.shiplist=FALSE;
1101   }
1102   else{
1103     gdraw.gamelog=FALSE;
1104     windowgamelog.active=FALSE;
1105     windowgamelog.scrollbar.n=0;
1106   }
1107   if(gdraw.shiplist||gdraw.gamelog){
1108     gdraw.info=FALSE;
1109   }
1110   else{
1111     gdraw.info=TRUE;
1112   }
1113 
1114   if(key->mright){
1115     key->order.state=TRUE;
1116     key->g=TRUE;
1117   }
1118 
1119   if(key->ctrl==TRUE && key->w==TRUE){
1120     key->order.state=TRUE;
1121   }
1122 
1123   if(key->order.state==TRUE){
1124     gdraw.order=TRUE;
1125   }
1126   if(key->map.state==TRUE){
1127 
1128     if(!(Shell(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)==2 &&
1129  	 Shell(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)==WRITE)){
1130       gdraw.map=gdraw.map==TRUE?FALSE:TRUE;
1131     }
1132     key->map.state=FALSE;
1133   }
1134   if(cv==NULL)gdraw.map=FALSE;
1135 
1136   /*--  what to draw */
1137 
1138 
1139   /* game window*/
1140   if(paused==0){
1141 
1142     /* clear window */
1143     if(gdraw.map==TRUE){
1144       if(drawmap){
1145 	gdk_draw_rectangle(pixmap,
1146 			   GetColor(BLACK),
1147 			   TRUE,
1148 			   0,0,
1149 			   drawing_area->allocation.width,
1150 			   drawing_area->allocation.height);
1151       }
1152     }
1153     else{
1154       gdk_draw_rectangle(pixmap,
1155 			 GetColor(BLACK),
1156 			 TRUE,
1157 			 0,0,
1158 			 drawing_area->allocation.width,
1159 			 drawing_area->allocation.height);
1160 
1161     }
1162     /* --clear window */
1163 
1164     /* drawing sound volume  */
1165 
1166     if(gdraw.volume==TRUE){
1167       static int contvolume=100;
1168       int x,y;
1169       if(contvolume==0)contvolume=100;
1170       contvolume--;
1171       if(contvolume==0)gdraw.volume=FALSE;
1172       x=gwidth-65;
1173       y=gheight-15;
1174       DrawBarBox(pixmap,GetColor(RED),GetColor(RED),x,y,60,10,SetMasterVolume(0,VOLGET));
1175     }
1176 
1177     if(gdraw.map==TRUE){
1178       if(drawmap){
1179 	DrawMap(pixmap,actual_player,listheadobjs,cv,ulx);
1180       }
1181     }
1182     else{
1183       if(cv!=NULL){
1184 	switch(habitat.type){
1185 	case H_SPACE:
1186 	  DrawStars(pixmap,nav_mode,r_rel.x,r_rel.y);
1187 	  DrawRadar(pixmap,cv,&listheadobjs,gdraw.crash);
1188 	  break;
1189 	case H_PLANET:
1190 	  DrawPlanetSurface(pixmap,habitat.obj->planet,gcolors[plyr[habitat.obj->player].color]);
1191 
1192 	  /* snow */
1193 	  if(cv->in!=NULL){
1194 	    if(cv->in->id==3){
1195 	      UpdateFlakes(cv->in->planet);
1196 	      DrawFlakes(pixmap,GetColor(WHITE),gwidth,gheight);
1197 	    }
1198 	  }
1199 	  break;
1200 	case H_SHIP:
1201 	  /**TODO draw ship ***/
1202 	  DrawSpaceShip(pixmap,cv,&listheadobjs);
1203 	  /*****/
1204 	  break;
1205 	default:
1206 	  /* draw nothing */
1207 	  break;
1208 	}
1209       }
1210 
1211       DrawObjs(pixmap,&listheadobjs,habitat,cv,r_rel);
1212 
1213       if(cv!=NULL){
1214 	if(cv->accel>0){
1215 	  Play(cv,THRUST,1.0*cv->accel/cv->engine.a_max);
1216 	}
1217       }
1218     }
1219 
1220     if(gdraw.crash)gdraw.crash=0;
1221 
1222     if(gdraw.shiplist==TRUE){
1223       DrawPlayerList(pixmap,actual_player,&listheadplayer,cv,loadsw || !(timenow%20));
1224     }
1225 
1226     if(gdraw.gamelog==TRUE){
1227       DrawWindow(pixmap,gfont,GetColor(WHITE),10,10,1,&windowgamelog);
1228     }
1229 
1230     DrawInfo(pixmap,cv,&gdraw,&listheadobjs,&listheadtext);
1231   }/* if(paused==0) */
1232 
1233   if(!(cont%24)){  /* statistics */
1234     UpdateStatistics();
1235     /* PrintStatistics(); */
1236   }
1237 
1238   /**** draw stats ****/
1239   if(gdraw.stats==TRUE){
1240     Rectangle rect;
1241     int x;
1242     stat_sw=1;
1243     rect.x=5;
1244     rect.y=5;
1245     rect.width=200;
1246     rect.height=100;
1247     x=DrawGameStatistics(pixmap,plyr)-5;
1248 
1249     rect.height=100;
1250     rect.width=x-5;
1251     if(rect.width>195)rect.width=195;
1252     if(rect.width<0)rect.width=0;
1253 
1254     Statistics_Draw(pixmap,&rect);
1255 
1256   }
1257   else{
1258     if(stat_sw==1){
1259       if(pixmap){
1260 	gdk_pixmap_unref(pixmap);
1261       }
1262       pixmap=gdk_pixmap_new(d_a->window,
1263 			    d_a->allocation.width,
1264 			    d_a->allocation.height,
1265 			    -1);
1266       stat_sw=0;
1267     }
1268   }
1269   /**** --draw stats ****/
1270 
1271 
1272   if(swmess){
1273     DrawMessageBox(pixmap,gfont,pointmess,gwidth/2,0.3*gheight,MBOXBORDER);
1274   }
1275 
1276 
1277   /* Draw Shell */
1278 
1279   if(gdraw.order==TRUE){/* QWERTY */
1280     gdk_draw_line(pixmap,GetColor(WHITE),
1281 		  0,gheight,
1282 		  gwidth,gheight);
1283 
1284     cv0=cv;     /* coordinates center */
1285     ShellTitle(2,NULL,NULL,NULL,NULL,0,0);
1286     Shell(0,pixmap,GetColor(GREEN),gfont,&listheadobjs,&plyr[actual_player],key,&cv,shellcad);
1287     DrawString(pixmap,gfont,GetColor(GREEN),10,GameParametres(GET,GHEIGHT,0)+GameParametres(GET,GPANEL,0)/2+4,shellcad);
1288     if(key->order.state==FALSE)gdraw.order=FALSE;
1289     if(cv!=NULL){
1290       if(cv->mode==SOLD){
1291 	cv=SelectObjInObj(&listheadplayer,cv->in->id,cv->player);
1292 	if(cv!=NULL){
1293 	  cv->selected=TRUE;
1294 	  if(cv->in==cv0->in){
1295 	    habitat.type=cv->habitat;
1296 	    habitat.obj=cv->in;
1297 	  }
1298 	  else{
1299 	    cv=cv0;
1300 	  }
1301 	}
1302       }
1303 
1304       if(cv0!=cv){ /* if center coordinates changes */
1305 	if(cv!=NULL){
1306 	  habitat.type=cv->habitat;
1307 	  habitat.obj=cv->in;
1308 	  if(cv->type==PLANET){
1309 	    habitat.type=H_PLANET;
1310 	    habitat.obj=cv;
1311 	  }
1312 	}
1313       }
1314     }
1315   }
1316   else{
1317     gdk_draw_line(pixmap,GetColor(RED),
1318 		  0,gheight,
1319 		  gwidth,gheight);
1320   }
1321 
1322   /* --Draw Shell */
1323 
1324 
1325   /*Selection box */
1326   SelectionBox(pixmap,GetColor(GREEN),&cv,0);
1327   /* --Selection box */
1328 
1329   /* show window */
1330 
1331   if(gdraw.map==TRUE){
1332     if(drawmap){
1333       update_rect.x=0;
1334       update_rect.y=0;
1335       update_rect.width=drawing_area->allocation.width;
1336       update_rect.height=drawing_area->allocation.height;
1337     }
1338   }
1339   else{
1340     update_rect.x=0;
1341     update_rect.y=0;
1342     update_rect.width=drawing_area->allocation.width;
1343     update_rect.height=drawing_area->allocation.height;
1344   }
1345 
1346   gtk_widget_draw(drawing_area,&update_rect); /*  deprecated */
1347 
1348   if(GameParametres(GET,GPAUSED,0)==TRUE){
1349     paused=1;
1350   }
1351   else{
1352     paused=0;
1353   }
1354 
1355 
1356   /* --Drawing window */
1357 
1358   if(GameParametres(GET,GPAUSED,0)==FALSE){
1359     IncTime();
1360   }
1361 
1362 
1363   loadsw=0;
1364 
1365   if(GameParametres(GET,GQUIT,0)==2 && swcomm==TRUE){
1366     Quit(NULL,NULL);
1367   }
1368 
1369   if(swcomm){
1370     /*** check for cargo objects ****/
1371     CargoCheck(&listheadobjs,cv);
1372     /*** --check for cargo objects ****/
1373     if(RemoveDeadObjs(&listheadobjs,cv)==NULL){
1374       cv=NULL;
1375     }
1376   }
1377 
1378   if(IsInObjList(&listheadobjs,ship_c)==0){
1379     ship_c=NULL;
1380   }
1381 
1382   if(cv!=NULL){
1383     habitat.type=cv->habitat;
1384     habitat.obj=cv->in;
1385     if(cv->type==PLANET){
1386       habitat.type=H_PLANET;
1387       habitat.obj=cv;
1388     }
1389   }
1390 
1391   /* Check for GAMEOVER */
1392 
1393   for(i=1;i<GameParametres(GET,GNPLAYERS,0)+1;i++){
1394     if(!((cont+i)%30) && plyr[i].status>=PLAYERACTIVE){
1395       if(GameOver(&listheadobjs,plyr,i)){
1396  	plyr[i].status=PLAYERDEAD;
1397  	plyr[i].level=0;
1398       }
1399     }
1400   }
1401 
1402   cont++;
1403   {
1404     static double t=0,tt=0;
1405     static int c=0;
1406     Clock(2,CL_STOP);
1407     t=Clock(2,CL_READ);
1408     tt+=t;
1409     c++;
1410     if(c==20){
1411       tt=0;
1412       c=0;
1413     }
1414   }
1415 
1416   gettimeofday(&time1,NULL);
1417 
1418   return(TRUE);
1419 
1420 } /* MainLoop */
1421 
1422 
1423 
Quit(GtkWidget * widget,gpointer gdata)1424 gint Quit(GtkWidget *widget,gpointer gdata){
1425   /*
1426 
1427    */
1428 
1429 
1430 
1431   sem_close(&sem_barrier);
1432   sem_close(&sem_barrier1);
1433 
1434 #if SOUND
1435   printf("Sound Closed\n");
1436   ExitSound();
1437   printf("Sound Closed\n");
1438 #endif
1439 
1440   DestroyAllObj(&listheadobjs);
1441   listheadobjs.list=NULL;
1442   listheadobjs.n=0;
1443   ship_c=NULL;
1444   cv=NULL;
1445 
1446 
1447   QuitGraphics(widget,gdata);
1448   printf("Graphics Closed\n");
1449   return FALSE;
1450 }
1451 
key_eval(void)1452 void key_eval(void){
1453   /*
1454     version 01 13May11
1455     Evaluate all the key and mouse press
1456 
1457   */
1458   struct ObjList *ls;
1459   Object *obj;
1460   static int swtab=0;
1461   static int swtab0=0;
1462   int proc;
1463   int keyf=-1;
1464   int navcontrol=TRUE; /* FALSE nav mode, TRUE order mode */
1465   int x,y;
1466 
1467   struct Player *plyr;
1468   struct Keys *key;
1469 
1470   plyr=GetPlayers();
1471   key=GetKeys();
1472   if(gdraw.menu==TRUE){
1473     return;
1474   }
1475   proc=GetProc();
1476 
1477   /* QUIT game */
1478 
1479   if(key->ctrl==TRUE && key->q==TRUE){
1480     GameParametres(SET,GQUIT,1);  /*  ask: Really Quit? */
1481   }
1482 
1483   if(GameParametres(GET,GQUIT,0)==1){
1484     if(key->n==TRUE || key->esc==TRUE){
1485       GameParametres(SET,GQUIT,0);
1486       key->ctrl=FALSE;
1487       key->q=FALSE;
1488       key->n=FALSE;
1489       key->esc=FALSE;
1490     }
1491     if(key->y==TRUE){
1492       GameParametres(SET,GQUIT,2);  /* Quit game */
1493       GameParametres(SET,GPAUSED,FALSE);
1494     }
1495     return;
1496   }
1497 
1498   if(key->esc==TRUE){
1499     key->alt=FALSE;
1500     key->ctrl=FALSE;
1501     Shell(0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /* reset shell() */
1502     key->order.state=FALSE; /* aqui01 salir de order mode */
1503   }
1504 
1505 
1506   /* game paused */
1507   if(key->p==TRUE && GameParametres(GET,GPAUSED,0)==TRUE){
1508     GameParametres(SET,GPAUSED,FALSE);
1509     key->ctrl=FALSE;
1510     key->p=FALSE;
1511   }
1512   if(key->ctrl==TRUE && key->p==TRUE && GameParametres(GET,GPAUSED,0)==FALSE){
1513     GameParametres(SET,GPAUSED,TRUE);
1514     key->ctrl=FALSE;
1515     key->p=FALSE;
1516     Shell(0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /* reset shell() */
1517     key->order.state=FALSE; /* aqui01 salir de order mode */
1518     navcontrol=TRUE;
1519   }
1520 
1521   if(GameParametres(GET,GPAUSED,0)==TRUE){
1522     Sound(SPAUSE,MUSIC);
1523   }
1524   else{
1525     Sound(SPLAY,MUSIC);
1526   }
1527 
1528 
1529   /* mouse */
1530   if(key->mleft==TRUE){
1531   }
1532   if(key->mright==TRUE){
1533   }
1534   if(key->mdclick==TRUE){
1535     key->mdclick=FALSE;
1536   }
1537 
1538   if(key->mleft==TRUE){
1539     if(WindowFocus(&windowgamelog)){
1540       MousePos(GET,&x,&y);
1541       ActWindow(&windowgamelog);
1542       key->mleft=FALSE;
1543     }
1544   }
1545 
1546 
1547   /* --mouse */
1548 
1549   /* sound */
1550 
1551   if(key->ctrl==TRUE && (key->plus==TRUE||key->minus==TRUE)){
1552     if(key->plus==TRUE){
1553       SetMasterVolume(0.025,VOLINC);
1554       gdraw.volume=TRUE;
1555     }
1556     if(key->minus==TRUE){
1557       SetMasterVolume(-0.025,VOLINC);
1558       gdraw.volume=TRUE;
1559     }
1560 
1561     GameParametres(SET,GSOUNDVOL,param.soundvol);
1562   }
1563   /* --sound */
1564 
1565 
1566   navcontrol=TRUE;
1567   if(key->order.state==TRUE)navcontrol=FALSE;
1568 
1569   /* in map view don't control the ship*/
1570   if(gdraw.map==TRUE){
1571     key->accel.state=key->turnleft.state=key->turnright.state=key->fire.state=FALSE;
1572     key->automode.state=key->manualmode.state=FALSE;
1573   }
1574 
1575   switch(navcontrol){
1576   case FALSE: /* order mode */
1577     break;
1578   case TRUE: /* Nav mode */
1579     /* f1 f2 f3 f4 */
1580     keyf=-1;
1581     if(key->f1)keyf=0;
1582     if(key->f2)keyf=1;
1583     if(key->f3)keyf=2;
1584     if(key->f4)keyf=3;
1585     key->f1=key->f2=key->f3=key->f4=FALSE;
1586 
1587     if(keyf>=0) {
1588       if(key->ctrl==TRUE){
1589       	key->ctrl=FALSE;
1590 	if(cv!=NULL)
1591 	  fobj[keyf]=cv->id;
1592       }
1593       else{
1594 	if((obj=SelectObj(&listheadobjs,fobj[keyf]))!=NULL){
1595 	  if(cv!=NULL)cv->selected=FALSE;
1596 	  cv=obj;
1597 	  habitat.type=cv->habitat;
1598 	  habitat.obj=cv->in;
1599 	  SelectionBox(NULL,NULL,&cv,2);
1600 	  cv->selected=TRUE;
1601 	}
1602       }
1603     }
1604     /*-- f1 f2 f3 f4 */
1605 
1606     /* observe enemies */
1607 
1608     if(observeenemies==TRUE){
1609       if(key->f9==TRUE || key->f10==TRUE){
1610 	if(cv!=NULL){
1611 	  plyr[actual_player].cv=cv->id;
1612 	}
1613 	else{
1614 	  plyr[actual_player].cv=0;
1615 	}
1616 	if(key->f9==TRUE){
1617 	  key->f9=FALSE;
1618 	  actual_player--;
1619 	  if(actual_player<1){
1620 	    actual_player=GameParametres(GET,GNPLAYERS,0)+1;
1621 	  }
1622 	}
1623 	if(key->f10==TRUE){
1624 	  key->f10=FALSE;
1625 	  actual_player++;
1626 	  if(actual_player>GameParametres(GET,GNPLAYERS,0)+1){
1627 	    actual_player=1;
1628 	  }
1629 	}
1630 
1631 	DestroyObjList(&listheadplayer);
1632 	listheadplayer.n=0;
1633 	listheadplayer.list=NULL;
1634 	CreatePlayerList(listheadobjs,&listheadplayer,actual_player);
1635 	listheadplayer.update=0;
1636 
1637 	cv=SelectObj(&listheadplayer,plyr[actual_player].cv);
1638 	if(cv==NULL){
1639 	  cv=NextCv(&listheadplayer,cv,actual_player);
1640 	}
1641 	if(cv!=NULL){
1642 	  habitat.type=cv->habitat;
1643 	  habitat.obj=cv->in;
1644 	  SelectionBox(NULL,NULL,&cv,2);
1645 	}
1646       }
1647     }   /*-- observe enemies */
1648 
1649     if(ship_c!=NULL){
1650       if(ship_c->type!=SHIP){
1651 	key->trace=FALSE;
1652 	ship_c->trace=FALSE;
1653       }
1654       if(ship_c->subtype!=EXPLORER &&
1655 	 ship_c->subtype!=FIGHTER &&
1656 	 ship_c->subtype!=QUEEN &&
1657 	 ship_c->subtype!=FREIGHTER){
1658 	key->trace=FALSE;
1659 	ship_c->trace=FALSE;
1660       }
1661 
1662       if(key->trace==TRUE){
1663 	if(ship_c->trace==TRUE)
1664 	  ship_c->trace=FALSE;
1665 	else
1666 	  ship_c->trace=TRUE;
1667 	key->trace=FALSE;
1668       }
1669 
1670       if(ship_c->ai == 0 && proc==plyr[ship_c->player].proc){
1671 
1672 	if(key->down==TRUE){
1673 	  ship_c->accel-=.08;
1674 	  if(ship_c->accel<0)ship_c->accel=0;
1675 	}
1676 
1677 	/**** ship movement *****/
1678 
1679 	if(cv==ship_c){
1680 	  if(ship_c->gas>0 && gdraw.map==FALSE){
1681 	    if(cv->type==SHIP && cv->subtype==PILOT){
1682 	      key->accel.state=key->turnleft.state=key->turnright.state=key->fire.state=FALSE;
1683 	    }
1684 	    if(key->accel.state==TRUE){
1685 	      if(ship_c->mode==LANDED && fabs(ship_c->a-PI/2)>.35){
1686 		ship_c->accel=0;
1687 	      }
1688 	      else{
1689 		ship_c->accel+=ship_c->engine.a;
1690 		if(ship_c->accel>ship_c->engine.a_max)ship_c->accel=ship_c->engine.a_max;
1691 	      }
1692 	    }
1693 	    else{
1694 	      ship_c->accel=0;
1695 	    }
1696 	    if(ship_c->mode==LANDED && ship_c->vy>0){ship_c->mode=NAV;}
1697 	    if(key->turnleft.state==TRUE && ship_c->gas > ship_c->engine.gascost){
1698 	      ship_c->ang_a+=ship_c->engine.ang_a;
1699 	      if(ship_c->ang_a > ship_c->engine.ang_a_max)
1700 		ship_c->ang_a=ship_c->engine.ang_a_max;
1701 	    }
1702 	    if(key->turnright.state==TRUE && ship_c->gas>ship_c->engine.gascost){
1703 	      ship_c->ang_a-=ship_c->engine.ang_a;
1704 	      if(ship_c->ang_a < -ship_c->engine.ang_a_max)
1705 		ship_c->ang_a = -ship_c->engine.ang_a_max;
1706 	    }
1707 	    if(key->turnleft.state==FALSE  && key->turnright.state==FALSE){
1708 	      ship_c->ang_a=0;
1709 	    }
1710 	    if(key->fire.state==TRUE && ship_c->gas > 2){
1711 	      if (!ship_c->weapon->cont1){
1712 		ChooseWeapon(ship_c);
1713 		if(proc==plyr[ship_c->player].proc){
1714 		  if(FireCannon(&listheadobjs,ship_c,NULL)==0){
1715 		    Play(ship_c,FIRE0,1);
1716 		  }
1717 		}
1718 	      }
1719 	    }
1720 	  }
1721 	}
1722 	/**** --ship movement *****/
1723       }
1724     }/* if(ship_c!=NULL) */
1725 
1726     if(cv!=NULL){
1727       if(key->ctrl && key->n==TRUE){
1728 	if(nav_mode==RELATIVE){
1729 	  nav_mode=ABSOLUTE;
1730 	  r_rel.x=cv->x;
1731 	  r_rel.y=cv->y;
1732 	}
1733 	else{
1734 	  nav_mode=RELATIVE;
1735 	}
1736 	key->n=FALSE;
1737       }
1738 
1739       if(actual_player==actual_player0){
1740 
1741 	if(key->automode.state==TRUE){
1742 	  /* pressing 'down' the selected ship goes to automatic mode */
1743 	  if(GameParametres(GET,GQUIT,0)==0){
1744 	    if(cv->type==SHIP &&
1745 	       (cv->subtype==FIGHTER ||
1746 		cv->subtype==EXPLORER ||
1747 		cv->subtype==QUEEN ||
1748 		cv->subtype==FREIGHTER ||
1749 		cv->subtype==TOWER)){
1750 	      ship_c=cv;
1751 	      ship_c->ai=1;
1752 	      key->manualmode.state=FALSE;
1753 	      key->automode.state=FALSE;
1754 	    }
1755 	  }
1756 	}
1757 
1758 	if(key->manualmode.state==TRUE && cv->type==SHIP &&
1759 	   /* pressing a movement key the spaceship goes to manual mode */
1760 	   (cv->subtype==FIGHTER || cv->subtype==EXPLORER || cv->subtype==QUEEN || cv->subtype==FREIGHTER || cv->subtype==TOWER)){
1761 	  ship_c=cv;
1762 	  if(ship_c->ai)ship_c->weapon=&ship_c->weapon0;
1763 	  ship_c->ai=0;
1764 
1765 	  key->manualmode.state=FALSE;
1766 	  key->automode.state=FALSE;
1767 	}
1768 
1769 	if(key->number[1]==TRUE){
1770 	  if(cv->weapon0.type!=CANNON0)
1771 	    cv->weapon=&cv->weapon0;
1772 	  key->number[1]=FALSE;
1773 	}
1774 	if(key->number[2]==TRUE){
1775 	  if(cv->weapon1.type!=CANNON0)
1776 	    cv->weapon=&cv->weapon1;
1777 	  key->number[2]=FALSE;
1778 	}
1779 	if(key->number[3]==TRUE){
1780 	  if(cv->weapon1.type!=CANNON0)
1781 	    cv->weapon=&cv->weapon2;
1782 	  key->number[3]=FALSE;
1783 	}
1784       }
1785     }
1786 
1787     break;
1788   default:
1789     break;
1790   }
1791 
1792   if(!(key->Pagedown | key->Pageup | key->home | key->tab)){
1793     swtab=0;
1794     swtab0=0;
1795   }
1796 
1797   if(key->Pagedown|key->Pageup|key->home|key->tab){
1798     Shell(0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /* reset shell() */
1799     key->order.state=FALSE; /* aqui01 salir de order mode */
1800     navcontrol=TRUE;
1801     key->p=FALSE;
1802 
1803     if(key->tab==TRUE){
1804       if(swtab==0){
1805 	if(cv!=NULL)cv->selected=FALSE;
1806 	if(key->ctrl==TRUE){
1807 	  cv=PrevCv(&listheadplayer,cv,actual_player);
1808 	}
1809 	else{
1810 	  cv=NextCv(&listheadplayer,cv,actual_player);
1811 	}
1812       }
1813       swtab++;
1814       if(swtab0)if(swtab>1)swtab=0;
1815       if(swtab>6){swtab=0;swtab0=1;}
1816     }
1817 
1818     if(key->Pagedown|key->Pageup|key->home){
1819       if(swtab==0){
1820 	if(cv!=NULL)cv->selected=FALSE;
1821 	if(key->Pagedown==TRUE){
1822 	  cv=NextPlanetCv(&listheadplayer,cv,actual_player);
1823 	  key->Pagedown=FALSE;
1824 	}
1825 	if(key->Pageup==TRUE){
1826 	  cv=PrevPlanetCv(&listheadplayer,cv,actual_player);
1827 	  key->Pageup=FALSE;
1828 	}
1829 	if(key->home==TRUE){
1830 	  key->home=FALSE;
1831 	  cv=FirstShip(&listheadplayer,cv,actual_player);
1832 	}
1833       }
1834       swtab++;
1835       if(swtab0)if(swtab>1)swtab=0;
1836       if(swtab>6){swtab=0;swtab0=1;}
1837     }
1838 
1839     if(cv!=NULL){
1840       habitat.type=cv->habitat;
1841       habitat.obj=cv->in;
1842       SelectionBox(NULL,NULL,&cv,2);
1843       cv->selected=TRUE;
1844 
1845       if(nav_mode==ABSOLUTE){
1846 	while(cv->x - r_rel.x>GameParametres(GET,GWIDTH,0)/2){
1847 	  r_rel.x+=GameParametres(GET,GWIDTH,0);
1848 	}
1849 	while(cv->x - r_rel.x <-GameParametres(GET,GWIDTH,0)/2){
1850 	  r_rel.x-=GameParametres(GET,GWIDTH,0);
1851 	}
1852 	while(cv->y - r_rel.y>GameParametres(GET,GHEIGHT,0)/2){
1853 	  r_rel.y+=GameParametres(GET,GHEIGHT,0);
1854 	}
1855 	while(cv->y - r_rel.y <-GameParametres(GET,GHEIGHT,0)/2){
1856 	  r_rel.y-=GameParametres(GET,GHEIGHT,0);
1857 	}
1858       }
1859     }
1860   }
1861 
1862   /* save and load game */
1863   if(key->ctrl==TRUE && key->s==TRUE){
1864     if(GameParametres(GET,GMODE,0)==CLIENT){
1865       key->save=FALSE;
1866     }
1867     else{
1868       key->save=TRUE;
1869       key->s=FALSE;
1870     }
1871   }
1872 
1873   if(key->ctrl==TRUE && key->l==TRUE){
1874 
1875     if(GameParametres(GET,GMODE,0)==CLIENT){
1876       key->load=FALSE;
1877     }
1878     else{
1879       key->load=TRUE;
1880       key->l=FALSE;
1881     }
1882   }
1883   /*-- save and load game */
1884 
1885   /* alt modes. Cargo */
1886 
1887   if(gdraw.order==FALSE && key->alt==TRUE){
1888     int n=0;
1889     int subtype=-1;
1890     if(key->s==TRUE){ /* SATELLITE off*/
1891       subtype=SATELLITE;
1892       key->s=FALSE;
1893     }
1894     if(key->p==TRUE){ /* PILOT off*/
1895       subtype=PILOT;
1896       key->p=FALSE;
1897     }
1898 
1899     if(subtype!=-1){
1900 
1901       /*
1902 	take off one object from selected ships
1903       */
1904       ls=listheadobjs.list;
1905       while(ls!=NULL){  /* HERE create a selected list */
1906 	if(ls->obj->selected==TRUE){
1907 	  obj=CargoGet(ls->obj,SHIP,subtype);
1908 	  if(obj!=NULL){
1909 	    n++;
1910 	    obj->habitat=ls->obj->habitat;
1911 	    obj->in=ls->obj->in;
1912 	    obj->mode=NAV;
1913 	    obj->planet=NULL;
1914 	    obj->ai=1;
1915 	    obj->x=ls->obj->x + ls->obj->radio*cos(ls->obj->a-PI);
1916 	    obj->y=ls->obj->y + ls->obj->radio*sin(ls->obj->a-PI);
1917 	    obj->vx=ls->obj->vx - 0.5+Random(-1);
1918 	    obj->vy=ls->obj->vy - 0.5+Random(-1);
1919 
1920 	    if(GameParametres(GET,GNET,0)==TRUE){
1921 	      SetModified(obj,SENDOBJALL);
1922 	      if(obj->modified!=SENDOBJALL){
1923 		printf("OBJ EJECT mod: %d\n",obj->modified);
1924 	      }
1925 	    }
1926 	  }
1927 	}
1928 	ls=ls->next;
1929       }
1930     }
1931   }
1932   /* alt modes. Cargo */
1933 
1934 }
1935 
1936 
1937 
1938 
UpdateShip(Object * obj)1939 void UpdateShip(Object *obj){
1940   /*
1941      Calculate the new coordinates of the ship *obj:
1942      calculate gravity forces
1943      update position and velocity
1944      recharge armor and fuel
1945      repair ship
1946      learning and experience
1947      check collision with planets
1948   */
1949 
1950   float vx,vy,v,vmax2;
1951   float cosa,sina;
1952   float rx,ry;
1953   float vr,vo;
1954   float fx,fy;
1955   float fx0,fy0;
1956   float dtim;
1957   float a,factor;
1958   float g=1.2/250000;
1959   int time;
1960   int n;
1961   int proc;
1962   float b=0.05;   /* air resistance */
1963   float bx,by;
1964   int mass;
1965   struct Player *plyr;
1966   plyr=GetPlayers();
1967 
1968   proc=GetProc();
1969 
1970   mass=obj->mass+obj->cargo.mass;
1971 
1972   if(obj->habitat==H_SHIP){
1973     if(obj->in!=NULL){
1974       obj->x=obj->in->x;
1975       obj->x0=obj->in->x0;
1976       obj->y=obj->in->y;
1977       obj->y0=obj->in->y0;
1978       obj->vx=obj->in->vx;
1979       obj->vy=obj->in->vy;
1980     }
1981     else{
1982       if(GameParametres(GET,GNET,0)==FALSE){
1983 	fprintf(stderr,"ERROR UpdateShip(): habitat=H_SHIP in = NULL id: %d (pid:%d) t:%d st: %d player: %d\n",obj->id,obj->pid, obj->type,obj->subtype,obj->player);
1984 	exit(-1);
1985       }
1986     }
1987     return;
1988   }
1989 
1990   vx=obj->vx;
1991   vy=obj->vy;
1992   dtim=DT/mass;
1993   fx0=fy0=0;
1994   bx=by=0;
1995   /***** Forces 1*****/
1996   switch(obj->habitat){
1997   case H_SPACE:
1998     PlanetAtraction(&fx0,&fy0,obj->x,obj->y,mass);
1999     if(obj->subtype==SATELLITE){
2000       if(fx0>0.0000001){
2001 	obj->life=LIFESATELLITE;
2002       }
2003     }
2004 
2005 
2006     break;
2007   case H_PLANET:
2008     if(obj->mode==LANDED){fy0=0;}
2009     else{  /* air resistance, */
2010       v=sqrt(obj->vx*obj->vx+obj->vy*obj->vy);
2011       b*=(obj->in->mass/120000 + 0.75);     /* density */
2012       bx=-b*v*obj->vx;   /* wind HERE TODO +3; */
2013       by=-b*v*obj->vy;
2014       fy0=-g*mass*(float)obj->in->mass+by;
2015       fx0=bx;
2016     }
2017     break;
2018   case H_SHIP:
2019     fx0=fy0=0;
2020     if(obj->in==NULL){
2021       fprintf(stderr,"ERROR UpdateShip(hship): in = NULL in id: %d (%d) t:%d st: %d\n",obj->id,obj->pid, obj->type,obj->subtype);
2022       return;
2023     }
2024     break;
2025   default:
2026     fprintf(stderr,"ERROR UpdateShip(): Habitat unknown: %d in = NULL in id: %d (%d) t:%d st: %d\n",obj->habitat,obj->id,obj->pid, obj->type,obj->subtype);
2027     exit(-1);
2028     break;
2029   }
2030 
2031   /*** first step ****/
2032 
2033   obj->x0=obj->x;
2034   obj->y0=obj->y;
2035 
2036   if(obj->mode==NAV){
2037     obj->x+=(vx+.5*(fx0)*dtim)*DT;
2038     obj->y+=(vy+.5*(fy0)*dtim)*DT;
2039   }
2040 
2041   /*** forces 2 ****/
2042 
2043   fx=fy=0;
2044   switch(obj->habitat){
2045   case H_SPACE:
2046     PlanetAtraction(&fx,&fy,obj->x,obj->y,mass);
2047     break;
2048   case H_PLANET:
2049     if(obj->mode==LANDED){fy=0;}
2050     else{
2051       fy=-g*mass*(float)obj->in->mass+by;
2052       fx=bx;
2053     }
2054     break;
2055   default:
2056     fx=fy=0;
2057     break;
2058   }
2059 
2060   /***** gas cost *****/
2061   if(proc==plyr[obj->player].proc || (obj->type==PROJECTILE && obj->subtype==MISSILE)){
2062     if(obj->engine.a>0){
2063       if(obj->accel>0){
2064 	obj->gas-=10*obj->engine.gascost*obj->accel/obj->engine.a_max;
2065 	if(obj->gas<0){
2066 	  obj->gas=0;
2067 	  obj->accel=0;
2068 	}
2069       }
2070     }
2071 
2072     if(obj->engine.ang_a_max && obj->ang_a!=0){
2073       obj->gas-=fabs(obj->engine.gascost*obj->ang_a/obj->engine.ang_a_max);
2074       if(obj->gas<0){
2075 	obj->gas=0;
2076 	obj->ang_a=0;
2077       }
2078     }
2079   }
2080 
2081   /***** step 2 *****/
2082   if(obj->accel){
2083     vx+=(.5*(fx+fx0)+cos(obj->a)*obj->accel)*dtim;
2084     vy+=(.5*(fy+fy0)+sin(obj->a)*obj->accel)*dtim;
2085   }
2086   else{
2087     vx+=(.5*(fx+fx0))*dtim;
2088     vy+=(.5*(fy+fy0))*dtim;
2089   }
2090 
2091 
2092   if(obj->mode==LANDED){
2093     if(vy<=0){
2094       vy=0;
2095       vx=0;
2096     }
2097     else{
2098       if(obj->accel>0){
2099 	obj->mode=NAV;
2100       }
2101     }
2102   }
2103 
2104   /***** if max vel is reached, reescaling *****/
2105 
2106   if(obj->type==SHIP){
2107     vmax2=obj->engine.v2_max*(1-0.4375*(obj->state<25)) + (obj->level*50)*(obj->accel>0);
2108     if(obj->subtype==PILOT)vmax2=15*15;
2109   }
2110   else{
2111     if(obj->engine.type>ENGINE0){
2112       vmax2=obj->engine.v2_max;
2113     }
2114     else{
2115       vmax2=(VELMAX2);
2116     }
2117   }
2118 
2119   if(vx*vx+vy*vy>vmax2){
2120     factor=sqrt(vmax2/(vx*vx+vy*vy));
2121     if(factor>1){
2122       fprintf(stderr,"ERROR factor>1\n");
2123       printf("\tobj_enginev2max: %d %d\n",obj->engine.v2_max,(obj->state<25));
2124     }
2125     vx*=factor;
2126     vy*=factor;
2127   }
2128 
2129   /***** angular velocity *****/
2130 
2131   if(obj->ang_a!=0){
2132     obj->ang_v+=obj->ang_a*100.*dtim;
2133     if(obj->ang_v > obj->engine.ang_v_max)obj->ang_v=obj->engine.ang_v_max;
2134     if(obj->ang_v < -obj->engine.ang_v_max)obj->ang_v=-obj->engine.ang_v_max;
2135   }
2136   else{
2137     if(obj->type==SHIP && obj->subtype!=PILOT) /* HERE TODO add artifact to engine*/
2138       obj->ang_v*=0.5;
2139   }
2140 
2141   obj->a+=(obj->ang_v+0.5*obj->ang_a*100.*dtim)*DT;
2142 
2143   if(obj->mode==LANDED){  /* max angle of landed ships */
2144     float maxang=0;
2145     switch(obj->subtype){
2146     case EXPLORER:
2147     case FIGHTER:
2148     case QUEEN:
2149       maxang=PI/4;
2150       break;
2151     case FREIGHTER:
2152     case PILOT:
2153       maxang=0;
2154       break;
2155     default:
2156       maxang=PI/2-PI/40;
2157       break;
2158     }
2159     if(obj->a>PI/2+maxang){obj->a=PI/2+maxang;obj->ang_a=obj->ang_v=0;}
2160     if(obj->a<PI/2-maxang){obj->a=PI/2-maxang;obj->ang_a=obj->ang_v=0;}
2161   }
2162   if(obj->a > PI)obj->a-=2*PI;
2163   if(obj->a < -PI)obj->a+=2*PI;
2164   obj->vx=vx;
2165   obj->vy=vy;
2166   obj->fx0=fx0;
2167   obj->fy0=fy0;
2168   obj->fx=fx;
2169   obj->fy=fy;
2170 
2171   /***** recharging armor and fuel ******/
2172 
2173   if(obj->weapon0.cont1)obj->weapon0.cont1--;
2174   if(obj->weapon1.cont1)obj->weapon1.cont1--;
2175   if(obj->weapon2.cont1)obj->weapon2.cont1--;
2176 
2177   if(proc==plyr[obj->player].proc){
2178     time=GetTime();
2179     /* refuel in space */
2180     if(obj->type==SHIP && obj->subtype!=PILOT && obj->habitat==H_SPACE){
2181       obj->gas+=0.05;
2182       if(obj->gas > obj->gas_max)obj->gas=obj->gas_max;
2183       if(obj->state>0 && obj->state<25){
2184 	obj->state+=0.005;
2185       }
2186     }
2187 
2188     /* ammunition in space */
2189     if(!(time%100)){
2190       if(obj->type==SHIP && obj->subtype==SATELLITE && obj->habitat==H_SPACE){
2191 	if(obj->gas > 0.1*obj->gas_max &&
2192 	   obj->state>25 &&
2193 	   obj->weapon0.n<obj->weapon0.max_n){
2194 	  obj->weapon0.n++;
2195 	}
2196       }
2197     }
2198     /*
2199      * repair, refuel and learning on a planet
2200      */
2201 
2202     if(obj->type==SHIP && obj->mode==LANDED && obj->subtype!=PILOT){ /* HERE TODO add propertie to ships, pilots. */
2203 
2204 
2205       /* Cargo FREIGHTERS */
2206       if(!(time%10)){
2207 	if(obj->subtype==FREIGHTER){
2208 	  if(obj->cargo.mass < obj->cargo.capacity){
2209 	    obj->cargo.mass+=1;
2210 	  }
2211 	}
2212       }
2213       /* --Cargo FREIGHTERS */
2214 
2215       /* repair and refuel  */
2216       if(plyr[obj->player].gold<5){
2217 	n=5*Random(-1); /* HERE depends on number of damaged objects */
2218       }
2219       else{
2220 	n=0;
2221       }
2222 
2223 
2224       /* first repair, then gas and last ammunition */
2225       if(plyr[obj->player].gold>0 && n==0){
2226 	if(obj->state<100){
2227 	  if(obj->state>0){
2228 	    obj->state+=0.05;
2229 	  }
2230 	  if(obj->state>100)obj->state=100;
2231 	  plyr[obj->player].gold-=.125; /* total cost 250  */
2232 	  plyr[obj->player].goldweapon+=.125;
2233 	}
2234 
2235 	if(obj->state>50){
2236 	  if(obj->gas < obj->gas_max){
2237 	    obj->gas+=2;
2238 	    if(obj->gas>obj->gas_max)obj->gas=obj->gas_max;
2239 	    plyr[obj->player].gold-=.2; /* total cost 100 */
2240 	    plyr[obj->player].goldweapon+=.2;
2241 	  }
2242 	  if(obj->gas > 0.5*obj->gas_max){
2243 	    if(!(time%4)){
2244 	      if(obj->weapon0.n<obj->weapon0.max_n){
2245 		if(plyr[obj->player].gold>obj->weapon0.projectile.unitcost){
2246 		  obj->weapon0.n++;
2247 		  plyr[obj->player].gold-=obj->weapon0.projectile.unitcost;
2248 		  plyr[obj->player].goldweapon+=obj->weapon0.projectile.unitcost;
2249 
2250 		}
2251 	      }
2252 	    }
2253 	    if(!(time%240)){
2254 	      if(obj->weapon1.n<obj->weapon1.max_n){
2255 		if(plyr[obj->player].gold>obj->weapon1.projectile.unitcost){
2256 		  plyr[obj->player].gold-=obj->weapon1.projectile.unitcost;
2257 		  plyr[obj->player].goldweapon+=obj->weapon1.projectile.unitcost;
2258 		  obj->weapon1.n++;
2259 		}
2260 	      }
2261 	    }
2262 	    if(!(time%14)){
2263 	      if(obj->weapon2.n<obj->weapon2.max_n){
2264 		if(plyr[obj->player].gold>obj->weapon2.projectile.unitcost){
2265 		  plyr[obj->player].gold-=obj->weapon2.projectile.unitcost;
2266 		  plyr[obj->player].goldweapon+=obj->weapon2.projectile.unitcost;
2267 		  obj->weapon2.n++;
2268 		}
2269 	      }
2270 	    }
2271 	  }
2272 	}
2273       }
2274 
2275       /***** -- repair and refuel *****/
2276 
2277       /***** Learning, experience *****/
2278       if(obj->type==SHIP && obj->state>99 && obj->subtype!=PILOT){ /* HERE TODO pilots has no ship for training. must depend of pilot properties. */
2279 	int mlevel=0;
2280 	float incexp;
2281 
2282 	mlevel=obj->in->level;
2283 	obj->cdata->tmlevel=time;
2284 	obj->cdata->mlevel=mlevel;
2285 	if(obj->cdata->mlevel - obj->level > 2){
2286 	  incexp=0.02*(obj->cdata->mlevel - obj->level);
2287 	  incexp=incexp>0.06?0.06:incexp;
2288 	  Experience(obj,incexp);
2289 	}
2290       }
2291 
2292       /***** --Learning, experience *****/
2293 
2294       if(obj->subtype==FIGHTER && obj->level>=MINLEVELPILOT) {
2295 	obj->items=obj->items|ITSURVIVAL; /* create a survival pod */
2296       }
2297 
2298       /* player level */
2299       if(proc==plyr[obj->player].proc){ /* ship is landed */
2300 	if((obj->level > plyr[obj->player].gmaxlevel)){
2301 	  plyr[obj->player].gmaxlevel=obj->level;
2302 	}
2303       }
2304     }  /*if(obj->mode==LANDED) */
2305 
2306     /*
2307      * -- repair, refuel and learning
2308      */
2309   }
2310 
2311   /***** boundaries at planet *****/
2312   if(obj->habitat==H_PLANET){
2313     if(obj->x<0)obj->x+=LXFACTOR;
2314     if(obj->x>LXFACTOR)obj->x-=LXFACTOR;
2315 
2316     if(obj->y>LYFACTOR){ /* its out of planet */
2317       plyr[obj->player].status=PLAYERMODIFIED;
2318       listheadplayer.update=1;
2319 
2320       if(proc==plyr[obj->player].proc || (obj->type==PROJECTILE && obj->subtype==MISSILE)){
2321 	a=-PI*(2*obj->x/(float)LXFACTOR+0.5);
2322 	cosa=cos(a);
2323 	sina=sin(a);
2324 	obj->x=obj->in->planet->x+2*obj->in->planet->r*cosa;
2325 	obj->y=obj->in->planet->y+2*obj->in->planet->r*sina;
2326 
2327 	vo=-obj->vx;
2328 	vr=obj->vy;
2329 	obj->vx=vr*cosa-vo*sina;
2330 	obj->vy=vr*sina+vo*cosa;
2331 
2332 	rx=obj->x - obj->in->planet->x;
2333 	ry=obj->y - obj->in->planet->y;
2334 
2335 	a=atan2(ry,rx);
2336 
2337 	obj->a=a-PI/2+obj->a;
2338 
2339 	obj->habitat=H_SPACE;
2340 	obj->planet=NULL;
2341 	obj->in=NULL;
2342 	if(GameParametres(GET,GNET,0)==TRUE){
2343 	  SetModified(obj,SENDOBJAALL);  /*on getting out of planet */
2344 	  obj->ttl=0;
2345 	}
2346 	if(obj==cv){
2347 	  habitat.type=H_SPACE;
2348 	  habitat.obj=NULL;
2349 	  SelectionBox(NULL,NULL,&cv,1);
2350 	}
2351       }
2352     }
2353   }
2354   return;
2355 }
2356 
UpdateAsteroid(Object * obj)2357 void UpdateAsteroid(Object *obj){
2358   /*
2359      Calculate the new coordinates of the asteroid *obj
2360      Only gravitational forces.
2361   */
2362 
2363   float vx,vy,vmax2;
2364   float cosa,sina;
2365   float rx,ry;
2366   float vr,vo;
2367   float fx,fy;
2368   float fx0,fy0;
2369   float dtim;
2370   float a,factor;
2371   float g=1.2/250000;
2372   int proc;
2373   struct Player *plyr;
2374   plyr=GetPlayers();
2375 
2376 
2377   if(obj->type!=ASTEROID)return;
2378 
2379   proc=GetProc();
2380 
2381   vx=obj->vx;
2382   vy=obj->vy;
2383   dtim=DT/obj->mass;
2384 
2385   fx0=fy0=0;
2386 
2387   if(obj->habitat!=H_SPACE){
2388     if(obj->mode==NAV){
2389       if(obj->habitat==H_PLANET){
2390 	fy0=-g*obj->mass*(float)obj->in->mass;
2391       }
2392       else{
2393 	printf("in = NULL in id: %d\n",obj->id);
2394 	return;
2395       }
2396     }
2397   }
2398 
2399   obj->x0=obj->x;
2400   obj->y0=obj->y;
2401 
2402   obj->x+=obj->vx*DT+.5*fx0*DT*dtim;
2403   obj->y+=obj->vy*DT+.5*fy0*DT*dtim;
2404 
2405   fx=fy=0;
2406   if(obj->habitat==H_SPACE){
2407     PlanetAtraction(&fx,&fy,obj->x,obj->y,obj->mass);
2408   }
2409   else{
2410     fy=-g*obj->mass*(float)obj->in->mass;
2411   }
2412 
2413   vx+=.5*(fx+fx0)*dtim;
2414   vy+=.5*(fy+fy0)*dtim;
2415 
2416   /* if max vel is reached, reescaling */
2417 
2418   vmax2=(VELMAX*VELMAX/16.0);
2419 
2420   if(vx*vx+vy*vy>vmax2){
2421     factor=sqrt(vmax2/(vx*vx+vy*vy));
2422     if(factor>1){
2423       fprintf(stderr,"ERROR factor>1\n");
2424       printf("\tobj_enginev2max: %d %d\n",obj->engine.v2_max,(obj->state<25));
2425     }
2426     vx*=factor;
2427     vy*=factor;
2428   }
2429 
2430   obj->a+=DT*obj->ang_v;
2431 
2432   if(obj->a > PI)obj->a-=2*PI;
2433   if(obj->a < -PI)obj->a+=2*PI;
2434 
2435   obj->vx=vx;
2436   obj->vy=vy;
2437   obj->fx0=obj->fx;
2438   obj->fy0=obj->fy;
2439 
2440   if(obj->habitat==H_PLANET){
2441 
2442     if(obj->x<0)obj->x+=LXFACTOR;
2443     if(obj->x>LXFACTOR)obj->x-=LXFACTOR;
2444 
2445     if(obj->y > LYFACTOR){ /* its out of planet */
2446       if(proc==plyr[obj->player].proc){
2447 	a=obj->x*(2*PI)/(float)LXFACTOR-PI;
2448 	cosa=cos(a);
2449 	sina=sin(a);
2450 	obj->x=obj->in->planet->x+2*obj->in->planet->r*cosa;
2451 	obj->y=obj->in->planet->y+2*obj->in->planet->r*sina;
2452 
2453 	vo=-obj->vx;
2454 	vr=obj->vy;
2455 	obj->vx=vr*cosa-vo*sina;
2456 	obj->vy=vr*sina+vo*cosa;
2457 
2458 	rx=obj->x - obj->in->planet->x;
2459 	ry=obj->y - obj->in->planet->y;
2460 
2461 	a=atan2(ry,rx);
2462 
2463 	/*      obj->a=obj->a-a+PI/2;  */
2464 	obj->a=a-PI/2+obj->a;
2465 
2466 	obj->habitat=H_SPACE;
2467 	obj->planet=NULL;
2468 	obj->in=NULL;
2469 	if(GameParametres(GET,GNET,0)==TRUE){
2470 	  if(GetProc()==plyr[obj->player].proc){
2471 	    SetModified(obj,SENDOBJAALL);   /*on getting out of planet */
2472 	    obj->ttl=0;
2473 	  }
2474 	}
2475 	if(obj==cv){
2476 	  habitat.type=H_SPACE;
2477 	  habitat.obj=NULL;
2478 	}
2479       }
2480     }
2481   }
2482   return;
2483 }
2484 
2485 
Collision(struct HeadObjList * lh)2486 void Collision(struct HeadObjList *lh){
2487   /*
2488     version 02.(200211) without CollisionList
2489     Calculate the collision between objects
2490   */
2491 
2492   struct ObjList *ls1,*ls2;
2493   Object *obj1,*obj2,*objt1,*objt2;
2494   Object *obj,*pnt,*shot;
2495   Object *nobj;
2496   Segment s;
2497   float radio2,r,r2,rx,ry;
2498   float r02,r0x,r0y;
2499   float damage;
2500   float v;
2501   float a,b;
2502   char text[MAXTEXTLEN];
2503   int i,j;
2504   int gkplanets,gnet,gnplayers;
2505   int proc;
2506   int crashsw=0;
2507   int time=0;
2508   int shocks=0;
2509   int swnextobj1=0;
2510   struct Player *plyr;
2511   plyr=GetPlayers();
2512 
2513   gkplanets=GameParametres(GET,GKPLANETS,0);
2514   gnet=GameParametres(GET,GNET,0);
2515   gnplayers=GameParametres(GET,GNPLAYERS,0);
2516 
2517   proc=GetProc();
2518   time=GetTime();
2519   /* among objs and ship */
2520   ls1=lh->list;
2521 
2522   /* among objs */
2523   while(ls1!=NULL){
2524     swnextobj1=0;
2525     obj1=ls1->obj;
2526     shocks=1; /* can collide with other objects */
2527 
2528     if(obj1->state<=0){
2529       ls1=ls1->next;
2530       continue;
2531     }
2532 
2533     switch(obj1->type){
2534     case SHIP:
2535 
2536       if(gnet==TRUE && obj1->ttl<MINTTL){ls1=ls1->next;continue;}
2537 
2538       if(obj1->habitat==H_SHIP){
2539 	ls1=ls1->next;continue;
2540       }
2541       if(obj1->subtype==PILOT && obj1->mode==LANDED){
2542 	ls1=ls1->next;continue;
2543       }
2544 
2545       break;
2546     case PROJECTILE:
2547       /* explosion only collide with terrain */
2548       if(obj1->subtype==EXPLOSION){
2549 	if(obj1->habitat!=H_PLANET){
2550 	  ls1=ls1->next;continue;
2551 	}
2552 	else{
2553 	  shocks=0;
2554 	}
2555       }
2556       break;
2557     case TRACKPOINT:
2558     case TRACE:
2559       ls1=ls1->next;
2560       continue;
2561       break;
2562     default:
2563       break;
2564     }
2565 
2566     if(shocks){
2567       ls2=ls1->next;
2568 
2569       if(obj1->type==PLANET){
2570 	while(ls2!=NULL && ls2->obj->type==PLANET){
2571 	  ls2=ls2->next;
2572 	}
2573       }
2574 
2575 
2576       /* double loop */
2577       /* collision between two objects */
2578       while(ls2!=NULL){
2579 	/* explosion only collide with terrain */
2580 	if(obj1->type==PROJECTILE && obj1->subtype==EXPLOSION){
2581 	  break;
2582 	}
2583 
2584 	if(obj1->state<=0){
2585 	  ls2=ls2->next;
2586 	  continue;
2587 	}
2588 	if(obj1->habitat!=ls2->obj->habitat){
2589 	  ls2=ls2->next;
2590 	  continue;
2591 	}
2592 
2593 	obj2=ls2->obj;
2594 	switch(obj2->type){
2595 	case SHIP:
2596 	  if(gnet==TRUE){
2597 	    if(obj2->ttl<MINTTL){ls2=ls2->next;continue;}
2598 	  }
2599 
2600 	  if(obj2->habitat==H_SHIP){
2601 	    ls2=ls2->next;continue;
2602 	  }
2603 	  if(obj2->subtype==PILOT && obj2->mode==LANDED){
2604 	    ls2=ls2->next;continue;
2605 	  }
2606 	  break;
2607 	case PROJECTILE:
2608 	  /* explosion only collide with terrain */
2609 	  if(obj2->subtype==EXPLOSION){
2610 	    ls2=ls2->next;continue;
2611 	  }
2612 
2613 	  if(obj1->type==PROJECTILE){
2614 	    /* missiles collides with the others projectiles */
2615 	    if(obj1->subtype!=MISSILE && obj2->subtype!=MISSILE){
2616 	      ls2=ls2->next;continue;
2617 	    }
2618 	  }
2619 	  break;
2620 	case PLANET:
2621 	  if(obj1->type==PLANET){
2622 	    ls2=ls2->next;continue;
2623 	  }
2624 	  break;
2625 	case ASTEROID:
2626 	  if(obj1->type==ASTEROID){
2627 	    ls2=ls2->next;continue;
2628 	  }
2629 	  break;
2630 	case TRACKPOINT:
2631 	case TRACE:
2632 	  ls2=ls2->next;continue;
2633 	  break;
2634 	default:
2635 	  break;
2636 	}
2637 
2638 	/***** same team, two ships or shots *****/
2639 	if(plyr[obj1->player].team==plyr[obj2->player].team){
2640 	  if((obj1->type!=PLANET && obj2->type!=PLANET)){
2641 
2642 
2643 	    /* collision between pilot and other object */
2644 	    if((obj1->type==SHIP && obj1->subtype==PILOT) ||
2645 	       (obj2->type==SHIP && obj2->subtype==PILOT)){
2646 
2647 	      if(obj1->subtype==PILOT && obj2->subtype==PILOT){
2648 		ls2=ls2->next;
2649 		continue;
2650 	      }
2651 
2652 	      /* pilot-projectile don't collide */
2653 	      if(obj1->type==PROJECTILE||obj2->type==PROJECTILE){
2654 		ls2=ls2->next;
2655 		continue;
2656 	      }
2657 
2658 	      /* pilot-satellite don't collide */
2659 	      if(obj1->subtype==SATELLITE||obj2->subtype==SATELLITE){
2660 		ls2=ls2->next;
2661 		continue;
2662 	      }
2663 	    }
2664 	    else{
2665 	      ls2=ls2->next;
2666 	      continue;
2667 	    }
2668 	  }
2669 	}
2670 	/***** --same team, two ships or shots *****/
2671 
2672 	if(obj2->state<=0){
2673 	  ls2=ls2->next;
2674 	  continue;
2675 	}
2676 
2677 	if(obj1->in!=obj2->in){
2678 	  ls2=ls2->next;
2679 	  continue;
2680 	}
2681 
2682 	if(obj1->parent==obj2 || obj2->parent==obj1){
2683 	  ls2=ls2->next;
2684 	  continue;
2685 	}
2686 	if(gnet==TRUE){
2687 	  if(plyr[obj1->player].proc==plyr[obj2->player].proc){
2688 	    if(proc!=plyr[obj1->player].proc){
2689 	      ls2=ls2->next;
2690 	      continue;
2691 	    }
2692 	  }
2693 	}
2694 
2695 	if(plyr[obj1->player].team==plyr[obj2->player].team){
2696 	  if(!(obj1->type==PLANET || obj2->type==PLANET)){
2697 	    if(obj1->subtype!=PILOT && obj2->subtype!=PILOT){
2698 	      ls2=ls2->next;
2699 	      continue;
2700 	    }
2701 	  }
2702 	}
2703 
2704 	radio2=(obj1->radio+obj2->radio)*(obj1->radio+obj2->radio);
2705 
2706 	rx=obj2->x - obj1->x;
2707 	ry=obj2->y - obj1->y;
2708 	r2=rx*rx+ry*ry;
2709 
2710 	r0x=obj2->x0 - obj1->x0;
2711 	r0y=obj2->y0 - obj1->y0;
2712 	r02=0.25*((rx+r0x)*(rx+r0x)+(ry+r0y)*(ry+r0y));
2713 
2714 
2715 	/***** Experience in combat, among SHIPS *****/
2716 	if(r2<1000000){
2717 
2718 	  if(obj1->type==SHIP && obj2->type==SHIP){
2719 	    if(plyr[obj2->player].team!=plyr[obj1->player].team){
2720 	      if(obj1->habitat==obj1->habitat){
2721 		if(obj1->subtype!=PILOT && obj2->subtype!=PILOT){
2722 		  int il;
2723 		  float factor,points;
2724 		  /* obj1 */
2725 		  if(proc==plyr[obj1->player].proc){
2726 		    il=obj2->level-obj1->level;
2727 		    factor=0.001;
2728 		    if(il>3)il=3;
2729 		    if(il==-1)factor/=2;
2730 		    if(il<-1)factor=0;
2731 		    if(factor>0){
2732 		      points=(il+2)*(il+2)*factor*(obj2->level+1);
2733 		      obj1->pexperience+=points;
2734 		    }
2735 		  }
2736 		  /* obj2 */
2737 		  if(proc==plyr[obj2->player].proc){
2738 		    il=obj1->level-obj2->level;
2739 		    if(il>3)il=3;
2740 		    factor=0.001;
2741 		    if(il==-1)factor/=2;
2742 		    if(il<-1)factor=0;
2743 		    if(factor>0){
2744 		      points=(il+2)*(il+2)*factor*(obj1->level+1);
2745 		      obj2->pexperience+=points;
2746 		    }
2747 		  }
2748 		}
2749 	      }
2750 	    }
2751 	  }
2752 	}
2753 	/***** --Experience in combat *****/
2754 
2755 	/***** planets and SHIPS *****/
2756 	if(gkplanets==FALSE){
2757 	  /*	if(r2<RADAR_RANGE2){  planet discovered  */
2758 	  if((obj1->type==PLANET && obj2->type==SHIP) ||
2759 	     (obj2->type==PLANET && obj1->type==SHIP)){
2760 	    if(obj1->type==PLANET){
2761 	      obj=obj2;
2762 	      pnt=obj1;
2763 	    }
2764 	    else{
2765 	      obj=obj1;
2766 	      pnt=obj2;
2767 	    }
2768 	    if(!((time+obj->id)%20)){
2769 	      if(proc==plyr[obj->player].proc && pnt->player!=obj->player){
2770 		if(r2< obj->radar*obj->radar){ /* planet near */
2771 		  if(IsInIntList((plyr[obj->player].kplanets),pnt->id)==0){
2772 		    /* planet discovered */
2773 		    Experience(obj,40);/* Experience for discover a planet */
2774 		    if(gnet==TRUE){
2775 		      struct NetMess mess;
2776 		      mess.id=NMPLANETDISCOVERED;
2777 		      mess.a=obj->id; /*  */
2778 		      mess.b=pnt->id; /*  */
2779 		      NetMess(&mess,NMADD);
2780 		    }
2781 		    for(i=0;i<=gnplayers+1;i++){
2782 		      if(plyr[obj->player].team==plyr[i].team ||
2783 			 (GameParametres(GET,GENEMYKNOWN,0) && plyr[obj->player].team > 1)){
2784 			plyr[i].kplanets=Add2IntList((plyr[i].kplanets),pnt->id);
2785 
2786 			if(plyr[obj->player].team==plyr[i].team ){
2787 			  snprintf(text,MAXTEXTLEN,"(%d) %s %d %s",
2788 				   obj->pid,
2789 				   GetLocale(L_PLANET),
2790 				   pnt->id,
2791 				   GetLocale(L_DISCOVERED));
2792 			  if(!Add2TextMessageList(&listheadtext,text,obj->id,obj->player,0,100,0)){
2793 			    Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
2794 			  }
2795 			}
2796 		      }
2797 		    }
2798 		  }
2799 		}
2800 	      }
2801 	    }
2802 	  }
2803 	}
2804 	/***** --planets and SHIPS *****/
2805 
2806 	if(r2<radio2 || r02<radio2){
2807 	  if(obj1->type==PROJECTILE || obj2->type==PROJECTILE){
2808 	    if(obj1->subtype==LASER || obj2->subtype==LASER){
2809 	      if(obj1->subtype==LASER){
2810 		obj=obj2;
2811 		shot=obj1;
2812 	      }
2813 	      else{
2814 		obj=obj1;
2815 		shot=obj2;
2816 	      }
2817 	      r=(obj->x-shot->x)*sin(shot->a)-(obj->y-shot->y)*cos(shot->a);
2818 	      r2=r*r;
2819 	      if(r2>obj->radio*obj->radio){
2820 		ls2=ls2->next;
2821 		continue;
2822 	      }
2823 	    }
2824 	  }
2825 
2826 	  /*****
2827 		objects and planets
2828 	  *****/
2829 
2830 	  if((obj1->type==PLANET && obj2->type!=PLANET) ||
2831 	     (obj2->type==PLANET && obj1->type!=PLANET)){
2832 
2833 	    /* inner planet */
2834 	    if(obj1->type==PLANET){
2835 	      obj=obj2;
2836 	      pnt=obj1;
2837 	    }
2838 	    else{
2839 	      obj=obj1;
2840 	      pnt=obj2;
2841 	    }
2842 	    plyr[obj->player].status=PLAYERMODIFIED;
2843 	    listheadplayer.update=1;
2844 
2845 	    if(proc==plyr[obj->player].proc || (obj->type==PROJECTILE && obj->subtype==MISSILE)){
2846 
2847 
2848 	      obj->habitat=H_PLANET;
2849 	      obj->planet=NULL;
2850 	      obj->in=pnt;
2851 
2852 	      /*entering planet */
2853 	      if(gnet==TRUE){
2854 		SetModified(obj,SENDOBJAALL);
2855 		obj->ttl=0; /* send now */
2856 	      }
2857 	      if(obj==cv){
2858 		habitat.type=H_PLANET;
2859 		habitat.obj=pnt;
2860 		SelectionBox(NULL,NULL,&cv,1);
2861 	      }
2862 	      /* initial conditions at planet */
2863 	      a=atan2(-pnt->y+obj->y,-pnt->x+obj->x);
2864 	      b=atan2(obj->vy,obj->vx)-a;
2865 	      obj->x=LXFACTOR-(a+PI/2)/(2*PI)*LXFACTOR;
2866 	      obj->y=LYFACTOR;
2867 	      v=sqrt(obj->vx*obj->vx+obj->vy*obj->vy);
2868 
2869 	      obj->vx=-v*sin(b);
2870 	      obj->vy=v*cos(b);
2871 
2872 	      obj->a=obj->a-a+PI/2;
2873 	      if(obj->a > PI)obj->a-=2*PI;
2874 	      if(obj->a < -PI)obj->a+=2*PI;
2875 	      if(obj->actorder.id!=-1)obj->actorder.time=0;
2876 	    }
2877 	  }
2878 
2879 	  /*****
2880 		--objects and planets
2881 	  *****/
2882 
2883 
2884 	  /* among ships and projectiles */
2885 	  if((obj1->type!=PLANET && obj2->type!=PLANET)){
2886 
2887 	    /*****
2888 		   between ship and pilots, same team
2889 		   pilot rescued by an allied ship.
2890 	    ******/
2891 	    if((plyr[obj1->player].team==plyr[obj2->player].team) &&
2892 	       (obj1->type==SHIP && obj2->type==SHIP) &&
2893 	       (obj1->subtype==PILOT || obj2->subtype==PILOT) &&
2894 	       (obj1->subtype!=PILOT || obj2->subtype!=PILOT) &&
2895 	       (obj1->habitat==obj2->habitat)){
2896 
2897 	      if(obj1->subtype==PILOT){
2898 		objt1=obj1;
2899 		objt2=obj2;
2900 	      }
2901 	      else{
2902 		objt1=obj2;
2903 		objt2=obj1;
2904 	      }
2905 
2906 	      /* objt1 is the pilot */
2907 	      if(proc==plyr[objt1->player].proc){
2908 		if(objt2->subtype==EXPLORER||objt2->subtype==FIGHTER||objt2->subtype==QUEEN||objt2->subtype==FREIGHTER){
2909 
2910 		  if(CargoAdd(objt2,objt1)){
2911 		    objt1->in=objt2;
2912 		    objt1->habitat=H_SHIP;
2913 
2914 		    if(objt1->player==actual_player){
2915 		      printf("%s %d %s %d\n",
2916 			     GetLocale(L_PILOT),
2917 			     objt1->pid,
2918 			     GetLocale(L_RESCUEDBY),
2919 			     objt2->pid);
2920 		    }
2921 
2922 		    if(gnet==TRUE){
2923 		      if(proc==plyr[objt1->player].proc){
2924 			SetModified(objt1,SENDOBJALL);
2925 		      }
2926 		    }
2927 		    /* pilot is captured: next obj1 */
2928 		    if(obj1==objt1){swnextobj1=1;break;} /* obj1 don't collide more */
2929 		  }
2930 		  /* next obj2 */
2931 		  break;
2932 		}
2933 	      }
2934 	    }
2935 	    /***** --between ship and pilot same team *****/
2936 
2937 	    for(i=0;i<2;i++){
2938 	      if(i==0){
2939 		objt1=obj1;
2940 		objt2=obj2;
2941 	      }
2942 	      if(i==1){
2943 		objt1=obj2;
2944 		objt2=obj1;
2945 	      }
2946 
2947 	      damage=objt2->damage*(1-objt1->shield);
2948 	      objt1->state-=damage;
2949 
2950 
2951 	      if(objt1->type==SHIP){
2952 		/*receive an impact */
2953 
2954 		Play(objt1,CRASH,1);
2955 		if(objt1==cv){
2956 		  gdraw.crash=1;
2957 		}
2958 
2959 		Explosion(&listheadobjs,cv,objt1,1);
2960 
2961 		if(objt1->state>0){
2962 		  if(proc==plyr[objt1->player].proc){
2963 		    Experience(objt1,damage/2); /* experience for receive an impact*/
2964 		  }
2965 
2966 		  if(objt1->player==actual_player && cv!=objt1){
2967 		    snprintf(text,MAXTEXTLEN,"(%c %d) %s",Type(objt1),objt1->pid,GetLocale(L_HELP));
2968 		    if(!Add2TextMessageList(&listheadtext,text,objt1->id,objt1->player,0,100,2)){
2969 		      Add2CharListWindow(&gameloglist,text,1,&windowgamelog);
2970 		    }
2971 		  }
2972 		}
2973 	      }
2974 	      if(objt1->type==SHIP || objt1->type==ASTEROID || (objt1->type==PROJECTILE && objt1->subtype==MISSILE)){/* HERE */
2975 		if(gnet==TRUE){
2976 		  if(proc==plyr[objt1->player].proc){
2977 		    SetModified(objt1,SENDOBJAALL);
2978 		    objt1->ttl=0;
2979 		  }
2980 		}
2981 	      }
2982 
2983 	      /***** ship destroyed *****/
2984 	      if(objt1->state<=0){
2985 
2986 		switch(objt1->type){
2987 		case SHIP:
2988 		  break;
2989 
2990 		case ASTEROID:
2991 		  if(objt1->subtype<ASTEROID3){
2992 		    if(proc==plyr[objt1->player].proc){
2993 		      for(j=0;j<3;j++){
2994 			nobj=NewObj(ASTEROID,objt1->subtype+1,
2995 				    objt1->x,objt1->y,objt1->vx+10.0*rand()/RAND_MAX-5,objt1->vy+10.0*rand()/RAND_MAX-5,
2996 				    CANNON0,ENGINE0,0,NULL,objt1->in);
2997 			nobj->a=PI/2;
2998 			nobj->ai=0;
2999 			nobj->in=objt1->in;
3000 			nobj->habitat=objt1->habitat;
3001 			nobj->mode=NAV;
3002 			Add2ObjList(&listheadobjs,nobj);
3003 		      }
3004 		    }
3005 		  }
3006 		  break;
3007 		default:
3008 		  break;
3009 		}
3010 
3011 		switch(objt2->type){
3012 		case SHIP:
3013 		  if(objt2->subtype!=PILOT){
3014 		    objt1->sw=objt2->id;
3015 		  }
3016 		  break;
3017 		case PROJECTILE:
3018 		  if(objt2->parent!=NULL){
3019 		    objt1->sw=objt2->parent->id;
3020 		  }
3021 		  break;
3022 		default:
3023 		  break;
3024 		}
3025 
3026 		if(gnet==TRUE){
3027 		  if(proc==plyr[objt1->player].proc){
3028 		    SetModified(objt1,SENDOBJKILL);
3029 		    objt1->ttl=0;
3030 		  }
3031 		}
3032 	      }
3033 	      /***** --ship destroyed *****/
3034 
3035 	    } /* for(i=0;i<2;i++){ */
3036 	  }
3037 	  /* --among ships and projectiles */
3038 	}     /*  if(r2<radio2 || r02<radio2){ */
3039 	else{
3040 	  if(r2<4*radio2 && 0){
3041 	    /* Avoid collision */ /* TODO */
3042 	  }
3043 	}
3044 
3045 	ls2=ls2->next;
3046       } /* while ls2!=NULL */ /* --double loop*/
3047       if(swnextobj1){swnextobj1=0;ls1=ls1->next;continue;}
3048     } /* if(shocks) */
3049 
3050     /*****
3051 	  collision with planet terrain
3052     *****/
3053     crashsw=0;
3054     if(obj1->mode!=LANDED && obj1->habitat==H_PLANET && obj1->y<LYFACTOR/2){
3055       if(proc==plyr[obj1->player].proc || obj1->type==PROJECTILE){
3056 	if(!GetSegment(&s,obj1->in->planet,obj1->x,obj1->y)){
3057 	  /* if(obj1->y - obj1->radio +1< s.y0 && obj1->y - obj1->radio +1< s.y1){ */
3058 	  if(obj1->y-obj1->radio <= s.y0 && obj1->y - obj1->radio <= s.y1){
3059 	    if(obj1->type!=SHIP){ /* destroy object */
3060 	      obj1->state=0;
3061 	      obj1->sw=0;
3062 
3063 	      if(gnet==TRUE){
3064 		if(proc==plyr[obj1->player].proc){
3065 		  SetModified(obj1,SENDOBJKILL);
3066 		  obj1->ttl=0;
3067 		}
3068 	      }
3069 	    }
3070 
3071 	    if(obj1->type==SHIP){
3072 	      switch(s.type){
3073 	      case TERRAIN:  /* destroy ship */
3074 		crashsw=1;
3075 		break;
3076 	      case LANDZONE:
3077 		if(obj1->subtype==SATELLITE){
3078 		  crashsw=1;
3079 		}
3080 		if( (fabs(obj1->vx)>2 || /* ship crashed */
3081 		     fabs(obj1->vy)>5 ||
3082 		     fabs(obj1->a-PI/2)>.35)){
3083 		  crashsw=1;
3084 		}
3085 		if(crashsw==0){/***** ship has landed *****/
3086 		  if(obj1->vy<0){
3087 		    obj1->mode=LANDED;
3088 		    if(obj1->cargo.hlist!=NULL){ /* if has a rescued pilot, eject him */
3089 		      if(CargoEjectObjs(obj1,SHIP,PILOT)){
3090 			listheadplayer.update=1;
3091 		      }
3092 		    }
3093 		    /* FREIGHTER Cargo Goods*/
3094 		    if(obj1->subtype==FREIGHTER &&
3095 		       obj1->oriid!=obj1->in->id){
3096 		      int mass=0;
3097 		      float d,factor;
3098 		      Object *objori,*objdest;
3099 
3100 		      mass=CargoGetMass(obj1); /* mass of objects */
3101 
3102 		      /* Adding gold to planet */
3103 
3104 		      obj1->destid=obj1->in->id;
3105 		      objori=SelectObj(&listheadobjs,obj1->oriid);
3106 		      objdest=SelectObj(&listheadobjs,obj1->destid);
3107 		      if(objori==NULL||objdest==NULL){
3108 			d=5000;
3109 		      }
3110 		      else{
3111 			d=sqrt((objori->x-objdest->x)*(objori->x-objdest->x)+
3112 			       (objori->y-objdest->y)*(objori->y-objdest->y));
3113 		      }
3114 
3115 		      if(d>GameParametres(GET,GULX,0)/10){
3116 			factor=4*d/20000;
3117 			Experience(obj1,40);  /* Experience for complete a travel */
3118 		      }
3119 		      else{
3120 			factor=2*d/20000;
3121 			Experience(obj1,20);  /* Experience for complete a travel */
3122 		      }
3123 		      obj1->ntravels++;
3124 		      obj1->in->planet->gold+=(obj1->cargo.mass-mass)*factor;
3125 		      obj1->cargo.mass=mass;
3126 		      obj1->destid=obj1->oriid; /* change dest  */
3127 		      obj1->oriid=obj1->in->id;
3128 
3129 		    }
3130 		    /* --FREIGHTER Cargo Goods*/
3131 
3132 		    if(gnet==TRUE){
3133 		      if(proc==plyr[obj1->player].proc){
3134 			SetModified(obj1,SENDOBJAALL);
3135 			obj1->ttl=0;
3136 		      }
3137 		    }
3138 		    obj1->vx=0;
3139 		    obj1->vy=0;
3140 		    obj1->ang_a=0;
3141 		    obj1->ang_v=0;
3142 		    obj1->y=obj1->y0=s.y0+obj1->radio;
3143 		    if(obj1->subtype==PILOT){
3144 		      obj1->a=0;
3145 		    }
3146 		  }
3147 
3148 		  /***** conquering a planet *****/
3149 		  switch(IsPlanetEmpty(obj1->in,obj1)){
3150 		  case 0:/* planet totally empty */
3151 		    if(plyr[obj1->in->player].team!=plyr[obj1->player].team){
3152 		      char text[MAXTEXTLEN];
3153 		      Experience(obj1,50);  /* Experience for conquest a planet */
3154 		      if(plyr[obj1->in->player].team != 1){/* HERE ??? */
3155 			GetInformation(&plyr[obj1->player],&plyr[obj1->in->player],obj1);
3156 		      }
3157 		      snprintf(text,MAXTEXTLEN,"%s %d %s",
3158 			       GetLocale(L_PLANET),
3159 			       obj1->in->id,
3160 			       GetLocale(L_LOST));
3161 		      if(!Add2TextMessageList(&listheadtext,text,obj1->in->id,obj1->in->player,0,100,2)){
3162 			Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
3163 		      }
3164 		      if(gnet==TRUE && proc!=plyr[obj1->in->player].proc){
3165 			struct NetMess mess;
3166 			mess.id=NMPLANETLOST;
3167 			mess.a=obj1->in->player; /* player that conquer */
3168 			mess.b=obj1->in->id;     /* id of the planet */
3169 			NetMess(&mess,NMADD);
3170 		      }
3171 		    }
3172 
3173 		    obj1->in->player=obj1->player;
3174 		    obj1->in->sw=1;
3175 
3176 		    if(gnet==TRUE){
3177 		      if(proc==plyr[obj1->in->player].proc){
3178 			SetModified(obj1->in,SENDOBJPLANET);
3179 			obj1->in->ttl=0;
3180 			plyr[obj1->player].modified=SENDPLAYERMOD;
3181 			obj1->ttl=0;
3182 		      }
3183 		    }
3184 		    break;
3185 
3186 		  case 1: /* only allies landed */
3187 		    break;
3188 		  case 2: /* enemies landed */
3189 		    break;
3190 		  default:
3191 		    break;
3192 		  }
3193 		} /*****if(crashsw==0) --else ship has landed *****/
3194 		break;
3195 	      default:
3196 		break;
3197 	      }
3198 	    } /* if SHIP*/
3199 	  } /* if(obj1->y - obj1->radio < s.y0 && obj1->y - obj1->radio < s.y1){ */
3200 	} /* if GetSegment()*/
3201       }  /* if(proc==plyr[obj1->player].proc || obj1->type==PROJECTILE){ */
3202 
3203       if(crashsw){
3204 	obj1->state=0;
3205 	obj1->sw=0;
3206 
3207 	if(gnet==TRUE){
3208 	  if(proc==plyr[obj1->player].proc){
3209 	    SetModified(obj1,SENDOBJKILL);
3210 	    obj1->ttl=0;
3211 	  }
3212 	}
3213       }
3214 
3215     } /*      if(obj1->mode!=LANDED && obj1->habitat==H_PLANET ) */
3216 
3217     /* --collision with planet terrain */
3218 
3219     ls1=ls1->next;
3220   } /* while(ls1!=NULL) */
3221 
3222   return;
3223 }  /* --Collission() */
3224 
3225 
3226 
UpdateObjs(void)3227 int UpdateObjs(void){
3228   /*
3229     Update the coordinates of the objects.
3230   */
3231   static int cont=0;
3232   int i;
3233   int n=0;
3234   struct ObjList *ls;
3235   Object *obj,*nobj;
3236   int gnet;
3237   int proc;
3238   struct Player *plyr;
3239   plyr=GetPlayers();
3240 
3241 
3242 #if CLOSEDUNIVERSE
3243   int gulx,guly;
3244   gulx=GameParametres(GET,GULX,0);
3245   guly=GameParametres(GET,GULY,0);
3246 #endif
3247 
3248   gnet=GameParametres(GET,GNET,0);
3249   proc=GetProc();
3250   cont++;
3251 
3252   if(cont>1000)cont=0;
3253 
3254   ls=listheadobjs.list;
3255 
3256   if(listheadobjs.n==0)return(0);
3257 
3258   /* update planets */
3259   while(ls!=NULL){
3260     obj=ls->obj;
3261     if(obj->type==PLANET){
3262 
3263       /* planets create some gold */
3264       obj->planet->A=obj->planet->reggold;
3265       if(!(cont%50))obj->level=0; /* reset level */
3266     }
3267     ls=ls->next;
3268   }
3269 
3270   /* --update planets */
3271 
3272   /* update players*/
3273   for(i=0;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
3274     plyr[i].maxlevel=0;
3275   }
3276   /* --update players */
3277 
3278   ls=listheadobjs.list;
3279   while(ls!=NULL){
3280     obj=ls->obj;
3281     obj->pexperience=0;
3282 
3283     if(obj->durable==TRUE){
3284       switch(obj->subtype){
3285       case PILOT:
3286 	if(obj->habitat==H_SPACE){
3287 	  obj->life--;
3288 	}
3289 	else{
3290 	  obj->life=LIFEPILOT;
3291 	}
3292 	break;
3293       case SATELLITE:
3294 	if(obj->habitat==H_SPACE){
3295 	  obj->life--;
3296 	}
3297 	break;
3298       default:
3299 	obj->life--;
3300 	break;
3301       }
3302       if(obj->life<=0){
3303 	obj->life=0;
3304 	obj->state=0;
3305 	obj->sw=0;
3306       }
3307     }
3308 
3309     if(obj->life>0){/* && proc==players[obj->player].proc){ */
3310 
3311       switch(obj->type){
3312       case PROJECTILE:
3313 	switch(obj->subtype){
3314 	case MISSILE:
3315 	  aimissile(&listheadobjs,obj);
3316 	  UpdateShip(obj);
3317 	  break;
3318 	case EXPLOSION:
3319 	  UpdateShip(obj);
3320 	  break;
3321 	default:
3322 	  obj->x0 = obj->x;
3323 	  obj->y0 = obj->y;
3324 
3325 	  obj->x += obj->vx*DT;
3326 	  obj->y += obj->vy*DT;
3327 	  break;
3328 	}
3329 	break;
3330       case SHIP:
3331 	if(obj->trace==TRUE && obj->mode!=LANDED){
3332 	  if(obj->vx*obj->vx+obj->vy*obj->vy>.25){
3333 	    Object *objin=obj->in;
3334 
3335 	    if(objin!=NULL){ /* don't create trace inside a ship */
3336 	      if(obj->in->type!=PLANET){
3337 		objin=NULL;
3338 	      }
3339 	    }
3340 	    nobj=NewObj(TRACE,SHIP0,
3341 			obj->x,obj->y,
3342 			0,0,
3343 			CANNON0,ENGINE0,obj->player,obj,objin);
3344 	    Add2ObjList(&listheadobjs,nobj);
3345 	  }
3346 	}
3347 
3348 	switch(obj->subtype){
3349 	case EXPLORER:
3350 	case FIGHTER:
3351 	case QUEEN:
3352 	case FREIGHTER:
3353 	case TOWER:
3354 	  /* level of a planet is the maxlevel of an object in it */
3355 	  if(obj->habitat==H_PLANET){
3356 	    if(plyr[obj->player].team == plyr[obj->in->player].team){
3357 	      if(obj->level > obj->in->level)obj->in->level=obj->level;
3358 	    }
3359 	  }
3360 	  if(obj->level > plyr[obj->player].maxlevel){
3361 	    plyr[obj->player].maxlevel = obj->level;
3362 	    if(plyr[obj->player].maxlevel > plyr[obj->player].gmaxlevel){
3363 	      plyr[obj->player].maxlevel = plyr[obj->player].gmaxlevel;
3364 	    }
3365 	  }
3366 	case SATELLITE:
3367 	case PILOT:
3368 	  if(proc==plyr[obj->player].proc){
3369 	    ai(&listheadobjs,obj,actual_player);
3370 	  }
3371 	  UpdateShip(obj);
3372 
3373 	  break;
3374 	default:
3375 	  g_print("ERROR (UpdateObjs 1) %d %d \n",obj->type,obj->subtype);
3376 	  exit(-1);
3377 	  break;
3378 	}
3379 	break;
3380       case ASTEROID:
3381 	UpdateAsteroid(obj);
3382 	break;
3383 
3384       case TRACKPOINT:
3385       case TRACE:
3386 	break;
3387       case PLANET:
3388 	break;
3389 
3390       default:
3391 	g_print("ERROR (UpdateObjs 2) %d\n",obj->type);
3392 	exit(-1);
3393 	break;
3394 
3395       }
3396 #if CLOSEDUNIVERSE
3397       if(obj->x>gulx)obj->x-=gulx;
3398       if(obj->x<0)obj->x+=gulx;
3399       if(obj->y>guly)obj->y-=guly;
3400       if(obj->y<0)obj->y+=guly;
3401 #endif
3402     } /* if (obj->life>0) */
3403 
3404     if(obj->life<=0){
3405       obj->state=0;obj->sw=0;
3406     }
3407 
3408     if(gnet==TRUE){
3409       obj->ttl--;
3410       if(obj->life<=0){
3411 	if(proc==plyr[obj->player].proc){
3412 	  SetModified(obj,SENDOBJKILL);
3413 	  obj->ttl=0;
3414 	}
3415       }
3416     }
3417     ls=ls->next;
3418     n++;
3419     if (n>listheadobjs.n){
3420       g_print("ERROR: n: %d  N: %d\n",n,listheadobjs.n);
3421       return(-1);
3422     }
3423   } /* while(ls!=NULL) */
3424   return (n);
3425 }
3426 
3427 
CheckPlanetDistance(struct HeadObjList * lh,float x,float y,int d)3428 int CheckPlanetDistance(struct HeadObjList *lh,float x,float y,int d){
3429   /*
3430     The distance between two planets must be greater than 600
3431     returns:
3432     1 if there are a near planet
3433     0 if not
3434   */
3435 
3436   struct ObjList *ls;
3437   float d2=d*d;
3438 
3439   ls=lh->list;
3440   while(ls!=NULL){
3441     if(ls->obj->type==PLANET){
3442       if((ls->obj->x-x)*(ls->obj->x-x)+(ls->obj->y-y)*(ls->obj->y-y)<d2){
3443 	return(1);
3444       }
3445     }
3446     ls=ls->next;
3447   }
3448   return(0);
3449 }
3450 
CreateUniverse(int ulx,int uly,struct HeadObjList * lheadobjs,char ** ptnames)3451 void CreateUniverse(int ulx,int uly,struct HeadObjList *lheadobjs,char **ptnames){
3452   /*
3453     Create Galaxies and planets.
3454   */
3455 
3456   int i,j;
3457   float x,y;
3458   float x0,y0;
3459   float r,rg,ru; /* radio galaxy and universe */
3460   float d2,d2min,d2limit;
3461   Object *obj;
3462   int n,np=0;
3463   int nplanetspergalaxy=1;
3464   int nplanets;
3465   int ngalaxies=1;
3466   int valid;
3467   Point *gpos;
3468   char *datadir;
3469   char frectable[128];
3470   FILE *fp;
3471   int namegen=FALSE;
3472 
3473   /* HERE check this equation. galaxy size */
3474 
3475 
3476   datadir=DATADIR;
3477   snprintf(frectable,128,"%s/%s",datadir,LETTERFREQUENCYFILE);
3478   printf("Checking for letter frequency file: %s\n",frectable);
3479 
3480   namegen=TRUE;
3481   if((fp=fopen(frectable,"rt"))==NULL){
3482     fprintf(stdout,"Can't open the file: %s\n", frectable);
3483 
3484     datadir=INSTALL_DATA_DIR;
3485     snprintf(frectable,128,"%s/%s",datadir,LETTERFREQUENCYFILE);
3486     printf("checking for letter frequency file 2 :%s\n",frectable);
3487 
3488     if((fp=fopen(frectable,"rt"))==NULL){
3489       fprintf(stdout,"Can't open the file: %s\n", frectable);
3490       namegen=FALSE;
3491     }
3492   }
3493 
3494   if(namegen){
3495     loadFrequencyTable(frectable);
3496     printf("letter frequency table loaded\n");
3497     fclose(fp);
3498   }
3499 
3500   ngalaxies=GameParametres(GET,GNGALAXIES,0);
3501   nplanets=GameParametres(GET,GNPLANETS,0);
3502   nplanetspergalaxy=(int)((float)nplanets/ngalaxies+0.5);
3503   ru=ulx/2;
3504   uly=ulx; /* universe is square */
3505 
3506   gpos=malloc(ngalaxies*sizeof(Point));
3507   if(gpos==NULL){
3508     fprintf(stderr,"ERROR in malloc CreateUniverse()\n");
3509     exit(-1);
3510   }
3511 
3512   for(i=0;i<ngalaxies;i++){
3513     gpos[i].x=0;
3514     gpos[i].y=0;
3515   }
3516 
3517   if(ngalaxies==1){
3518     rg=ulx/3;
3519   }
3520   else{
3521     rg=ulx/(sqrt(ngalaxies*16));
3522 
3523   }
3524 
3525   printf("\n\tnumber of galaxies: %d\n",ngalaxies);
3526   printf("\tnumber of planets per galaxy: %d\n",nplanetspergalaxy);
3527   printf("\tgalaxy radius: %.0f\n",rg);
3528 
3529   /* galaxy center coordinates */
3530 
3531   x0=2*(ru-rg)*Random(-1)-(ru-rg);
3532   y0=2*(ru-rg)*Random(-1)-(ru-rg);
3533   gpos[0].x=x0;
3534   gpos[0].y=y0;
3535   d2limit=9*(float)rg*rg;
3536   for(j=1;j<ngalaxies;j++){
3537     n=0;
3538     do{
3539       x0=2*(ru-rg)*Random(-1)-(ru-rg);
3540       y0=2*(ru-rg)*Random(-1)-(ru-rg);
3541       d2min=(float)ulx*ulx;
3542       n++;
3543       for(i=0;i<j;i++){
3544 	d2=(x0-gpos[i].x)*(x0-gpos[i].x)+(y0-gpos[i].y)*(y0-gpos[i].y);
3545 	if(d2<d2min)d2min=d2;
3546       }
3547       if(n>100){
3548 	n=0;
3549 	d2limit*=.8; /* relax condition */
3550       }
3551     }
3552     while(d2min<d2limit);
3553     gpos[j].x=x0;
3554     gpos[j].y=y0;
3555   }
3556 
3557   for(j=0;j<ngalaxies;j++){
3558     if(np>=nplanets)break;
3559     x0=gpos[j].x;
3560     y0=gpos[j].y;
3561     if(ngalaxies==1){
3562       x0=0;
3563       y0=0;
3564     }
3565     for(i=0;i<nplanetspergalaxy;i++){
3566       if(np>=nplanets)break;
3567       n=0;
3568       do{
3569 	valid=1;
3570 	x=x0+6*rg*(float)rand()/RAND_MAX-3*rg;
3571 	y=y0+6*rg*(float)rand()/RAND_MAX-3*rg;
3572 	if(n>100){
3573 	  fprintf(stderr,"ERROR: Universe size too small or too much planets. Exiting...\n");
3574 	  exit(-1);
3575 	}
3576 
3577 	if(CheckPlanetDistance(lheadobjs,x,y,600)){
3578 	  valid=0;
3579 	  n++;
3580 	}
3581 	/* planet distribution */
3582 	d2=(x-x0)*(x-x0)+(y-y0)*(y-y0);
3583 	r=(float)rand()/RAND_MAX;
3584 	if(r>5*exp(-d2/(1.44*rg*rg/2.)))valid=0;
3585 
3586 	if(x<-ulx/2||x>ulx/2||y<-uly/2||y>uly/2){
3587 	  valid=0;
3588 	}
3589       }
3590       while(valid==0);
3591 
3592       obj=NewObj(PLANET,SHIP0,x,y,0,0,CANNON0,ENGINE0,0,NULL,NULL);
3593       if(obj!=NULL){
3594 
3595 	if(i<NUMPLANETNAMES-1 && j==0){
3596 	  strncpy(obj->name,ptnames[i+1],OBJNAMESMAXLEN);
3597 	}
3598 	else{
3599 	  if(namegen){
3600 	    strncpy(obj->name,getRandomName(0),OBJNAMESMAXLEN);
3601 	  }
3602 	  else{
3603 	    strncpy(obj->name,ptnames[0],OBJNAMESMAXLEN);
3604 	  }
3605 	}
3606 	Add2ObjList(lheadobjs,obj);
3607 	np++;
3608       }
3609     }
3610   }
3611 
3612 
3613 
3614   if(np<nplanets){
3615     int m=nplanets-np;
3616     for(i=0;i<m;i++){
3617       x=ulx*Random(-1)-ulx/2;
3618       y=uly*Random(-1)-uly/2;
3619 
3620       obj=NewObj(PLANET,SHIP0,x,y,0,0,CANNON0,ENGINE0,0,NULL,NULL);
3621       if(obj!=NULL){
3622 	if(i<NUMPLANETNAMES-1 && j==0){
3623 	  strncpy(obj->name,ptnames[i+1],OBJNAMESMAXLEN);
3624 	}
3625 	else{
3626 	  strncpy(obj->name,ptnames[0],OBJNAMESMAXLEN);
3627 	}
3628 	Add2ObjList(lheadobjs,obj);
3629 	np++;
3630       }
3631     }
3632   }
3633 
3634   if(np!=nplanets){
3635     printf("WARNING CreateUniverse(): number of planets incorrect: %d\n",np);
3636     exit(-1);
3637   }
3638 
3639   free(gpos);
3640 }
3641 
PlanetAtraction(float * fx,float * fy,float x,float y,float m)3642 float PlanetAtraction(float *fx,float *fy,float x,float y,float m){
3643   /*
3644     calculates the atraction forces betwwen ships and planets
3645     returns:
3646     the force in fx,fy arguments.
3647     the potential energy.
3648   */
3649 
3650   struct ObjList *ls;
3651   float rx,ry,r,r2,ir2r;
3652   float U; /* potential*/
3653   float GM;
3654 
3655   if(m==0){
3656     *fx=*fy=0;
3657     return(0);
3658   }
3659 
3660 
3661   ls=listheadplanets.list;
3662   U=0;
3663 
3664   while (ls!=NULL){
3665     rx=ls->obj->x-x;
3666     ry=ls->obj->y-y;
3667     r2=rx*rx+ry*ry;
3668 
3669     if(r2<GRAVITATION_RANGE2){
3670       GM=G*ls->obj->mass;
3671       r=sqrt(r2);
3672       ir2r=1./(r2*r);
3673       *fx+=GM*rx*ir2r;
3674       *fy+=GM*ry*ir2r;
3675       U-=GM/r;
3676     }
3677     ls=ls->next;
3678   }
3679 
3680   *fx*=m;
3681   *fy*=m;
3682   U*=m;
3683 
3684   return(U);
3685 }
3686 
3687 
PrintfObjInfo(FILE * fp,Object * obj)3688 int PrintfObjInfo(FILE *fp,Object *obj){
3689   /*
3690     printf obj info
3691     used only for debug.
3692   */
3693 
3694   int in,dest,parent,planet;
3695   fprintf(fp,"time: %d\n id:%d durable:%d visible:%d\n \
3696 points:%d habitat:%d mode:%d \nmodified: %d \n	       \
3697 x:%g y:%g x0:%g y0:%g \nvx:%g vy:%g \n		       \
3698 fx0:%g fy0:%g fx:%g fy:%g\n a:%g ang_v:%g accel:%g \n  \
3699 gas:%g gas_max:%g life:%g shield:%g state:%g\n",
3700 	  GetTime(),
3701 	  obj->id,obj->durable,obj->visible,
3702 	  obj->kills,obj->habitat,obj->mode,
3703 	  obj->modified,
3704 	  obj->x,obj->y,obj->x0,obj->y0,
3705 	  obj->vx,obj->vy,
3706 	  obj->fx0,obj->fy0,obj->fx,obj->fy,
3707 	  obj->a,obj->ang_v,obj->accel,
3708 	  obj->gas,obj->gas_max,
3709 	  obj->life,obj->shield,obj->state);
3710 
3711   fprintf(fp,"dest_r2:%g mass:%d radio:%d \ntype:%d subtype:%d\n\
3712  damage:%d player:%d player:%d\nai:%d trace:%d norder:%d\n",
3713 	  obj->dest_r2,obj->mass,obj->radio,
3714 	  obj->type,obj->subtype,
3715 	  obj->damage,obj->player,obj->player,
3716 	  obj->ai,obj->trace,obj->norder);
3717 
3718   in=0;
3719   dest=0;
3720   planet=0;
3721   parent=0;
3722 
3723   if(obj->in!=NULL)in=obj->in->id;
3724   if(obj->dest!=NULL)dest=obj->dest->id;
3725   if(obj->parent!=NULL)parent=obj->parent->id;
3726   if(obj->planet!=NULL)planet=obj->id;
3727 
3728   fprintf(fp,"parent:%d dest:%d in:%d planet:%d\n weapon:%d engine:%d\n ",
3729 	  parent,dest,in,planet,
3730 	  obj->weapon->type,obj->engine.type);
3731 
3732   fprintf(fp,"parent:%p dest:%p in:%p planet:%p\n",
3733 	  (void *)obj->parent,(void *)obj->dest,(void *)obj->in,(void *)obj->planet);
3734 
3735   return(0);
3736 }
3737 
ChooseInitPlanet(struct HeadObjList lheadobjs)3738 Object *ChooseInitPlanet(struct HeadObjList lheadobjs){
3739   /*
3740     returns:
3741     a pointer to a free planet.
3742   */
3743 
3744   struct ObjList *ls;
3745   int n,cont=0;
3746   int nplanets=0;
3747   int rplanet;
3748 
3749   /* counting planets */
3750   ls=lheadobjs.list;
3751   while(ls!=NULL){
3752     if(ls->obj->type==PLANET){
3753       cont++;
3754     }
3755     ls=ls->next;
3756   }
3757 
3758   nplanets=cont;
3759   n=0;
3760 
3761   do{
3762     rplanet=(int)(nplanets*Random(-1));
3763 
3764     ls=lheadobjs.list;
3765     cont=0;
3766     while(ls!=NULL){
3767       if(ls->obj->type==PLANET){
3768 	if(ls->obj->player==0 && cont==rplanet){  /* a random planet */
3769 	  return(ls->obj);
3770 	}
3771       }
3772       ls=ls->next;
3773       cont++;
3774     }
3775     n++;
3776   }
3777   while(n<10);
3778 
3779   cont=0;
3780   ls=lheadobjs.list;
3781   while(ls!=NULL){
3782     if(ls->obj->type==PLANET ){
3783       if(ls->obj->player==0){  /* the first free planet */
3784 	return(ls->obj);
3785       }
3786     }
3787     ls=ls->next;
3788     cont++;
3789   }
3790 
3791   fprintf(stderr,"ERROR ChooseInitPlanet(): Too many players or too few planets\n");
3792   return(NULL);
3793 }
3794 
CreateShips(struct HeadObjList * lheadobjs)3795 void CreateShips(struct HeadObjList *lheadobjs){
3796   /*
3797     Choose initial planet.
3798     Create the initial player ships
3799   */
3800   Object *obj,*planet;
3801   Segment *s;
3802   int i;
3803   struct Player *plyr;
3804   plyr=GetPlayers();
3805 
3806   for(i=1;i<=GameParametres(GET,GNPLAYERS,0);i++){
3807     planet=ChooseInitPlanet(*lheadobjs);
3808     if(planet==NULL){
3809       fprintf(stderr,"ERROR CreateShips(): obj==NULL\n");
3810       exit(-1);
3811     }
3812     s=LandZone(planet->planet);
3813     if(s==NULL){
3814       fprintf(stderr,"ERROR CreateShips(): Segment==NULL\n");
3815       exit(-1);
3816     }
3817 
3818     obj=NewObj(SHIP,QUEEN,
3819 	       0,0,0,0,
3820 	       CANNON5,ENGINE5,i,NULL,planet);
3821 
3822     obj->x=s->x0+(s->x1-s->x0)*(Random(-1));
3823 
3824     obj->y=obj->y0=(s->y0)+obj->radio+1;
3825     obj->a=PI/2;
3826     obj->ai=1;
3827     obj->habitat=H_PLANET;
3828     obj->mode=LANDED;
3829 
3830     Add2ObjList(lheadobjs,obj);
3831     plyr[obj->player].nbuildships++;
3832 
3833     planet->player=obj->player;
3834 
3835     if(GameParametres(GET,GNET,0)==TRUE){
3836       if(GetProc()==plyr[planet->player].proc){
3837 	SetModified(planet,SENDOBJPLANET);
3838 	planet->sw=1;
3839 	planet->ttl=0;
3840       }
3841     }
3842 
3843     plyr[obj->player].kplanets=Add2IntList((plyr[obj->player].kplanets),planet->id);
3844     plyr[obj->player].nplanets++;
3845 
3846     if(GameParametres(GET,GKPLANETS,0)==FALSE){
3847       int j,k;
3848 
3849       for(j=-2;j<3;j++){
3850 	for(k=-2;k<3;k++){
3851 	  if(j*j+k*k<8){
3852 	    Add2IntIList(&(plyr[obj->player].ksectors),
3853 			 Quadrant(planet->x+j*SECTORSIZE,planet->y+k*SECTORSIZE));
3854 	  }
3855 	}
3856       }
3857     }
3858     if(i==actual_player){
3859       cv=obj;
3860       ship_c=obj;
3861       habitat.type=H_PLANET;
3862       habitat.obj=planet;
3863     }
3864   }
3865   return;
3866 }
3867 
3868 
3869 
CheckGame(char * cad,int action)3870 int CheckGame(char *cad,int action){
3871   /*
3872     Check some game consistence.
3873     Used every step (!!HERE check this)
3874     Used after load a game.
3875     action:
3876     0 only show messages
3877     1 try to correct errors
3878   */
3879 
3880   struct ObjList *ls;
3881   struct OrderList *lo;
3882   Object *obj;
3883   int i;
3884   int n=0;
3885   int types[ALLOBJS];
3886   int type;
3887   int proc;
3888   int nplayers=0;
3889 
3890   struct Player *plyr;
3891   plyr=GetPlayers();
3892 
3893 
3894   proc=GetProc();
3895   nplayers=(GameParametres(GET,GNPLAYERS,0));
3896   /* Checking Orders */
3897 
3898   for(i=0;i<ALLOBJS;i++){
3899     types[i]=0;
3900   }
3901 
3902   printf("%s",cad);
3903 
3904   ls=listheadobjs.list;
3905   while(ls!=NULL){
3906     obj=ls->obj;
3907 
3908     type=obj->type+1;
3909     if(type>ALLOBJS)type=ALLOBJS;
3910     types[type]++;
3911 
3912     if(proc==plyr[obj->player].proc){
3913       n=0;
3914       lo=obj->lorder;
3915       while(lo!=NULL){
3916 	n++;
3917 	lo=lo->next;
3918       }
3919       if(n!=obj->norder){
3920 	fprintf(stderr,"ERROR CheckGame():norder incorrect\n");
3921 	printf("\tObj: %d, type: %d norder=%d , size of list: %d\n",
3922 	       obj->id,obj->type,obj->norder,n);
3923 	printf("\tDeleting all the orders of object %d\n",obj->id);
3924 	DelAllOrder(obj);
3925       }
3926     }
3927 
3928     if(obj->player<0 || obj->player>nplayers+2){
3929       fprintf(stderr,"\tError CheckGame() obj: %d player id: %d invalid.\n",obj->id,obj->player);
3930     }
3931 
3932     if(obj->type==SHIP && obj->subtype==TOWER && obj->habitat!=H_PLANET){
3933       fprintf(stderr,"\tError CheckGame() obj %d TOWER not in planet. habitat: %d . player: %d \n",obj->id, obj->habitat,obj->player);
3934       printf("\tRemoving the ship (%d)%d\n",obj->player,obj->pid);
3935       obj->state=0;
3936       SetModified(obj,SENDOBJKILL);
3937       obj->ttl=0;
3938       ls=ls->next;continue;
3939     }
3940 
3941     /* if planet don't belongs to a landed ship */
3942     if(obj->type==SHIP){
3943       if(obj->radar<2000){
3944 	printf("SHIP %d(%d) player: %d with radar: %d\n",obj->pid,obj->id,obj->player,obj->radar);
3945       }
3946       if(obj->subtype==FIGHTER){
3947 	if(obj->items&ITSURVIVAL && obj->level<MINLEVELPILOT){
3948 	  printf("Error ship %d level: %d items: %d  => Removed survival pod.\n",obj->id,obj->level,obj->items);
3949 	  obj->items=obj->items&(~ITSURVIVAL);
3950 	}
3951 
3952 	if(fabs(obj->cost - COSTFIGHTER*COSTFACTOR*pow(COSTINC,obj->level))>0.01){
3953 	  printf("Error ship %d (%d-%d) level: %d cost: %f ->  %f \n",
3954 		 obj->id,obj->player,obj->pid,
3955 		 obj->level,obj->cost,0.01*COSTFACTOR*pow(COSTINC,obj->level));
3956 	  obj->cost=0.01*COSTFACTOR*pow(COSTINC,obj->level);
3957 	}
3958 
3959       }
3960       if(obj->mode==LANDED && obj->in==NULL){
3961 	fprintf(stderr,"\tError CheckGame() obj %d landed and in NULL\n",obj->id);
3962 	ls=ls->next;continue;
3963       }
3964       if(obj->mode==LANDED && obj->in!=NULL && obj->habitat==H_PLANET){
3965 	if(obj->in->planet==NULL){
3966 	  fprintf(stderr,"\tError CheckGame() obj %d planet not assigned\n",obj->id);
3967 	  ls=ls->next;continue;
3968 	}
3969       }
3970       if(obj->habitat!=H_SPACE && obj->in==NULL){
3971 	fprintf(stderr,"\tError CheckGame() obj %d not in space and in = NULL\n",obj->id);
3972 	fprintf(stderr,"\t\ttype: %d stype: %d\n",obj->type,obj->subtype);
3973 	fprintf(stderr,"\t\thabitat: %d\n",obj->habitat);
3974 	if(action){
3975 	  printf("\tRemoving the ship (%d)%d\n",obj->player,obj->pid);
3976 	  obj->state=0;
3977 	  SetModified(obj,SENDOBJKILL);
3978 	  obj->ttl=0;
3979 	}
3980 
3981 	ls=ls->next;continue;
3982       }
3983       if(obj->habitat==H_SHIP){
3984 	int sw=0;
3985 	if (obj->in==NULL){
3986 	  fprintf(stderr,"\tError CheckGame() obj %d in ship and in= NULL\n",obj->id);
3987 	  sw++;
3988 	}
3989 
3990 	if(obj->in!=NULL){
3991 	  if(CargoIsObj(obj->in,obj)==0){
3992 
3993 	    /* if((obj->in->items & ITPILOT)==0){ */
3994 	    sw++;
3995 	    printf("\tError CheckGame() obj (%d)%d (%d,%d) has no a pilot (%d)%d (%d,%d)\n",
3996 		   obj->in->player,obj->in->pid,obj->in->type,obj->in->subtype,
3997 		   obj->player,obj->pid,obj->type,obj->subtype);
3998 	    if(action){
3999 	      printf("\tRemoving the ship (%d)%d\n",obj->player,obj->pid);
4000 	      obj->state=0;
4001 	      SetModified(obj,SENDOBJKILL);
4002 	      obj->ttl=0;
4003 	    }
4004 	  }
4005 
4006 
4007 	}
4008 	if(sw){
4009 	  ls=ls->next;continue;
4010 	}
4011       }
4012     }
4013 
4014     ls=ls->next;
4015   }
4016   return(0);
4017 }
4018 
4019 
Density(void)4020 void Density(void){
4021   /*
4022 
4023     Not used by now
4024 
4025   */
4026   struct ObjList *ls;
4027   int i,j;
4028   int den[10][10];
4029   float x,y;
4030 
4031   for(i=0;i<10;i++)
4032     for(j=0;j<10;j++)
4033       den[i][j]=0;
4034 
4035   ls=listheadobjs.list;
4036   while(ls!=NULL){
4037     if(ls->obj->type==PLANET){
4038 
4039       if(ls->obj->habitat==H_PLANET){
4040 	x=ls->obj->in->planet->x;
4041 	y=ls->obj->in->planet->y;
4042       }
4043       else{
4044 	x=ls->obj->x;
4045 	y=ls->obj->y;
4046       }
4047 
4048 
4049       i=10.*x/(float)GameParametres(GET,GULX,0);
4050       j=10.*y/(float)GameParametres(GET,GULY,0);
4051       i+=5;
4052       j+=5;
4053       if(i<0)i=0;
4054       if(j<0)j=0;
4055       if(i>9)i=9;
4056       if(j>9)j=9;
4057       den[i][j]++;
4058     }
4059     ls=ls->next;
4060   }
4061 
4062   for(i=0;i<10;i++){
4063     for(j=0;j<10;j++){
4064     }
4065   }
4066 }
4067 
4068 
GetUniverse(void)4069 void GetUniverse(void){
4070   struct Player *plyr;
4071 
4072 
4073   /*ExecLoad("kk"); */
4074   ExecLoad(savefile);
4075   plyr=GetPlayers();
4076   plyr[actual_player].status=PLAYERMODIFIED;
4077   p_time=GetTime();
4078   CheckGame("Checking game after load...",1);
4079   printf("done\n");
4080 }
4081 
NetComm(void)4082 void NetComm(void){
4083   /* net gamming */
4084 
4085   /* orders to  thread:
4086      OTSENDOBJS: send modified objects.
4087      OTSENDALLOBJS save: send all the objects.
4088      OTSENDLOAD load: load all the objects.
4089      OTSENDKILL to finish: quit the program.
4090   */
4091   int mode;
4092   int fd;
4093   struct Keys *key;
4094 
4095   mode=GameParametres(GET,GMODE,0);
4096   order2thread=OTSENDOBJS;
4097   key=GetKeys();
4098 
4099   if(mode==SERVER){
4100     if(key->save==TRUE){
4101       order2thread=OTSENDSAVE;
4102     }
4103 
4104     if(key->load==TRUE){
4105       /* check if is possible open the dir */
4106       /* checking the file */
4107       if((fd=open(savefile,O_RDONLY))==-1){
4108 	fprintf(stdout,"CommServer()[OTSENDLOAD]: Can'T open the file: %s\n",savefile);
4109       }
4110       else{
4111 	order2thread=OTSENDLOAD;
4112       }
4113       close(fd);
4114     }
4115   }
4116 
4117   if(GameParametres(GET,GQUIT,0)==2){
4118     order2thread=OTSENDKILL;
4119   }
4120 
4121   switch(mode){
4122   case SERVER:
4123     LoadBuffer(order2thread,&buffer1,SERVER);
4124     sem_post(&sem_barrier1); /* run comm. thread*/
4125     break;
4126   case CLIENT:
4127     sem_post(&sem_barrier1); /* run comm. thread*/
4128     break;
4129   default:
4130     break;
4131   }
4132 
4133   sem_wait(&sem_barrier); /* HERE send this far away in code */
4134 }
4135 
4136 
int_handler(int sign)4137 void int_handler(int sign){
4138   fprintf(stderr,"signal n %d received (SIGINT)\n",sign);
4139   Quit(NULL,NULL);
4140 }
4141 
segfault_handler(int sign)4142 void segfault_handler(int sign){
4143   fprintf(stderr,"signal n %d received (SEGFAULT)\n",sign);
4144   if(ExecSave(listheadobjs,SAVETMPFILE)!=0){
4145     fprintf(stderr,"Error in main(): I can't open %s\n",SAVETMPFILE);
4146     exit(-1);
4147   }
4148   fprintf(stderr,"%s %s\n",GetLocale(L_GAMESAVEDTO),SAVETMPFILE);
4149   exit(-1);
4150   /*  Quit(NULL,NULL); */
4151 }
4152 
4153 
GetGold(void)4154 void GetGold(void){
4155   /*
4156     Count the number of planets that belongs to each player
4157     Increase players gold
4158   */
4159 
4160 
4161   struct ObjList *ls;
4162   int nplayers;
4163   int i;
4164   int proc;
4165   float inctower;
4166   float levelfactor;
4167   struct Player *plyr;
4168   plyr=GetPlayers();
4169 
4170   proc=GetProc();
4171   nplayers=GameParametres(GET,GNPLAYERS,0);
4172 
4173   for(i=0;i<nplayers+2;i++){
4174     plyr[i].nplanets=0;
4175     plyr[i].nships=0;
4176     plyr[i].balance=0;
4177     plyr[i].level=0;
4178   }
4179 
4180   ls=listheadobjs.list;
4181   while(ls!=NULL){
4182     switch(ls->obj->type){
4183     case PLANET:
4184       plyr[ls->obj->player].nplanets++;
4185       break;
4186     case SHIP:
4187       if(ls->obj->subtype!=SATELLITE){
4188 	plyr[ls->obj->player].nships++;
4189 	plyr[ls->obj->player].level+=ls->obj->level;
4190       }
4191       break;
4192     default:
4193       ls=ls->next;continue;
4194       break;
4195     }
4196 
4197     if(proc!=plyr[ls->obj->player].proc){
4198       ls=ls->next;continue;
4199     }
4200     if(ls->obj->player==0){
4201       ls=ls->next;continue;
4202     }
4203 
4204     switch(ls->obj->type){
4205     case PLANET:
4206       /*gold for each planet*/
4207       plyr[ls->obj->player].balance+=.01*RESOURCEFACTOR;
4208       break;
4209     case SHIP:
4210       if(ls->obj->subtype==PILOT){
4211 	plyr[ls->obj->player].balance-=0.25*ls->obj->cost;
4212 	ls=ls->next;continue;
4213       }
4214       plyr[ls->obj->player].balance-=ls->obj->cost;
4215 
4216       switch(ls->obj->subtype){
4217       case TOWER:
4218 	levelfactor=(1.0+1.0*ls->obj->level);
4219 
4220 	if(ls->obj->in->planet->gold>0){
4221 	  inctower=(.4+0.1*levelfactor)*RESOURCEFACTOR;
4222 	  if(ls->obj->in->planet->gold>inctower){
4223 	    plyr[ls->obj->player].balance+=inctower;
4224 	    ls->obj->in->planet->gold-=inctower;
4225 	    ls->obj->in->planet->A-=0.015;
4226 	    if(ls->obj->in->planet->A<0)ls->obj->in->planet->A=0;
4227 	  }
4228 	  else{
4229 	    plyr[ls->obj->player].balance+=ls->obj->in->planet->gold;
4230 	    ls->obj->in->planet->gold=0;
4231 	  }
4232 	}
4233 	else{
4234 	  ls->obj->in->planet->gold=0;
4235 	  if(ls->obj->in->planet->A > 0.015){
4236 	    plyr[ls->obj->player].balance+=0.015*levelfactor;
4237 	    ls->obj->in->planet->A-=0.015;
4238 	    if(ls->obj->in->planet->A<0)ls->obj->in->planet->A=0;
4239 	  }
4240 	  else{
4241 	    plyr[ls->obj->player].balance+=ls->obj->in->planet->A*levelfactor;
4242 	    ls->obj->in->planet->A=0.0;
4243 	  }
4244 	}
4245 
4246 
4247 	break;
4248 
4249       default:
4250 	break;
4251       }
4252 
4253       break;
4254     default:
4255       break;
4256     }
4257     ls=ls->next;
4258   }
4259 
4260   for(i=0;i<nplayers+2;i++){
4261     if(proc==plyr[i].proc){
4262       plyr[i].gold+=plyr[i].balance;
4263     }
4264   }
4265 }
4266 
4267 
GetPoints(struct HeadObjList * hol,int proc,struct Player * p)4268 void GetPoints(struct HeadObjList *hol,int proc,struct Player *p){
4269   /*
4270      version 0.3    12Dic2010
4271 
4272      if state is 0 sum points and experience
4273   */
4274 
4275   struct ObjList *ls;
4276   Object *obj;   /* dead object */
4277   int sw=0;
4278   int gnet;
4279   struct Player *plyr;
4280   plyr=GetPlayers();
4281 
4282   ls=hol->list;
4283   gnet=GameParametres(GET,GNET,0);
4284 
4285   while(ls!=NULL){
4286     obj=ls->obj;
4287     sw=0;
4288     if(gnet==TRUE){
4289       if(obj->modified==SENDOBJDEAD)sw=1;
4290     }
4291     else{
4292       if(obj->state<=0)sw=1;
4293     }
4294 
4295     if(obj->type==SHIP && obj->subtype==PILOT && obj->sw!=0){
4296       sw=1;
4297     }
4298 
4299     if(sw){
4300       GetPointsObj(hol,plyr,obj);/* points and experience */
4301     }
4302 
4303     /*****
4304 	   Partial experience
4305 	   By now, only due to proximity with enemies
4306     ******/
4307     if(obj->pexperience>0){
4308       obj->pexperience=obj->pexperience>0.1?0.1:obj->pexperience;
4309       Experience(obj,obj->pexperience);
4310       obj->pexperience=0;
4311     }
4312 
4313     ls=ls->next;
4314   }
4315   return;
4316 }
4317 
4318 
GetPointsObj(struct HeadObjList * lhobjs,struct Player * p,Object * obj)4319 void GetPointsObj(struct HeadObjList *lhobjs,struct Player *p,Object *obj){
4320   /*
4321      version 0.3    12Dic2010
4322      obj   dead object
4323      if state is 0 sum points and experience
4324   */
4325 
4326 
4327   Object *obj2;  /* killer */
4328   Object *obj3;  /* who receive points */
4329   int il;
4330   float factor,points;
4331 
4332 
4333 
4334   if(obj==NULL)return;
4335   if(obj->sw==0)return;
4336 
4337   obj2=obj3=NULL;
4338 
4339   switch(obj->type){
4340   case PROJECTILE:
4341     /* points to nobody */
4342 
4343     break;
4344   case SHIP:
4345     /* points to the killer */
4346     if(obj->subtype==PILOT){  /* no points for killing a pilot */
4347       break;
4348     }
4349     obj2=SelectObj(lhobjs,(obj->sw));
4350 
4351     if(obj2!=NULL){
4352       obj3=NULL;
4353       if(obj2->type==SHIP)obj3=obj2;
4354       if(obj3!=NULL){
4355 	/* must be a SHIP */
4356 	obj3->kills++;
4357 	p[obj3->player].nkills++;
4358 
4359 	/* Experience for kill an enemy */
4360 	il=obj->level - obj3->level;
4361 	if(il>3)il=3;
4362 	factor=50;
4363 	if(il<0)factor/=2;
4364 	if(il<-1)factor/=2;
4365 	if(il<-2)factor/=2;
4366 	if(factor>0){
4367 	  points=factor*pow(2,obj->level);
4368 	  if(obj->subtype==PILOT && obj->state<=0)points/=2;
4369 	  if(points<10)points=10;
4370 	  Experience(obj3,points);
4371 	}
4372 	/* --Experience for kill an enemy */
4373       }
4374     }
4375     obj->sw=0;
4376     break;
4377   case ASTEROID:
4378 
4379     obj2=SelectObj(lhobjs,(obj->sw));
4380     if(obj2!=NULL){
4381       obj3=NULL;
4382       /* 	    if(obj2->type==PROJECTILE){ */
4383       /* 	      obj3=SelectObj(&listheadobjs,obj2->parent->id); */
4384       /* 	    } */
4385       if(obj2->type==SHIP)obj3=obj2;
4386       if(obj3!=NULL){
4387 	/* must be a SHIP */
4388 
4389 	switch(obj->subtype){
4390 	case ASTEROID1:
4391 	  p[obj3->player].gold+=50;
4392 	  break;
4393 	case ASTEROID2:
4394 	  p[obj3->player].gold+=100;
4395 	  break;
4396 	case ASTEROID3:
4397 	  p[obj3->player].gold+=200;
4398 	  break;
4399 	default:
4400 	  fprintf(stderr,"ERROR in GetGold():asteroid subtype %d unknown\n",obj->subtype);
4401 	  exit(-1);
4402 	  break;
4403 	}
4404       }
4405     }
4406     obj->sw=0;
4407     break;
4408   default:
4409     break;
4410   }
4411 
4412   return;
4413 }
4414 
4415 
PrintGameOptions(void)4416 void PrintGameOptions(void){
4417 
4418   printf("actual game options:\n");
4419   printf("\tUniverse size: %d\n",GameParametres(GET,GULX,0));
4420   printf("\tNumber of Galaxies: %d\n",GameParametres(GET,GNGALAXIES,0));
4421   printf("\tNumber of planets: %d\n",GameParametres(GET,GNPLANETS,0));
4422   printf("\tNumber of players: %d\n",GameParametres(GET,GNPLAYERS,0));
4423   if(GameParametres(GET,GKPLANETS,0)==TRUE){
4424     printf("\tPlanets known by all the players.\n");
4425   }
4426   if(GameParametres(GET,GKPLANETS,0))
4427     printf("\tknown planets: yes\n");
4428   else
4429     printf("\tknown planets: no\n");
4430 
4431   if(GameParametres(GET,GCOOPERATIVE,0))
4432     printf("\tcooperative mode: yes\n");
4433   else
4434     printf("\tcooperative mode: no\n");
4435 
4436   if(GameParametres(GET,GCOMPCOOPERATIVE,0))
4437     printf("\tcomputer cooperative mode: yes\n");
4438   else
4439     printf("\tcomputer cooperative mode: no\n");
4440 
4441   if(GameParametres(GET,GQUEEN,0))
4442     printf("\tQueen mode: yes\n");
4443   else
4444     printf("\tQueen mode: no\n");
4445 
4446   if(GameParametres(GET,GPIRATES,0))
4447     printf("\tpirates: yes\n");
4448   else
4449     printf("\tpirates: no\n");
4450 
4451   if(GameParametres(GET,GENEMYKNOWN,0))
4452     printf("\tEnemy known: yes\n");
4453   else
4454     printf("\tEnemy known: no\n");
4455 
4456 
4457   if(GameParametres(GET,GNET,0))
4458     printf("\tnet game: yes\n");
4459   else
4460     printf("\tnet game: no\n");
4461 
4462   printf("\tSound: %d  volume: %d\n",
4463 	 GameParametres(GET,GSOUND,0),GameParametres(GET,GSOUNDVOL,0));
4464   printf("\tMusic: %d  volume: %d\n",
4465 	 GameParametres(GET,GMUSIC,0),GameParametres(GET,GMUSICVOL,0));
4466 
4467 }
4468 
4469 
SetGameParametres(struct Parametres param)4470 void SetGameParametres(struct Parametres param){
4471   int width,height;
4472 
4473   GameParametres(SET,DEFAULT,0);   /* defaults game values */
4474 
4475   if(gfont==NULL){
4476     GameParametres(SET,GPANEL,PANEL_HEIGHT);
4477   }
4478   else{
4479     GameParametres(SET,GPANEL,2*gdk_text_height(gfont,"pL",2));
4480   }
4481 
4482   if(param.server==TRUE||param.client==TRUE){
4483     GameParametres(SET,GNET,TRUE);
4484     printf("NET\n");
4485     if(param.server==TRUE){
4486       GameParametres(SET,GMODE,SERVER);
4487     }
4488     if(param.client==TRUE){
4489       GameParametres(SET,GMODE,CLIENT);
4490     }
4491   }
4492 
4493   GameParametres(SET,GNGALAXIES,param.ngalaxies);
4494   GameParametres(SET,GNPLANETS,param.nplanets);
4495   GameParametres(SET,GNPLAYERS,param.nplayers);  /*+1 system +1 pirates */
4496 
4497   if(param.kplanets==TRUE){
4498     GameParametres(SET,GKPLANETS,TRUE);
4499   }
4500 
4501   if(param.pirates==FALSE){
4502     GameParametres(SET,GPIRATES,FALSE);
4503   }
4504 
4505   if(param.enemyknown==TRUE){
4506     GameParametres(SET,GENEMYKNOWN,TRUE);
4507   }
4508 
4509   GameParametres(SET,GULX,param.ul);
4510   GameParametres(SET,GULY,param.ul);
4511 
4512   GameParametres(SET,GCOOPERATIVE,param.cooperative);
4513   GameParametres(SET,GCOMPCOOPERATIVE,param.compcooperative);
4514 
4515   GameParametres(SET,GMUSIC,param.music);
4516   GameParametres(SET,GSOUND,param.sound);
4517   GameParametres(SET,GSOUNDVOL,param.soundvol);
4518   GameParametres(SET,GMUSICVOL,param.musicvol);
4519 
4520 
4521   GameParametres(SET,GWIDTH,DEFAULTWIDTH);
4522   GameParametres(SET,GHEIGHT,DEFAULTHEIGHT);
4523   GetGeom(param.geom,&width,&height);
4524   GameParametres(SET,GWIDTH,width);
4525   GameParametres(SET,GHEIGHT,height-GameParametres(GET,GPANEL,0));
4526 
4527   printf("W: %d H: %d \n",    GameParametres(GET,GWIDTH,0),GameParametres(GET,GHEIGHT,0));
4528   printf("W: %d H: %d \n",width,height);
4529 
4530 
4531   /*********** process identifier ***********/
4532 
4533   SetProc(0);
4534   SetNProc(1);
4535 
4536   if(GameParametres(GET,GMODE,0)==CLIENT){
4537     SetProc(1);
4538   }
4539   if(GameParametres(GET,GNET,0)==TRUE){
4540     SetNProc(2);
4541   }
4542 
4543   /********** --process identifier ***********/
4544 
4545 }
4546 
MakeTitle(struct Parametres param,char * title)4547 void MakeTitle(struct Parametres param, char *title){
4548   strncat(title,TITLE,64-strlen(title));
4549   if(param.server==TRUE)
4550     strcat(title,"(server)  ");
4551   if(param.client==TRUE)
4552     strcat(title,"(client)  ");
4553   strncat(title,version,64-strlen(title));
4554   strcat(title,"  ");
4555   strncat(title,copyleft,64-strlen(title));
4556 }
4557 
4558 
InitGameVars(void)4559 void InitGameVars(void){
4560   int i;
4561   struct Sockfd sfd;
4562   int nx,ny;
4563   struct Player *plyr;
4564 
4565   /****** start server and client *********/
4566 
4567   if(GameParametres(GET,GNET,0)==TRUE){
4568     if(param.server==TRUE){
4569       printf("SERVER\n");
4570       OpenComm(0,param,&sfd);
4571       printf("opencomm finished\n");
4572       StartComm(0,&sfd);
4573     }
4574     if(param.client==TRUE){
4575       printf("CLIENT\n");
4576       OpenComm(1,param,&sfd);
4577       printf("opencomm finished\n");
4578       StartComm(1,&sfd);
4579     }
4580     printf("conexion established\n");
4581 
4582     /* synchronization with comm threads  */
4583     sem_wait(&sem_barrier);
4584   }
4585   /****** --start server and client *********/
4586 
4587   /*****************************************************************/
4588   /* client and server now known all the game options              */
4589   /*****************************************************************/
4590 
4591   listheadobjs.list=NULL;
4592   listheadobjs.n=0;
4593   listheadplanets.list=NULL;
4594   listheadplanets.n=0;
4595   listheadtext.next=NULL;
4596   listheadtext.info.n=0;
4597 
4598   for(i=0;i<4;i++)fobj[i]=0;
4599   gtime0=0;
4600 
4601   /********** players ***********/
4602   /* CreatePlayers(&players); */
4603   CreatePlayers(clientname,param);
4604   plyr=GetPlayers();
4605   /********** --players ***********/
4606 
4607   /********** teams ***********/
4608   CreateTeams(param);
4609   /********** --teams **********/
4610 
4611   if(param.queen){
4612     printf("WARNING: Queen mode set to ON.\n");
4613     GameParametres(SET,GQUEEN,TRUE);
4614   }
4615 
4616   /******** Create Universe **************/
4617   if(param.client==FALSE){
4618     printf("CreateUniverse()...");
4619     CreateUniverse(GameParametres(GET,GULX,0),GameParametres(GET,GULY,0),&listheadobjs,planetnames);
4620     CreatePlanetList(listheadobjs,&listheadplanets);
4621     printf("...done\n");
4622     printf("CreateShips()...");
4623     CreateShips(&listheadobjs);
4624     printf("...done\n");
4625 
4626   }
4627   /******** -- Create Universe **************/
4628 
4629   listheadcontainer=malloc((GameParametres(GET,GNPLANETS,0)+1)*sizeof(struct HeadObjList));
4630   MemUsed(MADD,(GameParametres(GET,GNPLANETS,0)+1)*sizeof(struct HeadObjList));
4631   if(listheadcontainer==NULL){
4632     fprintf(stderr,"ERROR in malloc main()\n");
4633     exit(-1);
4634   }
4635   for(i=0;i<GameParametres(GET,GNPLANETS,0)+1;i++){
4636     listheadcontainer[i].list=NULL;
4637     listheadcontainer[i].n=0;
4638   }
4639 
4640   listheadkplanets=malloc((GameParametres(GET,GNPLAYERS,0)+2)*sizeof(struct HeadObjList));
4641   MemUsed(MADD,(GameParametres(GET,GNPLAYERS,0)+2)*sizeof(struct HeadObjList));
4642   if(listheadkplanets==NULL){
4643     fprintf(stderr,"ERROR in malloc main()\n");
4644     exit(-1);
4645   }
4646   for(i=0;i<GameParametres(GET,GNPLAYERS,0)+2;i++){
4647     listheadkplanets[i].list=NULL;
4648     listheadkplanets[i].n=0;
4649   }
4650 
4651   /********* sending and receiving Universe *****************/
4652 
4653   if(param.server==TRUE){
4654     if(ExecSave(listheadobjs,SAVETMPFILE)!=0){
4655       fprintf(stderr,"Error in main(): I can't open %s\n",SAVETMPFILE);
4656       exit(-1);
4657     }
4658 
4659     SetModifiedAll(&listheadobjs,ALLOBJS,SENDOBJUNMOD,TRUE);
4660     p_time=GetTime();
4661   }
4662 
4663   if(GameParametres(GET,GNET,0)==TRUE){
4664     sem_post(&sem_barrier1);
4665     sem_wait(&sem_barrier);
4666   }
4667 
4668   if(param.client==TRUE){
4669     GetUniverse();
4670     g_objid=glocal.g_objid;
4671     plyr=GetPlayers();
4672 
4673     SetModifiedAll(&listheadobjs,ALLOBJS,SENDOBJUNMOD,TRUE);
4674     CreatePlanetList(listheadobjs,&listheadplanets);
4675   }
4676   /********* --sending and receiving Universe *****************/
4677 
4678   actual_player=1;
4679   if(GameParametres(GET,GMODE,0)==SERVER){ /* only two human players, by now*/
4680     actual_player=2;
4681   }
4682   actual_player0=actual_player;
4683   plyr[actual_player].control=HUMAN;
4684 
4685   printf("Actual Player: %d\n",actual_player);
4686 
4687   DestroyObjList(&listheadplayer);
4688   listheadplayer.n=0;
4689   listheadplayer.list=NULL;
4690   CreatePlayerList(listheadobjs,&listheadplayer,actual_player);
4691   listheadplayer.update=0;
4692 
4693   cv=NextCv(&listheadplayer,cv,actual_player);
4694   if(cv!=NULL){
4695     habitat.type=cv->habitat;
4696     habitat.obj=cv->in;
4697     cv->selected=TRUE;
4698   }
4699 
4700   /* Adding planets to players list */
4701   AddPlanets2List(&listheadobjs,plyr);
4702 
4703   /* print teams */
4704   PrintTeams();
4705 
4706   /*****CELLON*****/
4707 
4708   nx=GameParametres(GET,GULX,0)/2000;
4709   ny=GameParametres(GET,GULY,0)/2000;
4710 
4711   cell=malloc(nx*ny*sizeof(int));
4712   if(cell==NULL){
4713     fprintf(stderr,"ERROR in malloc (creating cell)\n");
4714     exit(-1);
4715   }
4716   for(i=0;i<nx*ny;i++){
4717     cell[i]=0;
4718   }
4719 
4720   /*****--CELLON*****/
4721   PrintGameOptions();
4722 }
4723 
AddPlanets2List(struct HeadObjList * listheadobjs,struct Player * players)4724 void AddPlanets2List(struct HeadObjList *listheadobjs,struct Player *players){
4725   /*
4726      Add known planets to players list
4727   */
4728   struct ObjList *ls;
4729   int i;
4730 
4731   if(listheadobjs==NULL || players==NULL){
4732     fprintf(stderr,"ERROR in AddPlanets2List()\n");
4733     exit(-1);
4734   }
4735 
4736   ls=listheadobjs->list;
4737   while(ls!=NULL){
4738     if(ls->obj->type==PLANET){
4739       for(i=0;i<GameParametres(GET,GNPLAYERS,0)+1;i++){
4740 	if(GameParametres(GET,GKPLANETS,0)==TRUE ||
4741 	   players[ls->obj->player].team==players[i].team ||
4742 	   (GameParametres(GET,GENEMYKNOWN,0)==TRUE && players[ls->obj->player].team > 1) ){
4743 	  players[i].kplanets=Add2IntList((players[i].kplanets),ls->obj->id);
4744 	}
4745       }
4746     }
4747     ls=ls->next;
4748   }
4749 }
4750