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 <sys/time.h>
27 #include "objects.h"
28 #include "general.h"
29 #include "functions.h"
30 #include "spacecomm.h"
31 #include "ai.h"
32 #include "data.h"
33 #include "sound.h"
34 #include "sectors.h"
35 #include "locales.h"
36 #include "players.h"
37 
38 #define DL (2*RADAR_RANGE)
39 /* #define DL 3000 */
40 
41 struct ObjTree *treeobjs=NULL;
42 struct HeadObjList listheadobjs;       /* List of all objs */
43 extern struct HeadObjList *listheadkplanets;  /* lists of planets known by players */
44 extern struct HeadObjList listheadplayer;     /* list of objects of each player */
45 extern struct TextMessageList listheadtext;
46 extern struct CharListHead gameloglist;       /* list of all game messages */
47 extern struct Window windowgamelog;
48 extern int actual_player,actual_player0;
49 extern int record;
50 extern int gameover;
51 extern int *cell;
52 
53 
54 int g_objid=1;  /* id of the objects */
55 int g_projid=-2; /* id of the projectiles */
56 
57 
58 
NewObj(int type,int stype,int x,int y,float vx,float vy,int weapontype,int engtype,int player,Object * parent,Object * in)59 Object *NewObj(int type,int stype,
60 	       int x,int y,float vx,float vy,
61 	       int weapontype,int engtype,int player,Object *parent,Object *in){
62 
63   /*
64     Create new object
65     return:
66     a pointer to the new object
67     NULL if the are some error or if isnot possible to create it.
68   */
69   Object *obj;
70   Weapon *weapon;
71   struct Player *players;
72   int i;
73 
74   players=GetPlayers();
75   if(player<0||player>GameParametres(GET,GNPLAYERS,0)+1){
76     fprintf(stderr, "ERROR in NewObj(): invalid player id %d\n", player);
77     fprintf(stderr, "\ttype :%d stype: %d\n", type,stype);
78     exit(-1);
79   }
80 
81 
82   obj=malloc(sizeof(Object));
83   MemUsed(MADD,+sizeof(Object));
84   if(obj==NULL){
85     fprintf(stderr,"ERROR in malloc NewObj()\n");
86     exit(-1);
87   }
88 
89   if(type<TRACKPOINT){
90     players[player].status=PLAYERMODIFIED;
91     if(type==SHIP)listheadplayer.update=1;
92   }
93   if(type<=0){
94     fprintf(stderr,"ERROR in NewObj() (type<0) type:%d stype:%d\n",type,stype);
95     exit(-1);
96   }
97 
98   strcpy(obj->name,"x");
99   obj->oriid=0;
100   obj->destid=0;
101   obj->durable=FALSE;
102   obj->visible=TRUE;
103   obj->selected=FALSE;
104   obj->radar=RADAR_RANGE;
105   obj->experience=0;
106   obj->pexperience=0;
107   obj->modified=SENDOBJNEW;
108   obj->ttl=0;
109   obj->level=0;
110   obj->kills=0;
111   obj->ntravels=0;
112   obj->habitat=H_SPACE;
113   obj->mode=NAV;
114   obj->damage=1;
115   obj->x=x;obj->y=y;      /* actual position */
116   obj->x0=x;obj->y0=y;    /* speed in the previous time */
117   obj->vx=vx,obj->vy=vy;  /* actual speed */
118   obj->fx0=obj->fy0=0;    /* force in previous time */
119   obj->fx=obj->fy=0;      /* actual force */
120   obj->a=0;               /* ship angle */
121   obj->ang_v=0;           /* angular speed */
122   obj->ang_a=0;           /* angular aceleration */
123   obj->accel=0;           /* aceleracion */
124   obj->gas=0;             /* combustible */
125   obj->gas_max=0;         /* max. combustible */
126   obj->life=1;            /* life time */
127   obj->shield=0;          /* shield  (0,1) */
128   obj->state=1;           /* ship state (0,1)*/
129 
130   switch(type){
131   case PLANET:
132     obj->id=g_objid;                         /* identifier */
133     break;
134   case PROJECTILE:
135     obj->id=GetNProc()*g_projid-GetProc();   /* identifier */
136     break;
137   default:
138     obj->id=GetNProc()*g_objid+GetProc();    /* identifier */
139     break;
140   }
141 
142 
143   obj->dest_r2=-1;       /* distance2 of the nearest object */
144   obj->parent=parent;    /* id of the creator obj */
145   obj->dest=NULL;        /* pointer to nearest object */
146   obj->in=in;            /* pointer to container object */
147   obj->mass=1;           /* mass */
148   obj->items=0;
149 
150   obj->radio=1;          /* radio */
151   obj->type=type;        /* object type  */
152   obj->subtype=stype;    /* object subsubtype */
153   obj->player=player;
154 
155   obj->ai=0;             /* 0: by keyboard. [1,10] */
156   obj->sw=0;
157   obj->lorder=NULL;
158   obj->actorder.id=-1;
159   obj->trace=FALSE;
160   obj->norder=0;
161 
162   obj->cargo.capacity=0;    /* max. cargo capacity */
163   obj->cargo.mass=0;        /* actual mass cargo */
164   obj->cargo.n=0;           /* number of elements */
165   obj->cargo.hlist=NULL;    /* list to object in cargo */
166 
167   obj->planet=NULL;
168 
169   NewWeapon(&obj->weapon0,weapontype);
170   NewWeapon(&obj->weapon1,CANNON0);
171   NewWeapon(&obj->weapon2,CANNON0);
172 
173   if(obj->type==SHIP && obj->subtype==TOWER){
174     obj->weapon0.projectile.gascost*=8;
175     obj->weapon1.projectile.gascost*=8;
176     obj->weapon2.projectile.gascost*=8;
177   }
178 
179   obj->weapon=&obj->weapon0;
180 
181   NewEngine(&obj->engine,engtype);
182   obj->cdata=NULL;
183 
184   switch(obj->type){
185   case PLANET:
186     obj->pid=obj->id;
187     g_objid++;
188     break;
189   case TRACE:
190     obj->id=-1;
191     obj->modified=SENDOBJNOTSEND;
192     break;
193   case PROJECTILE:
194     obj->pid=obj->id;
195     g_projid--;
196     if(obj->subtype==EXPLOSION){
197       obj->modified=SENDOBJNOTSEND;/* don't send explosion */
198     }
199     break;
200   default:
201     obj->pid=players[obj->player].pid;
202     players[obj->player].pid++;
203     g_objid++;
204     break;
205   }
206   switch(obj->type){
207 
208   case PROJECTILE:
209     obj->radar=0;
210     obj->planet=NULL;/* obj->parent->planet; */
211     obj->in=in;
212 
213     if(obj->parent==NULL){
214       fprintf(stderr,"ERROR (NewObj) parent NULL id: %d\n",obj->id);
215       fprintf(stderr,"\tplayer: %d\n",obj->player);
216       fprintf(stderr,"\ttype: %d\n",obj->type);
217       fprintf(stderr,"\tstype: %d\n",obj->subtype);
218       return(NULL);
219     }
220 
221     obj->habitat=obj->parent->habitat;
222 
223     switch(stype){
224     case SHOT1: /*  standard */
225       obj->state=1;
226       obj->radio=1;
227       weapon=&obj->parent->weapon0;
228       obj->durable=weapon->projectile.durable;
229       obj->life=weapon->projectile.life;
230       obj->damage=weapon->projectile.damage;
231       obj->mass=weapon->projectile.mass;
232       break;
233     case MISSILE:  /* SHOT3 */
234       obj->radar=.5*RADAR_RANGE;
235       obj->state=1;
236       obj->gas_max=100;
237       obj->gas=obj->gas_max;
238       obj->radio=6;
239       obj->level=parent->level;
240       weapon=&obj->parent->weapon1;
241       obj->durable=weapon->projectile.durable;
242       obj->life=weapon->projectile.life;
243       obj->damage=weapon->projectile.damage;
244       obj->mass=weapon->projectile.mass;
245       break;
246     case LASER: /*  shot4 */
247       obj->state=1;
248       obj->gas_max=0;
249       obj->radio=50;
250       weapon=&obj->parent->weapon2;
251       obj->durable=weapon->projectile.durable;
252       obj->life=weapon->projectile.life;
253       obj->damage=weapon->projectile.damage;
254       obj->mass=weapon->projectile.mass;
255       break;
256     case EXPLOSION:
257       obj->durable=TRUE;
258       obj->life=LIFEEXPLOSION;
259       obj->damage=obj->parent->damage/16;
260       obj->parent=NULL;
261       obj->mass=5;
262       break;
263     default:
264       fprintf(stderr,"ERROR (NewOb).Not implemented\n");
265       exit(-1);
266       break;
267     }
268 
269     break;
270   case SHIP:
271     /*     g_print("creando...%d...",GetTime()); */
272     ShipProperties(obj,obj->subtype,in);
273     break;
274 
275   case ASTEROID:
276     obj->durable=TRUE;
277     obj->life=LIFEASTEROID+LIFEASTEROID*rand()/RAND_MAX/2.0;
278     obj->state=10;
279     obj->a=0;
280     obj->ang_v=(2.0*Random(-1)-1.0)/5.0;
281 
282     switch(obj->subtype){
283     case ASTEROID1:
284       obj->mass=100;
285       obj->damage=100;
286       obj->radio=36;
287       break;
288     case ASTEROID2:
289       obj->mass=30;
290       obj->damage=50;
291       obj->radio=18;
292       obj->life/=2;
293       break;
294     case ASTEROID3:
295       obj->mass=10;
296       obj->damage=25;
297       obj->radio=10;
298       obj->life/=4;
299       break;
300     default:
301       fprintf(stderr,"ERROR in NewObj(): asteroid subtype %d no implemented\n",
302 	      obj->subtype);
303       exit(-1);
304       break;
305     }
306     break;
307 
308   case PLANET:
309     obj->mass=(int)((MINPLANETMASS+(MAXPLANETMASS-MINPLANETMASS)*
310 		     Random(-1))/1000)*1000;
311     obj->radio=pow(obj->mass,.333);
312     obj->shield=1.0;
313     obj->state=100;
314     obj->damage=10000;
315     obj->planet=NewPlanet();
316     obj->planet->x=obj->x;
317     obj->planet->y=obj->y;/*-obj->radio*2; */
318     obj->planet->r=obj->radio;
319     obj->planet->gold=(int)((MINPLANETGOLD+((MAXPLANETGOLD-MINPLANETGOLD)*
320 					    Random(-1))*(float)obj->mass/MAXPLANETMASS)*RESOURCEFACTOR);
321     obj->planet->reggold=0.035*((float)obj->mass/MAXPLANETMASS)+0.02+0.02*(Random(-1));
322     obj->planet->A=0;
323     obj->planet->B=0;
324     break;
325   case TRACKPOINT:
326     obj->durable=FALSE;
327     obj->visible=FALSE;
328     obj->damage=0;
329     obj->mass=0;
330     obj->shield=0;
331     break;
332   case TRACE:
333     obj->durable=TRUE;
334     obj->life=LIFETRACE;
335     obj->gas=0;
336     if(obj->parent!=NULL){
337       obj->habitat=obj->parent->habitat;
338       obj->in=in;
339     }
340     break;
341   default:
342     fprintf(stderr,"ERROR (NewOb)\n");
343     exit(-1);
344     break;
345   }
346 
347   obj->cost*=COSTFACTOR;
348 
349   /* data base */
350   if(obj->type==SHIP){  /* HERE TODO SHIP COMPUTER, only ships */
351     obj->cdata=malloc(sizeof(Data));
352     MemUsed(MADD,+sizeof(Data));
353     if(obj->cdata==NULL){
354       fprintf(stderr,"ERROR in malloc NewObj()\n");
355       exit(-1);
356     }
357     for(i=0;i<4;i++){
358       obj->cdata->obj[i]=NULL;
359       obj->cdata->d2[i]=-1;
360       obj->cdata->td2[i]=0;
361     }
362     obj->cdata->mlevel=0;
363     obj->cdata->tmlevel=0;
364     obj->cdata->a=0;
365     obj->cdata->b=0;
366   }
367   return(obj);
368 } /* --Newobj() */
369 
Add2ObjList(struct HeadObjList * lhead,Object * obj)370 int Add2ObjList(struct HeadObjList *lhead,Object *obj){
371   /*
372      add obj to the list lhead
373   */
374 
375   switch(obj->type){
376 
377   case SHIP:
378   case PLANET:
379     return(Add2ObjList_E(lhead,obj));
380     break;
381   case PROJECTILE:
382   case ASTEROID:
383   case ARTEFACT:
384   case TRACKPOINT:
385   case TRACE:
386     return(Add2ObjList_B(lhead,obj));
387     break;
388   default:
389     fprintf(stderr,"ERROR in Ass2ObjList(): type unknown\n");
390     exit(-1);
391     break;
392   }
393 }
394 
395 
Add2ObjList_B(struct HeadObjList * lhead,Object * obj)396 int Add2ObjList_B(struct HeadObjList *lhead,Object *obj){
397   /*
398      add obj at the beginning of the list
399   */
400 
401   struct ObjList *ls;
402 
403   ls=lhead->list;
404 
405   lhead->list=malloc(sizeof(struct ObjList));
406   MemUsed(MADD,+sizeof(struct ObjList));
407   if(lhead->list==NULL){
408     fprintf(stderr,"ERROR in malloc Add2ObjList()\n");
409     exit(-1);
410   }
411 
412   lhead->list->obj=obj;
413   lhead->n++;
414   lhead->list->next=ls;
415   return(0);
416 }
417 
Add2ObjList_E(struct HeadObjList * lhead,Object * obj)418 int Add2ObjList_E(struct HeadObjList *lhead,Object *obj){
419   /*
420      add obj at the end of the list
421   */
422 
423   struct ObjList *ls;
424 
425 
426   if(lhead->list==NULL){    /* first item */
427     return(Add2ObjList_B(lhead,obj));
428   }
429   else{
430     ls=lhead->list;
431     while(ls->next!=NULL){
432       ls=ls->next;
433     }
434 
435     ls->next=malloc(sizeof(struct ObjList));
436     MemUsed(MADD,+sizeof(struct ObjList));
437     if(ls->next==NULL){
438       fprintf(stderr,"ERROR in malloc Add2ObjList()\n");
439       exit(-1);
440     }
441 
442     ls->next->obj=obj;
443     ls->next->next=NULL;
444     lhead->n++;
445   }
446 
447   return(0);
448 }
449 
450 
NewWeapon(Weapon * weapon,int type)451 void NewWeapon(Weapon *weapon,int type){
452   /*
453     Create a weapon of type type
454     returns:
455     a pointer to the new weapon.
456   */
457   weapon->type=type;
458 
459   switch (type){
460   case CANNON0: /* no weapon */
461     weapon->projectile.type=SHOT0;
462     weapon->rate=10000;
463     weapon->nshots=0;
464     weapon->cont1=weapon->rate;
465     weapon->mass=0;
466     weapon->n=0;
467     weapon->max_n=0;
468     break;
469   case CANNON1:
470     weapon->projectile.type=SHOT1;
471     weapon->rate=20;
472     weapon->nshots=1;
473     weapon->cont1=weapon->rate;
474     weapon->mass=0;
475     weapon->n=0;
476     weapon->max_n=50;
477     break;
478   case CANNON2:
479     weapon->projectile.type=SHOT1;
480     weapon->rate=15;
481     weapon->nshots=1;
482     weapon->cont1=weapon->rate;
483     weapon->mass=0;
484     weapon->n=0;
485     weapon->max_n=50;
486     break;
487   case CANNON3:
488     weapon->projectile.type=SHOT1;
489     weapon->rate=12;
490     weapon->nshots=1;
491     weapon->cont1=weapon->rate;
492     weapon->mass=0;
493     weapon->n=0;
494     weapon->max_n=50;
495     break;
496   case CANNON4:
497     weapon->projectile.type=SHOT1;
498     weapon->rate=12;
499     weapon->nshots=2;
500     weapon->cont1=weapon->rate;
501     weapon->mass=0;
502     weapon->n=0;
503     weapon->max_n=50;
504     break;
505   case CANNON5:
506     weapon->projectile.type=SHOT1;
507     weapon->rate=8;
508     weapon->nshots=3;
509     weapon->cont1=weapon->rate;
510     weapon->mass=0;
511     weapon->n=0;
512     weapon->max_n=150;
513     break;
514   case CANNON6:
515     weapon->projectile.type=SHOT1;
516     weapon->rate=8;
517     weapon->nshots=5;
518     weapon->cont1=weapon->rate;
519     weapon->mass=0;
520     weapon->n=0;
521     weapon->max_n=50;
522     break;
523   case CANNON7:
524     weapon->projectile.type=SHOT1;
525     weapon->rate=8;
526     weapon->nshots=6;
527     weapon->cont1=weapon->rate;
528     weapon->mass=0;
529     weapon->n=0;
530     weapon->max_n=50;
531     break;
532   case CANNON8:
533     weapon->projectile.type=MISSILE;/* SHOT3; */
534     weapon->rate=80;
535     weapon->nshots=1;
536     weapon->cont1=weapon->rate;
537     weapon->mass=0;
538     weapon->n=0;
539     weapon->max_n=4;
540     break;
541   case CANNON9: /*  laser */
542     weapon->projectile.type=LASER;/* SHOT4 */
543     weapon->rate=10;
544     weapon->nshots=1;
545     weapon->cont1=weapon->rate;
546     weapon->mass=0;
547     weapon->n=0;
548     weapon->max_n=25;
549 
550     break;
551   default:
552     printf("error (NewWeapon) type: %d\n",type);
553     exit(-1);
554     break;
555   }
556 
557   switch(weapon->projectile.type){
558   case SHOT0: /* no weapon */
559     weapon->projectile.durable=TRUE;
560     weapon->projectile.life=0;
561     weapon->projectile.damage=0;
562     weapon->projectile.max_vel=0;
563     weapon->projectile.mass=0;
564     weapon->projectile.gascost=0;
565     weapon->projectile.unitcost=0;
566     break;
567   case SHOT1:
568     weapon->projectile.durable=TRUE;
569     weapon->projectile.life=LIFESHOT1;
570     weapon->projectile.damage=15*DAMAGEFACTOR;
571     weapon->projectile.max_vel=VELMAX*.75;
572     weapon->projectile.mass=1;
573     weapon->projectile.gascost=6;
574     weapon->projectile.unitcost=.25;
575     break;
576   case SHOT2:
577     weapon->projectile.durable=TRUE;
578     weapon->projectile.life=LIFESHOT2;
579     weapon->projectile.damage=25*DAMAGEFACTOR;
580     weapon->projectile.max_vel=VELMAX*.85;
581     weapon->projectile.mass=2;
582     weapon->projectile.gascost=10;
583     weapon->projectile.unitcost=2;
584     break;
585   case MISSILE:/* SHOT3:  missile  */
586     weapon->projectile.durable=TRUE;
587     weapon->projectile.life=LIFESHOT3;
588     weapon->projectile.damage=75*DAMAGEFACTOR;
589     weapon->projectile.max_vel=VELMAX*.85;
590     weapon->projectile.mass=15;
591     weapon->projectile.gascost=10;
592     weapon->projectile.unitcost=50;
593     break;
594   case LASER:/* SHOT4:  laser */
595     weapon->projectile.durable=TRUE;
596     weapon->projectile.life=LIFESHOT4;
597     weapon->projectile.damage=50*DAMAGEFACTOR;
598     weapon->projectile.max_vel=2*VELMAX;
599     weapon->projectile.mass=0;
600     weapon->projectile.gascost=30;
601     weapon->projectile.unitcost=2;
602     break;
603   default:
604     break;
605 
606   }
607 }
608 
NewEngine(Engine * eng,int type)609 void NewEngine(Engine *eng,int type){
610   /*
611     Create in eng a new engine of type type.
612   */
613 
614   /*
615     typedef struct{
616     int type;
617     int a_max;         max accel
618     int a;             increment of acceleration
619     int v_max;         max speed
620     int v2_max;        max speed 2
621     float ang_a;       increment angular acceleration
622     float ang_a_max;   max angular acceleration
623     float ang_v_max;   max angular velocity
624     float gascost;     cost of gas
625     int mass;          mass of the engine
626     }Engine;
627   */
628 
629 
630   /* default for all engines */
631 
632   eng->type=type;
633   switch (type){
634   case ENGINE0: /*  no engine */
635     eng->a=0;
636     eng->ang_a=0;
637     eng->a_max=0;
638     eng->v_max=0;
639     eng->ang_a=0;
640     eng->ang_a_max=0;
641     eng->ang_v_max=0;
642     eng->gascost=0;
643     eng->mass=0;
644     break;
645   case ENGINE1:
646     eng->a=0;
647     eng->a_max=0;
648     eng->v_max=20;/* VELMAX; 15; */
649     eng->ang_a=0.01;
650     eng->ang_a_max=.2;
651     eng->ang_v_max=0.3;
652     eng->gascost=.05;
653     eng->mass=10;
654     break;
655   case ENGINE2:
656     eng->a=25;
657     eng->a_max=200;
658     eng->v_max=40;/* 40VELMAX; 15; */
659     eng->ang_a=0.001; /* .0004  missile  */
660     eng->ang_a_max=.2;/* .2 */
661     eng->ang_v_max=.3;/* .3 */
662     eng->gascost=.07;
663     eng->mass=20;
664     break;
665   case ENGINE3:
666     eng->a=35;
667     eng->a_max=400;
668     eng->v_max=22;/* VELMAX; 20; */
669     eng->ang_a=0.02;
670     eng->ang_a_max=.2;
671     eng->ang_v_max=0.3;
672     eng->gascost=.07;
673     eng->mass=30;
674     break;
675   case ENGINE4:
676     eng->a=45;
677     eng->a_max=600;
678     eng->v_max=24;/* VELMAX; 25; */
679     eng->ang_a=0.03;
680     eng->ang_a_max=.2;
681     eng->ang_v_max=0.3;
682     eng->gascost=.11;
683     eng->mass=40;
684     break;
685   case ENGINE5:
686     eng->a=55;
687     eng->a_max=1200;
688     eng->v_max=24;/* VELMAX; 30; */
689     eng->ang_a=0.04;
690     eng->ang_a_max=.2;
691     eng->ang_v_max=0.3;
692     eng->gascost=.16;
693     eng->mass=60;
694     break;
695   case ENGINE6:
696     eng->a=55;
697     eng->a_max=1400;
698     eng->v_max=20;/* VELMAX; 30; */
699     eng->ang_a=0.04;
700     eng->ang_a_max=.2;
701     eng->ang_v_max=0.3;
702     eng->gascost=.18;
703     eng->mass=80;
704     break;
705 
706   default:
707     printf("error (NewEngine) type: %d\n",type);
708     exit(-1);
709     break;
710   }
711 
712   eng->v2_max=eng->v_max*eng->v_max;
713 }
714 
715 
CountObjs(struct HeadObjList * lh,int player,int type,int subtype)716 int CountObjs(struct HeadObjList *lh,int player,int type,int subtype){
717   /*
718     Count the number of objects of type type.
719     return this value.
720   */
721 
722   struct ObjList *ls;
723   int n=0;
724 
725   if(player!=-1){
726 
727     if(type==-1){
728       ls=lh->list;
729       while(ls!=NULL){
730 	if(ls->obj->player!=player){ls=ls->next;continue;}
731 	if(ls->obj->state<=0){ls=ls->next;continue;}
732 	n++;
733 	ls=ls->next;
734       }
735       return(n);
736     }
737 
738     if(subtype==-1){
739       ls=lh->list;
740       while(ls!=NULL){
741 	if(ls->obj->player!=player){ls=ls->next;continue;}
742 	if(ls->obj->state<=0){ls=ls->next;continue;}
743 	if(ls->obj->type==type)n++;
744 	ls=ls->next;
745       }
746       return(n);
747     }
748 
749     ls=lh->list;
750     while(ls!=NULL){
751       if(ls->obj->player!=player){ls=ls->next;continue;}
752       if(ls->obj->state<=0){ls=ls->next;continue;}
753       if(ls->obj->type==type && ls->obj->subtype==subtype)n++;
754       ls=ls->next;
755     }
756     return(n);
757   }
758 
759   /* player==-1 count for all players */
760 
761   if(type==-1){
762     ls=lh->list;
763     while(ls!=NULL){
764       if(ls->obj->state<=0){ls=ls->next;continue;}
765       n++;
766       ls=ls->next;
767     }
768     return(n);
769   }
770 
771   if(subtype==-1){
772     ls=lh->list;
773     while(ls!=NULL){
774       if(ls->obj->state<=0){ls=ls->next;continue;}
775       if(ls->obj->type==type)n++;
776       ls=ls->next;
777     }
778     return(n);
779   }
780 
781   ls=lh->list;
782   while(ls!=NULL){
783     if(ls->obj->state<=0){ls=ls->next;continue;}
784     if(ls->obj->type==type && ls->obj->subtype==subtype)n++;
785     ls=ls->next;
786   }
787   return(n);
788 }
789 
790 
CountModObjs(struct HeadObjList * lh,int type)791 int CountModObjs(struct HeadObjList *lh,int type){
792   /*
793     Count the number of modified objects of type type.
794     return this value.
795     note: not used
796   */
797 
798   struct ObjList *ls;
799   int n=0;
800 
801   ls=lh->list;
802   while(ls!=NULL){
803     if(ls->obj->type==type && ls->obj->modified!=SENDOBJUNMOD){
804       n++;
805     }
806     ls=ls->next;
807   }
808   return n;
809 }
810 
811 
RemoveDeadObjs(struct HeadObjList * lhobjs,Object * cv0)812 Object *RemoveDeadObjs(struct HeadObjList *lhobjs , Object *cv0){
813   /*
814      version 0.3
815      Remove all dead objects from the list lhobjs.
816      in net only are remove objects with modified=SENDOBJDEAD
817      in single game remove obj with state<=0
818      return:
819      cv0 if is not removed
820      NULL if cv0 is removed
821   */
822 
823   struct ObjList *ls,*freels;
824   Object *ret;
825   char text[MAXTEXTLEN];
826   int swdead=0;
827   int swx=0;
828   int gnet;
829   struct Player *players;
830 
831   ret=cv0;
832   gnet=GameParametres(GET,GNET,0);
833   players=GetPlayers();
834 
835   ls=lhobjs->list;
836   while(ls!=NULL){
837     freels=NULL;
838     swdead=0;
839     swx=0;
840     if(gnet==TRUE){
841       if(ls->obj->modified==SENDOBJDEAD){swdead=1;}
842     }
843     else{
844       if(ls->obj->state<=0){swdead=1;}
845     }
846 
847     if(ls->obj->type==PROJECTILE && ls->obj->subtype==MISSILE && ls->obj->state<=0){
848       swdead=1;
849     }
850 
851     if(swdead){
852       if(ls->obj->type<TRACKPOINT){
853 	int player=ls->obj->player;
854 	players[player].status=PLAYERMODIFIED;
855 	if(ls->obj->type==SHIP && player==actual_player)listheadplayer.update=1;
856       }
857 
858       freels=ls;
859 
860       switch(ls->obj->type){
861       case ASTEROID:
862 	swx=1;
863 
864 	if(ls->obj->habitat==H_PLANET && ls->obj->sw==0){  /* asteroid crashed */
865 	  ls->obj->in->planet->gold+=100*pow(2,5-ls->obj->subtype);
866 	}
867 
868 	break;
869       case SHIP:
870 	swx=1;
871 	if(ls->obj->mode==SOLD)swx=0;
872 	if(ls->obj->habitat==H_PLANET && swx){
873 
874 	  if(ls->obj->sw!=0){ /* ship killed */
875 	    ls->obj->in->planet->gold+=0.025*GetPrice(ls->obj,0,0,0);
876 	  }
877 	  else{ /* ship crashed */
878 	    float price,factor;
879 	    factor=0.01*ls->obj->state*0.25;
880 	    if(factor<.1)factor=.1;  /* at least an 10 percent*/
881 	    price=factor*GetPrice(ls->obj,0,0,0);
882 	    ls->obj->in->planet->gold+=price;
883 	  }
884 	}
885 
886 	break;
887       case PROJECTILE:
888 	if(ls->obj->subtype==MISSILE){
889 	  swx=1;
890 	}
891 	break;
892       default:
893 	break;
894       }
895 
896       if(swx){
897 	Explosion(lhobjs,cv0,ls->obj,0); /* create new objects, doesnot change ls*/
898 #if SOUND
899 	Play(ls->obj,EXPLOSION0,1);
900 #endif
901       }
902     }
903 
904     if(freels!=NULL){
905       if(freels->obj->type < TRACKPOINT) {
906 	players[freels->obj->player].status=PLAYERMODIFIED;
907       }
908       if(freels->obj->type==SHIP){
909 	switch(freels->obj->subtype){
910 	case EXPLORER:
911 	case FIGHTER:
912 	case QUEEN:
913 	case FREIGHTER:
914 	case TOWER:
915 	case PILOT:
916 	  players[freels->obj->player].ndeaths++;
917 	  break;
918 	case SATELLITE:
919 	case GOODS:
920 	  break;
921 	default:
922 	  fprintf(stderr,"ERROR in RemoveDeadObjs(): Unknown subtype: %d\n",
923 		  freels->obj->subtype);
924 	  exit(-1);
925 	  break;
926 	}
927 	if( freels->obj->player == actual_player && freels->obj->mode!=SOLD){
928 	  snprintf(text,MAXTEXTLEN,"(%c %d) %s",Type(freels->obj),freels->obj->pid,GetLocale(L_SHIPDESTROYED));
929 	  if(!Add2TextMessageList(&listheadtext,text,freels->obj->id,freels->obj->player,0,100,0)){
930 	    Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
931 	  }
932 	}
933       }
934 
935       if(freels->obj->subtype==QUEEN){
936 	int gqueen;
937 	if(freels->obj->player == actual_player){
938 	  printf("%s\n",GetLocale(L_QUEENDESTROYED));
939 	}
940 	gqueen=GameParametres(GET,GQUEEN,0);
941 
942 	if(gqueen==TRUE){
943 	  DestroyAllPlayerObjs(lhobjs,freels->obj->player);
944 	  if(freels->obj->player==actual_player0)gameover=TRUE;
945 	}
946       }
947     }
948 
949     ls=ls->next;
950 
951     if(freels!=NULL){
952       if(freels->obj==cv0)ret=NULL;
953       RemoveObj(lhobjs,freels->obj);
954     }
955   }
956   return(ret);
957 }
958 
959 
RemoveObj(struct HeadObjList * lhobjs,Object * obj2remove)960 void RemoveObj(struct HeadObjList *lhobjs,Object *obj2remove){
961   /*
962      Remove the object obj2remove from system.
963   */
964 
965   struct ObjList *ls,*ls0,*ls1,*freels;
966   Object *obj;
967 
968   if(obj2remove==NULL){
969     fprintf(stderr,"ERROR en removeobj(), obj is NULL\n");
970     return;
971   }
972 
973   freels=NULL;
974   ls=lhobjs->list;
975   ls0=lhobjs->list;
976 
977   while(ls->obj!=obj2remove && ls!=NULL){
978     ls0=ls;
979     ls=ls->next;
980   }
981   if(ls->obj==obj2remove){
982     if(ls != ls0){
983       freels=ls;
984       ls0->next=ls0->next->next;
985       ls=ls->next;
986     }
987     else{ /* its the first element */
988       freels=ls;
989       lhobjs->list=lhobjs->list->next;
990       ls=ls->next;
991       ls0=ls->next;
992     }
993 
994     /* cleaning the memory and references */
995 
996     obj=freels->obj;
997     ls1=lhobjs->list;
998     while(ls1!=NULL){
999       if(ls1->obj->parent==obj){
1000 	ls1->obj->parent=NULL;
1001       }
1002       if(ls1->obj->dest==obj){
1003 	ls1->obj->dest=NULL;
1004       }
1005       ls1=ls1->next;
1006     }
1007 
1008     DelAllOrder(freels->obj);
1009 
1010     free(freels->obj);
1011     freels->obj=NULL;
1012     MemUsed(MADD,-sizeof(Object));
1013     free(freels);
1014 
1015     MemUsed(MADD,-sizeof(struct ObjList));
1016     freels=NULL;
1017     lhobjs->n--;
1018   } /*  if(ls->obj==obj2remove) */
1019   else{
1020     fprintf(stderr,"ERROR en removeobj()\n");
1021     exit(-1);
1022   }
1023 
1024 
1025   return;
1026 }
1027 
CountPlayerShipObjs(struct HeadObjList * lh,int player,int * cont)1028 int CountPlayerShipObjs(struct HeadObjList *lh,int player,int *cont){
1029   /*
1030     Count the number of ship of the player player
1031     return this values in the vector cont.
1032     return the total number of ships.
1033   */
1034 
1035   struct ObjList *ls;
1036   int n=0;
1037 
1038   cont[0]=cont[1]=cont[2]=0;
1039   ls=lh->list;
1040   while(ls!=NULL){
1041     if(ls->obj->player!=player){ls=ls->next;continue;}
1042     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1043     switch(ls->obj->subtype){
1044     case TOWER:
1045       cont[0]++;
1046       break;
1047     case EXPLORER:
1048       cont[1]++;
1049       break;
1050     case FIGHTER:
1051       cont[2]++;
1052       break;
1053     default:
1054       n++;
1055       break;
1056     }
1057     ls=ls->next;
1058   }
1059 
1060   return(n+cont[0]+cont[1]+cont[2]);
1061 }
1062 
1063 
NewPlanet(void)1064 struct Planet *NewPlanet(void){
1065   /*
1066     Create the normailized surface of a planet
1067     returns a pointer to the planet surface
1068   */
1069   int x,y;
1070   int ix,iy;
1071   int x0,l;
1072   struct Planet *planet;
1073   Segment *s;
1074   /* int width=GameParametres(GET,GWIDTH,0); */
1075   int width=LXFACTOR;
1076   int factor=1;
1077   int sw=0;
1078 
1079   planet=malloc(sizeof(struct Planet));
1080   MemUsed(MADD,+sizeof(struct Planet));
1081 
1082   if(planet==NULL){
1083     fprintf(stderr,"ERROR in malloc NewPlanet()\n");
1084     exit(-1);
1085   }
1086 
1087   planet->segment=malloc(sizeof(Segment));
1088   MemUsed(MADD,+sizeof(Segment));
1089   if(planet->segment==NULL){
1090     fprintf(stderr,"ERROR in malloc NewPlanet()2\n");
1091     exit(-1);
1092   }
1093 
1094   /* first segment */
1095   planet->segment->next=NULL;
1096   s=planet->segment;
1097 
1098   x=0;y=0;
1099   y=50*((float)rand()/RAND_MAX);
1100   s->x0=0;
1101   s->y0=50*((float)rand()/RAND_MAX);
1102   s->x1=20*((float)rand()/RAND_MAX);
1103   s->y1=s->y0+40*((float)rand()/RAND_MAX)-20;
1104   if(s->y1<0)s->y1=0;
1105   s->type=TERRAIN;
1106 
1107   x=s->x1;
1108   y=s->y1;
1109 
1110   /* size and position of landing zone */
1111   l=FACTORLANDZONESIZE*((float)rand()/RAND_MAX)+LANDZONEMINSIZE;
1112   if(l>width-x)l=width-x;
1113 
1114   x0=(width-LANDZONEMINX-l)*((float)rand()/RAND_MAX)+LANDZONEMINX;
1115 
1116   if(x0<x)x0=x;
1117 
1118 
1119   while(x < width){
1120 
1121     ix =20*((float)rand()/RAND_MAX);
1122     iy =40*((float)rand()/RAND_MAX)-20;
1123 
1124     if(x>width-100){
1125       if(y-planet->segment->y0 > 100)factor=2;
1126 
1127       if(y>planet->segment->y0){
1128 	iy =-factor*20*((float)rand()/RAND_MAX);
1129       }
1130       else{
1131 	iy =20*((float)rand()/RAND_MAX);
1132       }
1133     }
1134 
1135     if(y+iy<5)continue;
1136     if(y+iy>MAXPLANETHEIGHT)continue;
1137 
1138 
1139     s->next=malloc(sizeof(Segment));
1140     MemUsed(MADD,+sizeof(Segment));
1141     if(s->next==NULL){
1142       fprintf(stderr,"ERROR in malloc NewPlanet()\n");
1143       exit(-1);
1144     }
1145 
1146     s=s->next;
1147     s->next=NULL;
1148     if(x<x0){
1149       s->x0=x;
1150       s->y0=y;
1151       x+=ix;
1152       y+=iy;
1153       if(x>width)x=width;
1154 
1155       s->x1=x;
1156       s->y1=y;
1157       s->type=TERRAIN;
1158     }
1159     else{
1160       s->x0=x;
1161       s->y0=y;
1162       x+=l;
1163       y+=0;
1164       if(x>width)x=width-2;
1165 
1166       s->x1=x;
1167       s->y1=y;
1168       s->type=LANDZONE;
1169       sw++;
1170       x0=width;
1171     }
1172   }
1173 
1174   /* last segment */
1175   s->next=malloc(sizeof(Segment));
1176   MemUsed(MADD,+sizeof(Segment));
1177   if(s->next==NULL){
1178     fprintf(stderr,"ERROR in malloc NewPlanet()2\n");
1179     exit(-1);
1180   }
1181   s->next->x0=s->x1;
1182   s->next->y0=s->y1;
1183   s->next->x1=width;
1184   s->next->y1=planet->segment->y0;
1185   s->next->type=TERRAIN;
1186   s=s->next;
1187   s->next=NULL;
1188 
1189   if(sw==0){
1190     fprintf(stderr,"ERROR in NewPlanet(): planet too small\n");
1191     fprintf(stderr,"\tincrease window geometry\n");
1192     exit(-1);
1193   }
1194   return planet;
1195 }
1196 
1197 
GetLandedZone(Segment * segment,struct Planet * planet)1198 int GetLandedZone(Segment *segment,struct Planet *planet){
1199 
1200   Segment *s;
1201 
1202   if(planet==NULL){
1203     return(0);
1204   }
1205 
1206   s=planet->segment;
1207   while(s!=NULL){
1208     switch(s->type){
1209     case LANDZONE:
1210       segment->x0=s->x0;
1211       segment->x1=s->x1;
1212       segment->y0=s->y0;
1213       segment->y1=s->y1;
1214       segment->type=s->type;
1215       return(0);
1216       break;
1217     default:
1218       break;
1219     }
1220     s=s->next;
1221   }
1222   return(1);
1223 }
1224 
1225 
GetSegment(Segment * segment,struct Planet * planet,float x,float y)1226 int GetSegment(Segment *segment,struct Planet *planet,float x,float y){
1227   /*
1228     returns the segment below the ship
1229   */
1230   Segment *s;
1231 
1232   if(planet==NULL)return(0);
1233   /* if(obj->habitat!=H_PLANET)return(0); */
1234 
1235   s=planet->segment;
1236 
1237   while(s!=NULL){
1238 
1239     if(x > s->x0 && x < s->x1){
1240       segment->x0=s->x0;
1241       segment->x1=s->x1;
1242       segment->y0=s->y0;
1243       segment->y1=s->y1;
1244       segment->type=s->type;
1245       return(0);
1246     }
1247     s=s->next;
1248   }
1249   return(1);
1250 }
1251 
1252 
1253 
Explosion(struct HeadObjList * lh,Object * cv,Object * obj,int type)1254 void Explosion(struct HeadObjList *lh,Object *cv,Object *obj,int type){
1255   /*
1256     Create explosion objects.
1257   */
1258   int i;
1259   float v,vx,vy;
1260   float a;
1261   Object *nobj;
1262   int nexplosion=16;
1263   int swexplosion=0;
1264 
1265   struct timeval time;
1266   static int n=0;
1267   static struct timeval time0;
1268 
1269 
1270   /* max 500 explosion dots by second */
1271   gettimeofday(&time,NULL);
1272   if(time.tv_sec-time0.tv_sec>1 ){
1273     n=0;
1274   }
1275   if(n==0){
1276     time0=time;
1277   }
1278   if(n>500)return;
1279 
1280 
1281   if(obj==NULL)return;
1282   if(cv==NULL)return;
1283 
1284   /* only there are an explosion if you can see it. */
1285 
1286   if(cv->habitat==obj->habitat){
1287     if(cv->habitat==H_PLANET){
1288       if(cv->in==obj->in)swexplosion++;
1289     }
1290     else{
1291       /* check if are close */
1292       if( (cv->x-obj->x)*(cv->x-obj->x)+(cv->y-obj->y)*(cv->y-obj->y)<4000000)
1293 	swexplosion++;
1294     }
1295   }
1296   if(!swexplosion)return;
1297 
1298 
1299   switch (type){
1300   case 0: /* ship destroyed */
1301     nexplosion=(64*obj->mass)/100;
1302     n+=nexplosion;
1303     for(i=0;i<nexplosion;i++){   /* 16 */
1304       a=2.*PI*(Random(-1));
1305       v=1.0*VELMAX*(Random(-1));
1306       vx=v*cos(a) + obj->vx;
1307       vy=v*sin(a) + obj->vy;
1308       nobj=NewObj(PROJECTILE,EXPLOSION,obj->x,obj->y,vx,vy,
1309 		  CANNON0,ENGINE0,obj->player,obj,obj->in);
1310       if(nobj!=NULL){
1311 	nobj->life*=(.25+Random(-1));
1312 	Add2ObjList(lh,nobj);
1313 	nobj->parent=NULL;
1314       }
1315     }
1316     break;
1317   case 1: /* ship hitted */
1318     n+=4;
1319     for(i=0;i<4;i++){
1320       a=2.*PI*(Random(-1));
1321       v=0.5*VELMAX*(Random(-1));
1322       vx=v*cos(a) + obj->vx;
1323       vy=v*sin(a) + obj->vy;
1324       nobj=NewObj(PROJECTILE,EXPLOSION,obj->x,obj->y,vx,vy,
1325 		  CANNON0,ENGINE0,obj->player,obj,obj->in);
1326       if(nobj!=NULL){
1327 	Add2ObjList(lh,nobj);
1328 	nobj->parent=NULL;
1329       }
1330     }
1331     break;
1332   default:
1333     fprintf(stderr,"Error Explosion(): type %d not implemented\n",type);
1334     exit(-1);
1335     break;
1336   }
1337 }
1338 
1339 
CountPlayerPlanets(struct HeadObjList * lh,struct Player * player,int * cont)1340 int CountPlayerPlanets(struct HeadObjList *lh,struct Player *player,int *cont){
1341   /*
1342     version 0.1
1343     Count the known planets of the player player.
1344     return the status of the known planets in the vector cont
1345     returns the total number of known planets.
1346   */
1347   struct ObjList *ls;
1348 
1349   cont[0]=cont[1]=cont[2]=0;
1350   ls=lh->list;
1351   while(ls!=NULL){
1352     if(ls->obj->type==PLANET){
1353       if(IsInIntList((player->kplanets),ls->obj->id)){
1354 
1355 	if(ls->obj->player==0)cont[0]++;	 /* INEXPLORE */
1356 	else{
1357 	  if(ls->obj->player==player->id)cont[1]++; /* ALLY */
1358 	  else{
1359 	    cont[2]++;                             /* ENEMY */
1360 	  }
1361 	}
1362       }
1363     }
1364     ls=ls->next;
1365   }
1366   return (cont[0]+cont[1]+cont[2]);
1367 }
1368 
1369 
CountPlanets(struct HeadObjList * lh,int type)1370 int CountPlanets(struct HeadObjList *lh,int type){
1371   /*
1372     Count the planets of the list
1373   */
1374   struct ObjList *ls;
1375   int n=0;
1376 
1377   printf("CountPlanets():\n");
1378 
1379   ls=lh->list;
1380   while(ls!=NULL){
1381     printf("%p\n",(void *)ls);
1382     n++;
1383     ls=ls->next;
1384   }
1385   return n;
1386 }
1387 
CountShipsInPlanet(struct HeadObjList * lh,int objid,int player,int type,int stype,int max)1388 int CountShipsInPlanet(struct HeadObjList *lh,int objid,int player,int type,int stype,int max){
1389   /*
1390     Count the number of ships inside the object objid of type and subtype
1391     of the player player.
1392     if type or subtype are equal to -1 count all.
1393     if lh is NULL use the all objects list.
1394     Returns the number of ships.
1395   */
1396 
1397   struct ObjList *ls;
1398   int n=0;
1399 
1400   if(lh!=NULL){
1401     ls=lh->list;
1402   }
1403   else{
1404     ls=listheadobjs.list;
1405   }
1406   while(ls!=NULL){
1407     if(type!=-1){
1408       if(ls->obj->state<=0){ls=ls->next;continue;}
1409       if(ls->obj->type!=type){ls=ls->next;continue;}
1410       if(stype!=-1){
1411 	if(ls->obj->subtype!=stype){ls=ls->next;continue;}
1412       }
1413     }
1414     if(ls->obj->player!=player){ls=ls->next;continue;}
1415 
1416     if(ls->obj->in!=NULL){
1417       if(ls->obj->in->id==objid)n++;
1418       if(max>0 && n>=max)return(max);
1419     }
1420     else{ /* Count ships in space */
1421       if(objid==0)n++;
1422       if(max>0 && n>=max)return(max);
1423     }
1424 
1425     ls=ls->next;
1426   }
1427   return(n);
1428 }
1429 
1430 
CountShips(struct HeadObjList * lh,int * planet,int * ships)1431 int CountShips(struct HeadObjList *lh,int *planet,int *ships){
1432   /*
1433     Count the number of ships in planet
1434     Returns the number of ships.
1435   */
1436 
1437   struct ObjList *ls;
1438   int n=0;
1439   int i;
1440 
1441   for(i=0;i<MAXNUMPLANETS+1;i++){
1442     planet[i]=0;
1443   }
1444   for(i=0;i<SHIP_S_MAX+1;i++){
1445     ships[i]=0;
1446   }
1447   ls=lh->list;
1448   while(ls!=NULL){
1449 
1450     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1451     if(ls->obj->state<=0){ls=ls->next;continue;}
1452     if(ls->obj->habitat==H_PLANET){
1453       if(ls->obj->in!=NULL){
1454 	if(ls->obj->in->id < 1 ||ls->obj->in->id > MAXNUMPLANETS){
1455 	  fprintf(stderr,"ERROR: wrong planet id in CountShips(): %d\n",
1456 		  ls->obj->in->id);
1457 	  ls=ls->next;continue;
1458 	}
1459       }
1460       else{
1461 	fprintf(stderr,"ERROR in CountShips(): in NULL id: %d\n",ls->obj->id);
1462 	ls=ls->next;continue;
1463       }
1464       planet[ls->obj->in->id - 1]++;
1465     }
1466     else{
1467       planet[MAXNUMPLANETS]++;
1468     }
1469     ships[ls->obj->subtype]++;
1470     n++;
1471     ls=ls->next;
1472   }
1473   return(n);
1474 }
1475 
1476 
CopyObject(Object * nobj,Object * obj)1477 int CopyObject(Object *nobj,Object *obj){
1478 
1479   memcpy(nobj,obj,sizeof(Object));
1480   return (sizeof(Object));
1481 }
1482 
SelectObj(struct HeadObjList * lh,int id)1483 Object *SelectObj(struct HeadObjList *lh,int id){
1484   /*
1485      returns:
1486      a pointer to the Object with the id id,
1487      NULL if not exist.
1488   */
1489   struct ObjList *ls;
1490 
1491   if(id==0)return(NULL);
1492 
1493   ls=lh->list;
1494   while(ls!=NULL){
1495     if(ls->obj->id==id)
1496       return(ls->obj);
1497     ls=ls->next;
1498   }
1499   return(NULL);
1500 }
1501 
1502 
SelectpObj(struct HeadObjList * lh,int pid,int player)1503 Object *SelectpObj(struct HeadObjList *lh,int pid,int player){
1504   /*
1505      returns:
1506      a pointer to the Object with the id id,
1507      NULL if not exist.
1508   */
1509   struct ObjList *ls;
1510 
1511   if(pid==0)return(NULL);
1512 
1513   ls=lh->list;
1514   while(ls!=NULL){
1515     if(ls->obj->type!=PLANET && ls->obj->player != player){ls=ls->next;continue;}
1516     if(ls->obj->pid==pid){
1517       return(ls->obj);
1518     }
1519     ls=ls->next;
1520   }
1521   return(NULL);
1522 }
1523 
1524 
SelectObjInObj(struct HeadObjList * lh,int id,int player)1525 Object *SelectObjInObj(struct HeadObjList *lh,int id,int player){
1526   /*
1527      returns:
1528      a pointer to the first Object which is inside of id
1529      NULL if not exist.
1530   */
1531   struct ObjList *ls;
1532 
1533   if(id==0)return(NULL);
1534 
1535 
1536   ls=lh->list;
1537   while(ls!=NULL){
1538     if(ls->obj->in == NULL){ls=ls->next;continue;}
1539     if(ls->obj->in->id != id){ls=ls->next;continue;}
1540     if(ls->obj->id == id){ls=ls->next;continue;}
1541     if(ls->obj->player != player){ls=ls->next;continue;}
1542     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1543 
1544     if(ls->obj->state >= 0){
1545       return(ls->obj);
1546     }
1547     ls=ls->next;
1548   }
1549   return(NULL);
1550 }
1551 
SelectpObjInObj(struct HeadObjList * lh,int pid,int player)1552 Object *SelectpObjInObj(struct HeadObjList *lh,int pid,int player){
1553   /*
1554      returns:
1555      a pointer to the first Object which is inside of id
1556      NULL if not exist.
1557   */
1558   struct ObjList *ls;
1559 
1560   if(pid==0)return(NULL);
1561   if(pid<=GameParametres(GET,GNPLANETS,0))return(SelectObjInObj(lh,pid,player));
1562 
1563   ls=lh->list;
1564   while(ls!=NULL){
1565     if(ls->obj->in == NULL){ls=ls->next;continue;}
1566     if(ls->obj->in->pid != pid){ls=ls->next;continue;}
1567     if(ls->obj->pid == pid){ls=ls->next;continue;}
1568     if(ls->obj->player != player){ls=ls->next;continue;}
1569     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1570 
1571     if(ls->obj->state >= 0){
1572       return(ls->obj);
1573     }
1574     ls=ls->next;
1575   }
1576   return(NULL);
1577 }
1578 
1579 
SelectOneShip(struct HeadObjList * lh,Space reg,Object * cv,int ctrl)1580 Object *SelectOneShip(struct HeadObjList *lh,Space reg,Object *cv,int ctrl){
1581   /*
1582     select the nearest obj to mouse pointer
1583     return the obj selected
1584   */
1585 
1586   struct ObjList *ls;
1587   Rectangle rect;
1588   float x,y;
1589   int sw1=0; /* first selected */
1590   Object *ret;
1591   float d2,d2min=10000;
1592 
1593   if(lh==NULL)return(NULL);
1594 
1595   ret=NULL;
1596 
1597   rect.x=reg.rect.x;
1598   rect.y=reg.rect.y;
1599 
1600   ls=lh->list;
1601   while(ls!=NULL){
1602     if(ls->obj->player!=actual_player){ls=ls->next;continue;}
1603     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1604     if(ls->obj->habitat!=H_SPACE && ls->obj->habitat!=H_PLANET){ls=ls->next;continue;}
1605 
1606 
1607     if(ctrl==FALSE)ls->obj->selected=FALSE;
1608 
1609     if(reg.habitat>0){  /* select a region inside a planet */
1610       if(ls->obj->habitat==H_SPACE){ls=ls->next;continue;}
1611       if(reg.habitat!=ls->obj->in->id){ls=ls->next;continue;}
1612       d2=(rect.x-ls->obj->x)*(rect.x-ls->obj->x)+(rect.y-ls->obj->y)*(rect.y-ls->obj->y);
1613     }
1614     else{ /* select a region in map view */
1615       if(ls->obj->habitat==H_PLANET){
1616 	x=ls->obj->in->x;
1617 	y=ls->obj->in->y;
1618       }
1619       else{
1620 	x=ls->obj->x;
1621 	y=ls->obj->y;
1622       }
1623       d2=(rect.x-x)*(rect.x-x)+(rect.y-y)*(rect.y-y);
1624     }
1625 
1626     if(d2<d2min||sw1==0){
1627       ret=ls->obj;
1628       d2min=d2;
1629       sw1++;
1630     }
1631     ls=ls->next;
1632   }
1633   return(ret);
1634 }
1635 
1636 
IsInRegion(Object * obj,Space region)1637 int IsInRegion(Object *obj,Space region){
1638   Point a,b;
1639   Rectangle rect;
1640   rect.x=region.rect.x;
1641   rect.y=region.rect.y;
1642   rect.width=region.rect.width;
1643   rect.height=region.rect.height;
1644 
1645   if(region.rect.width<0){
1646     rect.x+=region.rect.width;
1647     rect.width*=-1;
1648   }
1649 
1650   if(region.rect.height<0){
1651     rect.y+=region.rect.height;
1652     rect.height*=-1;
1653   }
1654   if(region.habitat>0){ /* select a region inside a planet */
1655     a.x=rect.x;
1656     a.y=rect.y-rect.height;
1657     b.x=rect.x+rect.width;
1658     b.y=rect.y;
1659   }
1660   else{ /* select a region in map view */
1661     a.x=rect.x;
1662     a.y=rect.y;
1663     b.x=rect.x+rect.width;
1664     b.y=rect.y+rect.height;
1665   }
1666   if(obj->x < a.x || obj->x > b.x || obj->y < a.y || obj->y > b.y ){
1667     /*reset */
1668 
1669     return(TRUE);
1670   }
1671   return(FALSE);
1672 
1673 }
1674 
1675 
Distance2NearestShip(struct HeadObjList * lh,int player,int x,int y)1676 float Distance2NearestShip(struct HeadObjList *lh,int player,int x,int y){
1677   /*
1678 
1679     Return the distance2 of the nearest SHIP to the point x,y.  x,y
1680     are space coordinates, no planet. The nearest obj can be in free
1681     space or inside a planet. In this last case the coordinates are
1682     the planet ones.
1683     if player = -1 match all players
1684   */
1685 
1686   float d2;
1687   struct ObjList *ls;
1688   float rx,ry,r2;
1689   float x1,y1;
1690   Object *obj=NULL;
1691   int sw=0;
1692 
1693   /*   if(!PLANETSKNOWN) */
1694   /*     if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1695 
1696   d2=-1;
1697 
1698   ls=lh->list;
1699   while(ls!=NULL){
1700     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1701     if(ls->obj->player!=player && player !=-1){ls=ls->next;continue;}
1702 
1703     obj=ls->obj;
1704 
1705     switch(obj->habitat){
1706     case H_PLANET:
1707       x1=obj->in->x;
1708       y1=obj->in->y;
1709       break;
1710     case H_SPACE:
1711       x1=obj->x;
1712       y1=obj->y;
1713       break;
1714     default:
1715       ls=ls->next;continue;
1716       break;
1717     }
1718 
1719     rx=x - x1;
1720     ry=y - y1;
1721     r2=rx*rx+ry*ry;
1722 
1723     if(sw==0|| r2<d2){
1724       d2=r2;
1725       sw++;
1726     }
1727     ls=ls->next;
1728   }
1729   return(d2);
1730 }
1731 
1732 
Distance2NearestShipLessThan(struct HeadObjList * lh,int player,int x,int y,float dmin2)1733 float Distance2NearestShipLessThan(struct HeadObjList *lh,int player,int x,int y,float dmin2){
1734   /*
1735 
1736     returns 1 if the distance2 to nearest SHIP to the point x,y is less than dmin2.
1737     returns 0 if is greater.
1738     x,y are space coordinates, no planet. The nearest obj can be in free
1739     space or inside a planet. In this last case the coordinates are
1740     the planet ones.
1741     if player = -1 match all players
1742 
1743   */
1744 
1745   float d2;
1746   struct ObjList *ls;
1747   float rx,ry,r2;
1748   float x1,y1;
1749   Object *obj=NULL;
1750   int sw=0;
1751 
1752   /*   if(!PLANETSKNOWN) */
1753   /*     if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1754 
1755   d2=-1;
1756 
1757   ls=lh->list;
1758   while(ls!=NULL){
1759     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1760     if(ls->obj->player!=player && player !=-1){ls=ls->next;continue;}
1761 
1762     obj=ls->obj;
1763 
1764     switch(obj->habitat){
1765     case H_PLANET:
1766       x1=obj->in->x;
1767       y1=obj->in->y;
1768       break;
1769     case H_SPACE:
1770       x1=obj->x;
1771       y1=obj->y;
1772       break;
1773     default:
1774       ls=ls->next;continue;
1775       break;
1776     }
1777 
1778     rx=x - x1;
1779     ry=y - y1;
1780     r2=rx*rx+ry*ry;
1781 
1782     if(sw==0|| r2<d2){
1783       d2=r2;
1784       if(d2<dmin2)return(1);
1785       sw++;
1786     }
1787     ls=ls->next;
1788   }
1789   return(0);
1790 }
1791 
ObjNearThan(struct HeadObjList * lh,int player,int x,int y,float d2)1792 Object *ObjNearThan(struct HeadObjList *lh,int player,int x,int y,float d2){
1793   /*
1794     returns:
1795     the nearest obj planet id of first  planet closer than dmin2.
1796     0 if there are no planets at that distance.
1797   */
1798 
1799   struct ObjList *ls;
1800   float rx,ry;
1801   float dmin2;
1802   Object *obj=NULL;
1803   Object *retobj=NULL;
1804   struct Player *players;
1805 
1806   players=GetPlayers();
1807   dmin2=d2;
1808 
1809   ls=lh->list;
1810   while(ls!=NULL){
1811     if(ls->obj->player!=player && ls->obj->type!=PLANET){ls=ls->next;continue;}
1812     if(ls->obj->habitat!=H_SPACE){ls=ls->next;continue;}
1813     if(ls->obj->type!=PLANET && ls->obj->type!=SHIP){ls=ls->next;continue;}
1814 
1815     if(ls->obj->type==PLANET){
1816       if(!PLANETSKNOWN){
1817 	if(IsInIntList((players[player].kplanets),ls->obj->id)==0){
1818 	  ls=ls->next;continue;
1819 	}
1820       }
1821     }
1822     obj=ls->obj;
1823 
1824     rx=x - obj->x;
1825     ry=y - obj->y;
1826 
1827     if(rx*rx+ry*ry<dmin2){
1828       dmin2=rx*rx+ry*ry;
1829       retobj=obj;
1830     }
1831     ls=ls->next;
1832   }
1833   return(retobj);
1834 }
1835 
1836 
1837 
NearestObj(struct HeadObjList * lh,Object * obj,int type,int stype,int pstate,float * d2)1838 Object *NearestObj(struct HeadObjList *lh,Object *obj,int type,int stype,int pstate,float *d2){
1839   /*
1840     Return a pointer to the nearest object to obj in state pstate.
1841     pstate can be own, ally, enemy or inexplore.
1842     in d2 returns the distance^2.
1843   */
1844 
1845   struct ObjList *ls;
1846   float rx,ry,r2;
1847   float x0,y0,x1,y1;
1848   float r2min;
1849   int player;
1850   Object *robj=NULL;
1851   Object *obj2=NULL;
1852   int pheight2=0;
1853   int swp=0;
1854   int sw=0;
1855   struct Player *players;
1856 
1857   players=GetPlayers();
1858 
1859 
1860   /*   if(!PLANETSKNOWN) */
1861   /*     if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1862 
1863   *d2=-1;
1864   if(obj==NULL)return(NULL);
1865 
1866   player=obj->player;
1867   r2min=-1;
1868   obj->dest_r2=-1;
1869 
1870   if(obj->habitat==H_PLANET){
1871     pheight2=(0.7)*GameParametres(GET,GHEIGHT,0);
1872     pheight2*=pheight2;
1873   }
1874 
1875   ls=lh->list;
1876   while(ls!=NULL){
1877     obj2=ls->obj;
1878     if(obj2->type!=type){ls=ls->next;continue;}
1879 
1880     if(stype!=SHIP0){
1881       if(obj2->subtype!=stype){ls=ls->next;continue;}
1882     }
1883 
1884     switch(obj2->type){
1885     case SHIP:
1886       if(obj2->ttl<MINTTL){ls=ls->next;continue;}
1887       if(obj2->state<=0){
1888 	ls=ls->next;continue;
1889       }
1890 
1891       if(obj2->subtype==PILOT){
1892 	ls=ls->next;continue; /* ignoring pilots */
1893 	if(obj2->mode==LANDED){ls=ls->next;continue;}
1894 	if(obj2->habitat==H_SHIP){ls=ls->next;continue;}
1895       }
1896       break;
1897     case PLANET:
1898       if(IsInIntList((players[obj->player].kplanets),obj2->id)==0){
1899 	ls=ls->next;continue;
1900       }
1901       break;
1902     default:
1903       break;
1904     }
1905 
1906     sw=0;
1907     if(pstate & PENEMY){
1908       if((players[obj2->player].team!=players[player].team) &&  obj2->player!=0) {sw=1;}
1909     }
1910     if(pstate & PINEXPLORE){
1911       if(obj2->player==0){sw=1;}
1912     }
1913     if(pstate & PALLY){
1914       if(players[obj2->player].team==players[player].team){sw=1;}
1915     }
1916     if(!sw){ls=ls->next;continue;}
1917 
1918     if(obj2==obj){ls=ls->next;continue;}
1919 
1920     if(obj2->habitat==H_PLANET){
1921       if(obj->habitat!=H_PLANET){ls=ls->next;continue;}
1922 
1923       if(obj->habitat==H_PLANET){
1924 	if(obj->in!=obj2->in){ls=ls->next;continue;}
1925       }
1926     }
1927 
1928     x0=obj->x;
1929     y0=obj->y;
1930 
1931     swp=0;
1932     if(obj->habitat==H_PLANET && obj2->habitat!=H_PLANET){
1933       x0=obj->in->x;
1934       y0=obj->in->y;
1935       swp=1;
1936     }
1937     x1=obj2->x;
1938     y1=obj2->y;
1939 
1940     rx=x0 - x1;
1941     ry=y0 - y1;
1942     r2=rx*rx+ry*ry;
1943     if(swp)r2+=pheight2;
1944 
1945     if(robj==NULL || r2<r2min){
1946       r2min=r2;
1947       *d2=r2;
1948       obj->dest_r2=r2;
1949       robj=obj2;
1950     }
1951     ls=ls->next;
1952   }
1953   obj->dest=robj;
1954   return(robj);
1955 }
1956 
1957 
NearestObjAll(struct HeadObjList * lhc,Object * obj,struct NearObject * objs)1958 void NearestObjAll(struct HeadObjList *lhc,Object *obj,struct NearObject *objs){
1959   /*
1960     version 03
1961     look for closer object to obj in the list lhc.
1962 
1963     In vector objs save the next information, (in order):
1964     the nearest enemy ship or ASTEROID
1965     the nearest known enemy planet
1966     the nearest known inexplore planet
1967     the nearest known ally planet
1968   */
1969 
1970   struct ObjList *ls;
1971   Object *obj2;
1972   int i,j;
1973   float rx,ry,r2;
1974   float x0,y0;
1975   int player;
1976   float radar2;
1977   int nlist;
1978   int pheight2=0;
1979   int swp=0;
1980   struct Player *players;
1981 
1982 
1983 
1984   for(i=0;i<4;i++){
1985     objs[i].obj=NULL;
1986     objs[i].d2=-1;
1987   }
1988 
1989   if(obj==NULL)return;
1990   if(obj->habitat!=H_SPACE && obj->habitat!=H_PLANET)return;
1991 
1992   players=GetPlayers();
1993   player=obj->player;
1994   radar2=obj->radar*obj->radar;
1995 
1996   if(obj->habitat==H_PLANET){
1997     pheight2=(0.7)*GameParametres(GET,GHEIGHT,0);
1998     pheight2*=pheight2;
1999   }
2000 
2001   /* among free space and planets */
2002   nlist=3;
2003   if(obj->habitat==H_SPACE){
2004     nlist=2;
2005   }
2006   for(j=0;j<nlist;j++){
2007     switch(j){
2008     case 0:
2009       ls=listheadkplanets[obj->player].list;
2010       break;
2011     case 1:
2012       ls=lhc[0].list;
2013       break;
2014     default:
2015       ls=lhc[(obj->in->id)].list;
2016       break;
2017     }
2018 
2019     while(ls!=NULL){
2020       obj2=ls->obj;
2021 
2022       switch(obj2->type){
2023       case SHIP:
2024       case ASTEROID:
2025 	if(obj2->player==obj->player){
2026 	  ls=ls->next;continue;
2027 	}
2028 	if(obj2->ttl<MINTTL){ls=ls->next;continue;}
2029 
2030 	if(obj2->state<=0){
2031 	  ls=ls->next;continue;
2032 	}
2033 
2034 	if(obj->habitat==H_PLANET && obj2->habitat==H_PLANET){
2035 	  if(obj->in != obj2->in){
2036 	    /* unupdated list */
2037 
2038 	    ls=ls->next;continue;
2039 	  }
2040 	}
2041 	/* ignore pilots */
2042 	if(obj2->type==SHIP && obj2->subtype==PILOT){ls=ls->next;continue;}
2043 
2044 	break;
2045       case PLANET:
2046 	if(j!=0){ls=ls->next;continue;}
2047 	break;
2048       default:
2049 	ls=ls->next;continue;
2050       }
2051       swp=0;
2052       if(obj->habitat==H_PLANET && obj2->habitat!=H_PLANET){
2053 	x0=obj->in->x;
2054 	y0=obj->in->y;
2055 	swp=1;
2056       }
2057       else{
2058 	x0=obj->x;
2059 	y0=obj->y;
2060       }
2061 
2062       rx=x0 - obj2->x;
2063       ry=y0 - obj2->y;
2064       r2=rx*rx+ry*ry;
2065       if(swp)r2+=pheight2;
2066 
2067       switch(obj2->type){
2068       case SHIP:
2069 	if(r2>radar2){ls=ls->next;continue;}
2070       case ASTEROID:
2071 	if(r2>25*radar2){ls=ls->next;continue;}
2072 
2073 	if( players[obj2->player].team!=players[player].team ){ /* Enemy Ship */
2074 	  if(objs[0].obj==NULL){ /* first element */
2075 	    objs[0].obj=obj2;
2076 	    objs[0].d2=r2;
2077 	  }
2078 	  else{
2079 	    if(r2<objs[0].d2){
2080 	      objs[0].obj=obj2;
2081 	      objs[0].d2=r2;
2082 	    }
2083 	  }
2084 	}
2085 	break;
2086 
2087       case PLANET:
2088 	if(obj2->player!=0 && (players[obj2->player].team != players[player].team )){ /* Enemy Planet */
2089 	  if(objs[1].obj==NULL){
2090 	    objs[1].obj=obj2;
2091 	    objs[1].d2=r2;
2092 	  }
2093 	  else{
2094 	    if(r2<objs[1].d2){
2095 	      objs[1].obj=obj2;
2096 	      objs[1].d2=r2;
2097 	    }
2098 	  }
2099 	  break;
2100 	}
2101 
2102 	if((obj2->player==0) ){ /* Inexplore Planet */
2103 	  if(objs[2].obj==NULL){
2104 	    objs[2].obj=obj2;
2105 	    objs[2].d2=r2;
2106 	  }
2107 	  else{
2108 	    if(r2<objs[2].d2){
2109 	      objs[2].obj=obj2;
2110 	      objs[2].d2=r2;
2111 	    }
2112 	  }
2113 	  break;
2114 	}
2115 
2116 	if((players[obj2->player].team==players[player].team) ){ /* Ally Planet */
2117 	  if(objs[3].obj==NULL){
2118 	    objs[3].obj=obj2;
2119 	    objs[3].d2=r2;
2120 	  }
2121 	  else{
2122 	    if(r2<objs[3].d2){
2123 	      objs[3].obj=obj2;
2124 	      objs[3].d2=r2;
2125 	    }
2126 	  }
2127 	  break;
2128 	}
2129 	break;
2130       default:
2131 	fprintf(stderr,"ERROR in NearestObjAll\n");
2132 	exit(-1);
2133 	break;
2134       }
2135       ls=ls->next;
2136     }
2137   }
2138   return;
2139 }
2140 
2141 
DestroyAllObj(struct HeadObjList * lh)2142 void DestroyAllObj(struct HeadObjList *lh){
2143   struct ObjList *ls,*ls0;
2144 
2145   ls=lh->list;
2146 
2147   while(ls!=NULL){
2148     DestroyObj(ls->obj);
2149     ls->obj=NULL;
2150     ls0=ls;
2151     ls=ls->next;
2152     free(ls0);
2153     ls0=NULL;
2154     MemUsed(MADD,-sizeof(struct ObjList));
2155     lh->n--;
2156   }
2157 }
2158 
2159 
DestroyAllPlayerObjs(struct HeadObjList * lh,int player)2160 void DestroyAllPlayerObjs(struct HeadObjList *lh,int player){
2161   struct ObjList *ls;
2162 
2163   ls=lh->list;
2164 
2165   while(ls!=NULL){
2166     if(ls->obj->player!=player){ls=ls->next;continue;}
2167     if(ls->obj->type==SHIP){
2168       ls->obj->state=0;
2169     }
2170     ls=ls->next;
2171   }
2172 }
2173 
2174 
DestroyObj(Object * obj)2175 void DestroyObj(Object *obj){
2176   /*
2177     Use only when load a game
2178   */
2179   if(obj==NULL)return;
2180   DelAllOrder(obj);
2181   CargoDestroy(obj);
2182   if(obj->type==PLANET){
2183     DestroyPlanet(obj->planet);
2184   }
2185   if(obj->cdata!=NULL){  /* HERE COMPUTER, only ships */
2186     if(obj->type!=SHIP){ /* checking  */
2187       fprintf(stderr,"ERROR DestroyObj(): obj is not a SHIP\n");
2188       exit(-1);
2189     }
2190     free(obj->cdata);
2191     obj->cdata=NULL;
2192     MemUsed(MADD,-sizeof(Data));
2193 
2194   }
2195   free(obj);
2196   obj=NULL;
2197   MemUsed(MADD,-sizeof(Object));
2198 }
2199 
DestroyPlanet(struct Planet * planet)2200 void DestroyPlanet(struct Planet *planet){
2201   Segment *s,*s0;
2202 
2203   s=planet->segment;
2204   while(s!=NULL){
2205     s0=s;
2206     s=s->next;
2207     free(s0);
2208     s0=NULL;
2209     MemUsed(MADD,-sizeof(Segment));
2210 
2211   }
2212   free(planet);
2213   planet=NULL;
2214   MemUsed(MADD,-sizeof(struct Planet));
2215 
2216 }
2217 
CopyPlanet2Buf(struct Planet * planet,char * buf)2218 int CopyPlanet2Buf(struct Planet *planet,char *buf){
2219   struct Planet *planet2;
2220   Segment *s,*s2;
2221   int offset=0;
2222 
2223   planet2=(struct Planet *)buf;
2224 
2225   planet2->x=planet->x;
2226   planet2->y=planet->y;
2227   planet2->r=planet->r;
2228   planet2->gold=planet->gold;
2229   planet2->segment=planet->segment;
2230   offset=sizeof(struct Planet);
2231 
2232   s=planet->segment;
2233 
2234   s2=(Segment *)(buf+offset);
2235 
2236 
2237   while(s!=NULL){
2238 
2239     s2->x0=s->x0;
2240     s2->y0=s->y0;
2241     s2->x1=s->x1;
2242     s2->y1=s->y1;
2243     s2->type=s->type;
2244     s2->next=s->next;
2245 
2246     offset+=sizeof(Segment);
2247     s2++;
2248     s=s->next;
2249   }
2250   return(offset);
2251 }
2252 
2253 
CopyBuf2Planet(char * buf,struct Planet * planet)2254 int CopyBuf2Planet(char *buf,struct Planet *planet){
2255   struct Planet *planet2;
2256   Segment *s,*s2;
2257   int offset=0;
2258 
2259   planet=malloc(sizeof(struct Planet));
2260   MemUsed(MADD,+sizeof(struct Planet));
2261   if(planet==NULL){
2262     fprintf(stderr,"ERROR in malloc CopyBuf2Planet()\n");
2263     exit(-1);
2264   }
2265 
2266   planet2=(struct Planet *)buf;
2267 
2268   planet->x=planet2->x;
2269   planet->y=planet2->y;
2270   planet->r=planet2->r;
2271   planet->gold=planet2->gold;
2272   planet->segment=NULL;
2273 
2274   offset=sizeof(struct Planet);
2275 
2276   s=malloc(sizeof(Segment));
2277   MemUsed(MADD,+sizeof(Segment));
2278   if(s==NULL){
2279     fprintf(stderr,"ERROR in malloc CopyBuf2Planet()2\n");
2280     exit(-1);
2281   }
2282   s->next=NULL;
2283   planet->segment=s;
2284 
2285   s2=(Segment *)(buf+offset);
2286 
2287   s->x0=s2->x0;
2288   s->y0=s2->y0;
2289   s->x1=s2->x1;
2290   s->y1=s2->y1;
2291   s->type=s2->type;
2292   s->next=NULL;
2293 
2294 
2295   while(s2->next!=NULL){
2296     s->next=malloc(sizeof(Segment));
2297     MemUsed(MADD,+sizeof(Segment));
2298     if(s->next==NULL){
2299       fprintf(stderr,"ERROR in malloc CopyBuf2Planet()2\n");
2300       exit(-1);
2301     }
2302     s->next->next=NULL;
2303     s=s->next;
2304     s2++;
2305     offset+=sizeof(Segment);
2306 
2307     s->x0=s2->x0;
2308     s->y0=s2->y0;
2309     s->x1=s2->x1;
2310     s->y1=s2->y1;
2311     s->type=s2->type;
2312   }
2313   return(0);
2314 }
2315 
2316 
UpdateSectors(struct HeadObjList lh)2317 int UpdateSectors(struct HeadObjList lh){
2318   /*
2319     add the actual sector to his own player list
2320 
2321   */
2322 
2323   struct ObjList *ls;
2324   int n=0;
2325   int i,j,k;
2326   int i2,k2,is;
2327   int time;
2328   int proc=0;
2329   float maxx,maxy;
2330   struct Player *players;
2331 
2332   players=GetPlayers();
2333   proc=GetProc();
2334   time=GetTime();
2335 
2336   maxx=0.55*GameParametres(GET,GULX,0);
2337   maxy=0.55*GameParametres(GET,GULY,0);
2338 
2339   ls=lh.list;
2340 
2341   while(ls!=NULL){
2342     if((ls->obj->id + time)%20){ls=ls->next;continue;}
2343     if(proc==players[ls->obj->player].proc){
2344       if(ls->obj->type==SHIP && ls->obj->habitat==H_SPACE){
2345 
2346 	if(ls->obj->x>maxx || ls->obj->x<-maxx || ls->obj->y>maxy || ls->obj->y<-maxy){
2347 	  ls=ls->next;continue;
2348 	}
2349 
2350 	switch(ls->obj->subtype){
2351 	case EXPLORER:
2352 	case SATELLITE:
2353 	case QUEEN:
2354 	  k=ls->obj->radar/SECTORSIZE;
2355 	  k2=k*k;
2356 	  for(i=-k;i<k+1;i++){
2357 	    i2=i*i;
2358 	    is=i*SECTORSIZE;
2359 	    for(j=-k;j<k+1;j++){
2360 	      if(i2+j*j<=k2){
2361 		Add2IntIList(&(players[ls->obj->player].ksectors),
2362 			     Quadrant(ls->obj->x+is,ls->obj->y+j*SECTORSIZE));
2363 	      }
2364 	    }
2365 	  }
2366 	  break;
2367 	default:
2368 	  Add2IntIList(&(players[ls->obj->player].ksectors),
2369 		       Quadrant(ls->obj->x,ls->obj->y));
2370 	  break;
2371 	}
2372 
2373 	n++;
2374       }
2375     }
2376     ls=ls->next;
2377   }
2378   return n;
2379 }
2380 
Add2TextMessageList(struct TextMessageList * listhead,char * cad,int source,int dest,int mid,int time,int priority)2381 int Add2TextMessageList(struct TextMessageList *listhead,char *cad,
2382 			int source,int dest,int mid,int time,int priority){
2383   /*
2384      version 02. April 2 2011
2385      add the integer id to the list by priority given by priority
2386      if is not already added.
2387      where:
2388      cad: the message.
2389      source: the object id
2390      dest: the destination player. -1 : for all players
2391      mid: is a message indentifier.
2392      time: the duration of the message in centiseconds.
2393      priority: priority.
2394      returns:
2395      0 if the message is added to the list
2396      1 if not, because is already added.
2397   */
2398   struct TextMessageList *list;
2399   struct TextMessageList *lh;
2400   int n=0;
2401 
2402   /* Add text at the end of the list */
2403 
2404   if(dest!=actual_player && dest!=-1){
2405     return(1);
2406   }
2407 
2408   lh=listhead;
2409   while(lh->next!=NULL){
2410 
2411     if(lh->next->info.source==source && lh->next->info.id==mid && lh->next->info.value==priority){ /* already added */
2412       return(1);
2413     }
2414 
2415     if(lh->next->info.value<priority){ /* added before end */
2416       break;
2417     }
2418     n++;
2419     lh=lh->next;
2420   }
2421 
2422   list=malloc(sizeof(struct TextMessageList));
2423   MemUsed(MADD,+sizeof(struct TextMessageList));
2424   if(list==NULL){
2425     fprintf(stderr,"ERROR in malloc Add2TextMessageList()\n");
2426     exit(-1);
2427   }
2428   list->info.source=source;
2429   list->info.dest=dest;
2430   list->info.id=mid;
2431   list->info.value=priority;
2432   list->info.time=GetTime();
2433   list->info.print=0;
2434   list->info.duration=time;
2435   strncpy(list->info.text,cad,MAXTEXTLEN);
2436 
2437   if(lh->next==NULL){ /* is the lastest */
2438     list->next=NULL;
2439     lh->next=list;
2440   }
2441   else{
2442     list->next=lh->next->next;
2443     lh->next=list;
2444   }
2445   listhead->info.n++;
2446   /*   gdk_beep(); */
2447   return (0);
2448 }
2449 
2450 
GetPrice(Object * obj,int stype,int eng,int weapon)2451 int GetPrice(Object *obj,int stype,int eng,int weapon){
2452   /*
2453     return:
2454     -1 if there are some error
2455     the price of the object obj
2456     if obj is NULL the price given for the other parametres.
2457   */
2458   static int ship_price[]={PRICESHIP0,PRICESHIP1,PRICESHIP2,PRICESHIP3,PRICESHIP4,PRICESHIP5,PRICESHIP6,PRICESHIP7,PRICESHIP8};
2459   static int engine_price[]={PRICEENGINE0,PRICEENGINE1,PRICEENGINE2,PRICEENGINE3,PRICEENGINE4,PRICEENGINE5};
2460   static int weapon_price[NUMWEAPONS]={PRICECANNON0,PRICECANNON1,PRICECANNON2,PRICECANNON3,PRICECANNON4,PRICECANNON5,PRICECANNON6,PRICECANNON7,PRICECANNON8,PRICECANNON9};
2461   int price=0;
2462   int level=0;
2463 
2464 
2465   if(obj!=NULL){
2466     if(obj->type!=SHIP){
2467       fprintf(stdout,"ERROR in GetPrice() obj type:%d\n",obj->type);
2468       return(-1);
2469     }
2470 
2471     stype=obj->subtype;
2472     eng=obj->engine.type;
2473     weapon=obj->weapon0.type;
2474     level=obj->level;
2475 
2476     if(obj->type==SHIP && obj->subtype==PILOT){
2477       /* TODO show this only in human game */
2478       eng=ENGINE0;
2479       weapon=CANNON0;
2480     }
2481   }
2482 
2483   if(stype<SHIP0 || stype>SHIP_S_MAX){
2484     fprintf(stderr,"ERROR in GetPrice() stype id:%d\n",stype);
2485     return(-1);
2486   }
2487   if(eng<ENGINE0 || eng>ENGINEMAX){
2488     fprintf(stderr,"ERROR in GetPrice() engine id:%d\n",eng);
2489     return(-1);
2490   }
2491   if(weapon<CANNON0 || weapon>CANNONMAX){
2492     fprintf(stderr,"ERROR in GetPrice() weapon id:%d\n",weapon);
2493     return(-1);
2494   }
2495 
2496   price+=ship_price[stype];
2497   price+=engine_price[eng];
2498   price+=weapon_price[weapon];
2499   price*=(level+1);
2500 
2501   return(price);
2502 }
2503 
BuyShip(struct Player * player,Object * obj,int stype)2504 int BuyShip(struct Player *player,Object *obj,int stype){
2505   /*
2506     buy and create an SHIP of subtype stype
2507     returns:
2508     an error code:
2509     0 ok
2510     1 obj is null
2511     2 obj is not landed
2512     3 player in a enemy planet
2513     4 Code error, must not happen
2514     5 Error in GetPrice()
2515     6 Not enough gold.
2516     7 Not enought room
2517   */
2518 
2519   Object *obj_b;
2520   Segment *s;
2521   float r;
2522   int price=0;
2523   float shield;
2524 
2525   if(obj==NULL)return(SZ_OBJNULL);
2526   if(obj->mode!=LANDED)return(SZ_OBJNOTLANDED);
2527   if(obj->player!=obj->in->player && stype==TOWER){
2528     printf("Warning: Buyship() player: %d planet: %d. Not owned.\n",player->id,obj->in->player);
2529     return(SZ_NOTOWNPLANET);
2530   }
2531 
2532   if(obj->type==SHIP && obj->subtype==PILOT && stype!=FIGHTER){ /* pilot buy a ship */
2533     printf("A pilot only can buy FIGHTERS\n");
2534     return(SZ_NOTALLOWED);
2535   }
2536 
2537   switch(stype){
2538   case EXPLORER:
2539     price=GetPrice(NULL,EXPLORER,ENGINE3,CANNON3);
2540     break;
2541   case FIGHTER:
2542     price=GetPrice(NULL,FIGHTER,ENGINE4,CANNON4);
2543     break;
2544   case TOWER:
2545     price=GetPrice(NULL,TOWER,ENGINE1,CANNON4);
2546     break;
2547   case FREIGHTER:
2548     price=GetPrice(NULL,FREIGHTER,ENGINE6,CANNON0);
2549     break;
2550   case SATELLITE:
2551     if(obj->cargo.mass + MASSSATELLITE > obj->cargo.capacity){
2552       return(SZ_NOTENOUGHROOM);
2553     }
2554     price=GetPrice(NULL,SATELLITE,ENGINE1,CANNON3);
2555     break;
2556   case GOODS:
2557     if(obj->cargo.mass + MASSGOODS > obj->cargo.capacity){
2558       return(SZ_NOTENOUGHROOM);
2559     }
2560     price=GetPrice(NULL,GOODS,ENGINE0,CANNON0);
2561     break;
2562 
2563   default:
2564     fprintf(stderr,"WARNING in Buyship() ship stype %d not implemented\n",stype);
2565     return(SZ_NOTIMPLEMENTED);
2566     break;
2567 
2568   }
2569   if(price<0)return(SZ_UNKNOWNERROR);
2570   if(player->gold < price)return(SZ_NOTENOUGHGOLD);
2571 
2572 
2573   if(obj->type==SHIP && obj->subtype==PILOT){ /* pilot buy a ship */
2574     shield=obj->shield;
2575     ShipProperties(obj,stype,obj->in);
2576     obj->shield=shield;
2577     obj->cost*=pow(2,obj->level);
2578     obj->subtype=stype;
2579     obj->a=PI/2;
2580     obj->ai=1;
2581     obj->durable=FALSE;
2582     obj->mode=LANDED;
2583     obj->habitat=H_PLANET;
2584     /* obj->selected=FALSE; */
2585     if(obj->in->type!=PLANET){
2586       fprintf(stderr,"ERROR BuyShip() pilot buying\n");
2587     }
2588 
2589     if(GameParametres(GET,GNET,0)==TRUE){
2590       SetModified(obj,SENDOBJALL);
2591     }
2592     player->gold -=price;
2593     return(SZ_OK);
2594   }
2595 
2596   s=LandZone(obj->in->planet);
2597   if(s==NULL){
2598     fprintf(stderr,"ERROR BuyShip(): Segment==NULL\n");
2599     exit(-1);
2600   }
2601 
2602   switch(stype){
2603   case EXPLORER:
2604     obj_b=NewObj(SHIP,EXPLORER,
2605 		 obj->x,s->y0,
2606 		 0,0,
2607 		 CANNON3,ENGINE3,obj->player,NULL,obj->in);
2608     break;
2609   case FIGHTER:
2610     obj_b=NewObj(SHIP,FIGHTER,
2611 		 obj->x,s->y0,
2612 		 0,0,
2613 		 CANNON4,ENGINE4,obj->player,NULL,obj->in);
2614     break;
2615   case TOWER:
2616     obj_b=NewObj(SHIP,TOWER,
2617 		 obj->x,s->y0,
2618 		 0,0,
2619 		 CANNON4,ENGINE1,obj->player,NULL,obj->in);
2620     break;
2621   case FREIGHTER:
2622     obj_b=NewObj(SHIP,FREIGHTER,
2623 		 obj->x,s->y0,
2624 		 0,0,
2625 		 CANNON0,ENGINE6,obj->player,NULL,obj->in);
2626     obj_b->oriid=obj->in->id;
2627     break;
2628 
2629   case SATELLITE:
2630     obj_b=NULL;
2631 
2632     obj_b=NewObj(SHIP,SATELLITE,
2633 		 obj->x,s->y0,
2634 		 0,0,
2635 		 CANNON3,ENGINE1,obj->player,NULL,obj->in);
2636 
2637     break;
2638   case GOODS:
2639     obj_b=NULL;
2640 
2641     obj_b=NewObj(SHIP,GOODS,
2642 		 obj->x,s->y0,
2643 		 0,0,
2644 		 CANNON0,ENGINE0,obj->player,NULL,obj->in);
2645 
2646     break;
2647 
2648   default:
2649     obj_b=NULL;
2650     fprintf(stderr,"ERROR in Buyship() ship stype %d not implemented\n",stype);
2651     return(SZ_NOTIMPLEMENTED);
2652     break;
2653 
2654   }
2655 
2656 
2657   if(obj_b!=NULL){
2658     player->gold -=price;
2659     player->goldships+=price;
2660     /* obj_b->y+=obj_b->radio+1; */
2661     r=s->x1-s->x0-2*obj_b->radio;
2662 
2663     obj_b->x=s->x0+obj_b->radio+r*(Random(-1));
2664     obj_b->y+=obj_b->radio+1;
2665     obj_b->player=obj->player;
2666     obj_b->a=PI/2;
2667     obj_b->habitat=obj->habitat;
2668     obj_b->planet=NULL;
2669     obj_b->gas=obj_b->gas_max*(.5+.5*(Random(-1)));
2670     obj_b->mode=LANDED;
2671 
2672     if(stype==SATELLITE){
2673       if(CargoAdd(obj,obj_b)){
2674 	obj_b->weapon->n=obj_b->weapon->max_n;
2675 	obj_b->gas=obj_b->gas_max;
2676 	obj_b->state=100;
2677 	obj_b->habitat=H_SHIP;
2678 	obj_b->in=obj;
2679       }
2680     }
2681     if(stype==GOODS){
2682       if(CargoAdd(obj,obj_b)){
2683 	obj_b->state=100;
2684 	obj_b->habitat=H_SHIP;
2685 	obj_b->in=obj;
2686       }
2687     }
2688 
2689     player->nbuildships++;
2690 
2691     Add2ObjList(&listheadobjs,obj_b);
2692     if(GameParametres(GET,GNET,0)==TRUE){
2693       SetModified(obj,SENDOBJNEW);/* HERE obj or obj_b???*/
2694     }
2695   }
2696   else{
2697     fprintf(stderr,"ERROR in BuyShip()\n");
2698   }
2699   return(SZ_OK);
2700 }
2701 
2702 
2703 
NextCv(struct HeadObjList * lh,Object * cv0,int pid)2704 Object *NextCv(struct HeadObjList *lh,Object *cv0,int pid){
2705   /*
2706     returns:
2707     if cv0 is NULL a pointer to the first ship
2708     if cv0 != NULL a pointer to the next ship in the list
2709 
2710   */
2711 
2712   struct ObjList *ls;
2713   Object *obj1=NULL;
2714   int sw1=0;
2715   int swcv=0;
2716 
2717   ls=lh->list;
2718   if(ls==NULL){
2719     printf("There are no ship selected!!\n");
2720     return(NULL);
2721   }
2722 
2723   while(ls!=NULL){   /* find the actual cv */
2724     if(ls->obj->player!=pid){ls=ls->next;continue;}
2725     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2726     if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2727 
2728     if(!sw1){
2729       if(cv0==NULL){
2730 	return(ls->obj); /* first found */
2731       }
2732       obj1=ls->obj;
2733       sw1=1;
2734     }
2735     if(!swcv && cv0!=NULL){
2736       if(ls->obj==cv0)
2737 	swcv=1;
2738     }
2739     if(swcv && ls->obj!=cv0){
2740       return(ls->obj); /* first after cv */
2741     }
2742 
2743     ls=ls->next;
2744   }
2745   return(obj1);
2746 }
2747 
PrevCv(struct HeadObjList * lh,Object * cv0,int pid)2748 Object *PrevCv(struct HeadObjList *lh,Object *cv0,int pid){
2749   /*
2750     returns:
2751     if cv0 is NULL a pointer to the first ship
2752     if cv0 != NULL a pointer to the previous ship in the list
2753 
2754   */
2755 
2756   struct ObjList *ls;
2757   Object *obj,*pobj;
2758 
2759   obj=pobj=NULL;
2760 
2761   ls=lh->list;
2762   if(ls==NULL){
2763     printf("There are no ship selected!!\n");
2764     return(NULL);
2765   }
2766 
2767   while(ls!=NULL){
2768     obj=ls->obj;
2769     if(obj->player==pid && obj->type==SHIP){
2770       if(obj->subtype==PILOT && obj->habitat==H_SHIP){ls=ls->next;continue;}
2771       if(cv0==NULL)return(obj); /* first found */
2772       else{
2773 	if(obj!=cv0)pobj=obj;
2774 	if(obj==cv0){
2775 	  if(pobj!=NULL)return(pobj);
2776 	}
2777       }
2778     }
2779     ls=ls->next;
2780   }
2781   if(pobj==NULL && cv0!=NULL)return(cv0);
2782   return(pobj);
2783 }
2784 
2785 
FirstShip(struct HeadObjList * lh,Object * cv0,int pid)2786 Object *FirstShip(struct HeadObjList *lh,Object *cv0,int pid){
2787   /*
2788     returns:
2789     a pointer to the first ship in free space.
2790     if not, the actual selected cv0.
2791   */
2792 
2793   struct ObjList *ls;
2794 
2795   ls=lh->list;
2796   if(ls==NULL){
2797     printf("There are no ship selected!!\n");
2798     return(NULL);
2799   }
2800 
2801   while(ls!=NULL){
2802     if(ls->obj->player!=pid){ls=ls->next;continue;}
2803     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2804     if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2805 
2806     if(ls->obj->habitat==H_SPACE){
2807       return(ls->obj); /* first found */
2808     }
2809 
2810 
2811     ls=ls->next;
2812   }
2813 
2814   return(cv0);
2815 }
2816 
PrevPlanetCv(struct HeadObjList * lh,Object * cv0,int playerid)2817 Object *PrevPlanetCv(struct HeadObjList *lh,Object *cv0,int playerid){
2818   /*
2819     version 01
2820     returns:
2821     if cv0 is NULL a pointer to the first planet
2822     if cv0 != NULL a pointer to the previous planet in the list
2823   */
2824 
2825   struct ObjList *ls;
2826   Object *pobj=NULL;
2827   int pplanet=-1;
2828   int planet0=-1;
2829   int planet;
2830 
2831   ls=lh->list;
2832   if(ls==NULL){
2833     printf("There are no ship selected!!\n");
2834     return(NULL);
2835   }
2836   if(cv0!=NULL){
2837     planet0=cv0->habitat==H_PLANET ? cv0->in->id : 0;
2838   }
2839 
2840   while(ls!=NULL){
2841 
2842     if(ls->obj->player!=playerid){ls=ls->next;continue;}
2843     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2844     if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2845     if(cv0==NULL)return(ls->obj);
2846 
2847     planet=ls->obj->habitat==H_PLANET ? ls->obj->in->id : 0;
2848     if(planet==planet0){
2849       if(pobj!=NULL)return(pobj);
2850       else{
2851 	ls=ls->next;continue;
2852       }
2853     }
2854     else{
2855       if(pplanet!=planet){
2856 	pobj=ls->obj;
2857 	pplanet=planet;
2858       }
2859     }
2860     ls=ls->next;
2861   }
2862   if(pobj==NULL && cv0!=NULL)return(cv0);
2863   return(pobj);
2864 }
2865 
2866 
NextPlanetCv(struct HeadObjList * lh,Object * cv0,int playerid)2867 Object *NextPlanetCv(struct HeadObjList *lh,Object *cv0,int playerid){
2868   /*
2869     returns:
2870     if cv0 is NULL a pointer to the first ship
2871     if cv0 != NULL a pointer to the first ship in next planet in the list
2872   */
2873 
2874   struct ObjList *ls;
2875   Object *obj1;
2876   int sw1=0;
2877   int swcv=0;
2878   int planet0=0;
2879 
2880 
2881   ls=lh->list;
2882   if(ls==NULL){
2883     printf("There are no ship selected!!\n");
2884     return(NULL);
2885   }
2886 
2887   obj1=NULL;
2888   if(cv0!=NULL){
2889     if(cv0->habitat==H_PLANET){
2890       planet0=cv0->in->id;
2891     }
2892   }
2893 
2894   while(ls!=NULL){   /* find the actual cv */
2895     if(ls->obj->player==playerid && ls->obj->type==SHIP){
2896       if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2897       if(!sw1){
2898 	if((cv0==NULL || planet0==0) && ls->obj->habitat==H_PLANET){
2899 	  return(ls->obj); /* first found */
2900 	}
2901 	obj1=ls->obj;
2902 	sw1=1;
2903       }
2904       if(!swcv && cv0!=NULL){
2905 	if(ls->obj==cv0)
2906 	  swcv=1;
2907       }
2908       if(swcv && ls->obj!=cv0 && ls->obj->habitat==H_PLANET){
2909 	if(planet0==0){
2910 	  return(ls->obj); /* first after cv */
2911 	}
2912 	else{
2913 	  if(planet0!=ls->obj->in->id){
2914 	    return(ls->obj);
2915 	  }
2916 	}
2917       }
2918     }
2919     ls=ls->next;
2920   }
2921   return(obj1);
2922 }
2923 
2924 
CountObjList(struct HeadObjList * hlist)2925 int CountObjList(struct HeadObjList *hlist){
2926   /*
2927     returns:
2928     the number of item of the list hlist.
2929   */
2930   struct ObjList *ls;
2931   int n=0;
2932 
2933   if(hlist==NULL)return(0);
2934   ls=hlist->list;
2935   while(ls!=NULL){
2936     n++;
2937     ls=ls->next;
2938   }
2939   return n;
2940 }
2941 
2942 
DestroyObjList(struct HeadObjList * hl)2943 int DestroyObjList(struct HeadObjList *hl){
2944   /*
2945     free memory for the list hl.
2946   */
2947   struct ObjList *ls0;
2948   int n=0;
2949   long memused=0;
2950 
2951   if(hl==NULL)return(0);
2952 
2953   while(hl->list!=NULL){
2954     ls0=hl->list;
2955     hl->list=hl->list->next;
2956     ls0->obj=NULL;
2957     ls0->next=NULL;
2958     free(ls0);
2959     ls0=NULL;
2960     memused-=sizeof(struct ObjList);
2961     hl->n--;
2962     n++;
2963   }
2964   MemUsed(MADD,memused);
2965 
2966   if(hl->list!=NULL){
2967     fprintf(stderr,"ERROR 1 in DestroyObjList()\n");
2968     exit(-1);
2969   }
2970   if(hl->n!=0){
2971     fprintf(stderr,"ERROR 2 in DestroyObjList()  n:%d  del:%d\n",hl->n,n);
2972     hl->n=0;
2973     hl->list=NULL;
2974     /*     exit(-1); */
2975   }
2976   return(n);
2977 }
2978 
PrintObjList(struct HeadObjList * hl)2979 int PrintObjList(struct HeadObjList *hl){
2980   /*
2981     print some info of the list hl
2982     DEBUG only
2983   */
2984   if(hl==NULL)return(0);
2985   printf("List: ");
2986   while(hl->list!=NULL){
2987     printf("%d ",hl->list->obj->id);
2988     hl->list=hl->list->next;
2989   }
2990   printf("\n");
2991   return(0);
2992 }
2993 
2994 
IsInObjList(struct HeadObjList * lhobjs,Object * obj)2995 int IsInObjList(struct HeadObjList *lhobjs,Object *obj){
2996 
2997   /*
2998     NOTUSED
2999     Look for obj in the list lhobjs
3000     returns:
3001     0 if obj is not in the list
3002     1 if is in the list
3003   */
3004 
3005   struct ObjList *ls;
3006   if(lhobjs==NULL)return(-1);
3007   if(obj==NULL)return(0);
3008 
3009   ls=lhobjs->list;
3010   while(ls!=NULL){
3011     if(ls->obj==obj)return(1);
3012     ls=ls->next;
3013   }
3014   return(0);
3015 }
3016 
KillAllObjs(struct HeadObjList * lheadobjs)3017 void KillAllObjs(struct HeadObjList *lheadobjs){
3018   /*
3019     Kill all objects setting their state and life to zero.
3020   */
3021   struct ObjList *ls;
3022 
3023   if(lheadobjs==NULL)return;
3024   ls=lheadobjs->list;
3025 
3026   while(ls!=NULL){
3027     ls->obj->life=0;
3028     ls->obj->state=0;
3029     ls->obj->sw=0;
3030     ls=ls->next;
3031   }
3032 }
3033 
3034 
CreatePlayerList(struct HeadObjList hlist1,struct HeadObjList * hlist2,int player)3035 int CreatePlayerList(struct HeadObjList hlist1,struct HeadObjList *hlist2,int player){
3036   /*
3037      version 04
3038      Create a list in hlist2 only with ships an planets
3039      that belongs to player player from the list hlist1.
3040      return:
3041      the number of elements of the list.
3042   */
3043 
3044   struct ObjList *ls0,*ls1,*ls2;
3045   Object *objin;
3046   int id1,id2;
3047   int n=0;
3048   long memused=0;
3049   struct Player *players;
3050 
3051   players=GetPlayers();
3052 
3053     if(hlist2->list!=NULL){
3054     fprintf(stderr,"WARNING CPL not NULL %p %d\n",(void *)hlist2->list,hlist2->n);
3055   }
3056 
3057   hlist2->n=0;
3058   hlist2->list=NULL;
3059   ls0=ls1=ls2=NULL;
3060 
3061   for(ls1=hlist1.list;ls1!=NULL;ls1=ls1->next){
3062 
3063     switch(ls1->obj->type){
3064     case SHIP:
3065       if(ls1->obj->player!=player)continue;
3066       break;
3067     case PLANET:
3068       if(players[ls1->obj->player].team!=players[player].team)continue;
3069       break;
3070     default:
3071       continue;
3072       break;
3073     }
3074 
3075     if(ls1->obj->subtype==SATELLITE)continue;
3076     if(ls1->obj->subtype==GOODS)continue;
3077     if(ls1->obj->state<=0)continue;
3078 
3079 
3080     id1=ls1->obj->id; /* id of the planet in which is contained, 0 for free space*/
3081     if(ls1->obj->type!=PLANET)id1=0;
3082 
3083     /* HERENEW */
3084 
3085     if(ls1->obj->in!=NULL){ /* not a planet */
3086       objin=ls1->obj->in;
3087       while(objin!=NULL){
3088 	id1=objin->id;
3089 	if(objin->type!=PLANET)id1=0;
3090 	objin=objin->in;
3091       }
3092     }
3093 
3094     ls0=malloc(sizeof(struct ObjList));
3095     memused+=sizeof(struct ObjList);
3096     /* MemUsed(MADD,+sizeof(struct ObjList)); */
3097     if(ls0==NULL){
3098       fprintf(stderr,"ERROR in malloc CreateList()\n");
3099       exit(-1);
3100     }
3101     ls0->obj=ls1->obj;
3102     ls0->next=NULL;
3103 
3104 
3105     if(hlist2->list==NULL){ /* first item */
3106       hlist2->list=ls0;
3107       hlist2->n++;
3108       n++;
3109       continue;
3110     }
3111 
3112     id2=hlist2->list->obj->id;
3113     if(hlist2->list->obj->type!=PLANET)id2=0;
3114 
3115     if(hlist2->list->obj->in!=NULL){
3116       objin=hlist2->list->obj->in;
3117       while(objin!=NULL){
3118 	id2=objin->id;
3119 	if(objin->type!=PLANET)id2=0;
3120 	objin=objin->in;
3121       }
3122     }
3123 
3124     if(id1 < id2 ){
3125       ls0->next=hlist2->list;
3126       hlist2->list=ls0;
3127       hlist2->n++;
3128       n++;
3129       continue;
3130     }
3131 
3132     for(ls2=hlist2->list;ls2->next!=NULL;ls2=ls2->next){
3133 
3134       id2=ls2->next->obj->id;
3135       if(ls2->next->obj->type!=PLANET)id2=0;
3136 
3137       if(ls2->next->obj->in!=NULL){
3138 	objin=ls2->next->obj->in;
3139 	while(objin!=NULL){
3140 	  id2=objin->id;
3141 	  if(objin->type!=PLANET)id2=0;
3142 	  objin=objin->in;
3143 	}
3144       }
3145 
3146 
3147       if(id1 < id2 )break;
3148     }
3149 
3150     ls0->next=ls2->next;
3151     ls2->next=ls0;
3152 
3153     hlist2->n++;
3154     n++;
3155   }
3156   MemUsed(MADD,memused);
3157   return(n) ;
3158 }
3159 
3160 
CreateContainerLists(struct HeadObjList * lh,struct HeadObjList * hcontainer)3161 int CreateContainerLists(struct HeadObjList *lh,struct HeadObjList *hcontainer){
3162   /*
3163      Create a list with all the objects that can collide.
3164      Create a container list for every planet
3165      Add to hcontainer all the objects in each planet plus free space objects
3166      returns:
3167      0
3168   */
3169   struct ObjList *ls;
3170   Object *obj;
3171   int nplanets;
3172   int i,n;
3173   int proc;
3174   int value0;
3175   int gulx,guly;
3176   struct Player *players;
3177 
3178   players=GetPlayers();
3179 
3180   for(i=0;i<GameParametres(GET,GNPLANETS,0)+1;i++){
3181     if(hcontainer[i].list!=NULL){
3182       fprintf(stderr,"WARNING: CCL() not NULL\n");
3183     }
3184     hcontainer[i].n=0;
3185   }
3186 
3187   nplanets=GameParametres(GET,GNPLANETS,0);
3188   gulx=GameParametres(GET,GULX,0);
3189   guly=GameParametres(GET,GULY,0);
3190 
3191   proc=GetProc();
3192 
3193   ls=lh->list;
3194   while(ls!=NULL){
3195 
3196     if(ls->obj->state<=0 && proc==players[ls->obj->player].proc){
3197       ls=ls->next;continue;
3198     }
3199     /* objects than don't collide */
3200     switch(ls->obj->type){
3201     case PROJECTILE:
3202       if(ls->obj->subtype==EXPLOSION && ls->obj->habitat==H_SPACE){
3203 	ls=ls->next;continue;
3204       }
3205       break;
3206     case TRACE:
3207     case TRACKPOINT:
3208       ls=ls->next;
3209       continue;
3210       break;
3211     case SHIP:
3212       if(ls->obj->subtype==PILOT && ls->obj->mode==LANDED){
3213 	ls=ls->next;
3214 	continue;
3215       }
3216       break;
3217     default:
3218       break;
3219     }
3220     /* --objects than don't collide */
3221 
3222     switch(ls->obj->habitat){
3223     case H_SPACE:
3224       n=0;
3225       break;
3226     case H_PLANET:
3227       n=ls->obj->in->id;
3228       break;
3229     case H_SHIP:
3230       ls=ls->next;continue;
3231       break;
3232     default:
3233       n=0;
3234       break;
3235     }
3236 
3237     /* check */
3238 
3239     if(n<0||n>nplanets){
3240       fprintf(stderr,"ERROR 1 in CreateContainerlists()\n");
3241       fprintf(stderr,"\t DEBUG info:   n: %d objid:%d type: %d stype: %d\n",n,ls->obj->id,ls->obj->type,ls->obj->subtype);
3242       n=0;
3243     }
3244 
3245     obj=ls->obj;
3246 
3247     /**** CELLON****/
3248     if(n==0){
3249       switch(obj->type){
3250       case PLANET:
3251 	value0=1;
3252 	break;
3253       case ASTEROID:
3254 	value0=2;
3255 	break;
3256       case SHIP:
3257 	value0=1<<(players[obj->player].team+3);
3258 	if(obj->subtype==PILOT)value0=4;
3259 	break;
3260       case PROJECTILE:
3261 	value0=1<<(players[obj->player].team+3);
3262 	break;
3263       default:
3264 	ls=ls->next;
3265 	continue;
3266 	break;
3267       }
3268       if(ValueCell(cell,obj,gulx,guly)==value0){
3269 	ls=ls->next;continue;
3270       }
3271     }
3272     /*****CELLON*****/
3273 
3274     Add2ObjList(&hcontainer[n],ls->obj);
3275     ls=ls->next;
3276   }
3277   return(0);
3278 }
3279 
3280 
3281 
CreatekplanetsLists(struct HeadObjList * lh,struct HeadObjList * hkplanets)3282 int CreatekplanetsLists(struct HeadObjList *lh,struct HeadObjList *hkplanets){
3283   /*
3284      Create a list with all the known planets.
3285      returns the number of objects of the list.
3286   */
3287   struct ObjList *ls;
3288   int gnplayers;
3289   int i;
3290   int n=0;
3291   int proc;
3292   struct Player *players;
3293 
3294   players=GetPlayers();
3295   proc=GetProc();
3296   gnplayers=GameParametres(GET,GNPLAYERS,0);
3297 
3298   for(i=0;i<gnplayers+1;i++){
3299     if(hkplanets[i].list!=NULL){
3300       fprintf(stderr,"WARNING: CkpL() not NULL\n");
3301     }
3302     hkplanets[i].n=0;
3303   }
3304 
3305   ls=lh->list;
3306   while(ls!=NULL){
3307     if(ls->obj->type!=PLANET){ls=ls->next;continue;}
3308 
3309     for(i=0;i<gnplayers+2;i++){
3310       if(proc==players[i].proc){
3311 	if(IsInIntList(players[i].kplanets,ls->obj->id)){
3312 	  Add2ObjList(&hkplanets[i],ls->obj);
3313 	  n++;
3314 	}
3315       }
3316     }
3317     ls=ls->next;
3318   }
3319   return(n);
3320 }
3321 
3322 
CreatePlanetList(struct HeadObjList lheadobjs,struct HeadObjList * lheadplanets)3323 int CreatePlanetList(struct HeadObjList lheadobjs,struct HeadObjList *lheadplanets){
3324   /*
3325     version 0.1
3326     Create a list of planets from the object list lheadobjs
3327     to obj. list lheadplanets.
3328     returns:
3329     the number of planets added to the list.
3330   */
3331 
3332 
3333   struct ObjList *ls,*ls0,*lsp;
3334   long memused=0;
3335 
3336   if(lheadplanets->list!=NULL){
3337     DestroyObjList(lheadplanets);
3338   }
3339   lheadplanets->n=0;
3340 
3341   ls=lheadobjs.list;
3342   ls0=NULL;
3343   lsp=NULL;
3344 
3345   while(ls!=NULL){
3346     if(ls->obj->type==PLANET){
3347 
3348       ls0=malloc(sizeof(struct ObjList));
3349       memused+=sizeof(struct ObjList);
3350 
3351       if(ls0==NULL){
3352 	fprintf(stderr,"ERROR in malloc() CreatePlanetList()\n");
3353 	exit(-1);
3354       }
3355 
3356       ls0->obj=ls->obj;
3357       ls0->next=NULL;
3358 
3359       if(lheadplanets->n==0){
3360 	lheadplanets->list=ls0;
3361 	lsp=ls0;
3362       }
3363       else{
3364 	lsp->next=ls0;
3365 	lsp=ls0;
3366       }
3367       lheadplanets->n++;
3368     }
3369     ls=ls->next;
3370   }
3371   MemUsed(MADD,memused);
3372   return(lheadplanets->n);
3373 }
3374 
3375 
CreateNearObjsList(struct HeadObjList * lh,struct HeadObjList * lhn,int player)3376 void CreateNearObjsList(struct HeadObjList *lh,struct HeadObjList *lhn,int player){
3377   /*
3378     Create a list of enemy ships in radar range of the player player
3379   */
3380 
3381   struct ObjList *ls1,*ls2;
3382   Object *obj1,*obj2;
3383 
3384   float rx,ry,r2;
3385   int gnet,proc;
3386   struct Player *players;
3387 
3388   players=GetPlayers();
3389   gnet=GameParametres(GET,GNET,0);
3390   proc=GetProc();
3391 
3392   if(lhn->list!=NULL){
3393     fprintf(stderr,"WARNING: CNOL() not NULL\n");
3394   }
3395   lhn->n=0;
3396   ls1=lh->list;
3397   while(ls1!=NULL){
3398     obj1=ls1->obj;
3399 
3400     /* obj1 is an enemy, a ship and in SPACE */
3401     if(players[obj1->player].team==players[player].team ||
3402        obj1->type!=SHIP ||
3403        obj1->habitat!=H_SPACE){
3404       ls1=ls1->next;continue;
3405     }
3406 
3407     if(gnet==TRUE){
3408       if(proc!=players[obj1->player].proc){
3409 	if(obj1->ttl<MINTTL){ls1=ls1->next;continue;}
3410       }
3411     }
3412 
3413     ls2=lh->list;
3414     while(ls2 != NULL){
3415       /* obj2 is an ally */
3416       obj2=ls2->obj;
3417       if(obj2->player!=player){
3418 	ls2=ls2->next;continue;
3419       }
3420       if(obj2->type!=SHIP){
3421 	ls2=ls2->next;continue;
3422       }
3423 
3424       switch(obj2->habitat){
3425       case H_SPACE:
3426 	rx=obj2->x - obj1->x;
3427 	ry=obj2->y - obj1->y;
3428 	break;
3429       case H_PLANET:
3430 	rx=obj2->in->x - obj1->x;
3431 	ry=obj2->in->y - obj1->y;
3432 	break;
3433       case H_SHIP:
3434 	ls2=ls2->next;continue;
3435 	break;
3436       default:
3437 	fprintf(stderr,
3438 		"ERROR in CreateNearObjsList() unknown habitat %d\n",
3439 		obj2->habitat);
3440 	exit(-1);
3441 	break;
3442 
3443       }
3444 
3445       r2=rx*rx+ry*ry;
3446 
3447       if(r2 < obj2->radar*obj2->radar){
3448 	Add2ObjList(lhn,obj1);
3449 	break;
3450       }
3451       ls2=ls2->next;
3452     }
3453     ls1=ls1->next;
3454   }
3455 }
3456 
3457 
3458 
Experience(Object * obj,float pts)3459 void Experience(Object *obj,float pts){
3460   /*
3461     Increase ships level.
3462 
3463   */
3464 
3465   float mulshots;
3466   struct Player *players;
3467 
3468   if(obj->state<=0){
3469     return;
3470   }
3471   if(obj->type!=SHIP)return;
3472   if(obj->subtype==PILOT)return;
3473 
3474   players=GetPlayers();
3475 
3476   players[obj->player].points+=pts;
3477   if(players[obj->player].points>=record){
3478     record=players[obj->player].points;
3479   }
3480 
3481   obj->experience+=pts;
3482 
3483 
3484   while(obj->experience>=100*pow(2,obj->level)){
3485     obj->experience-=100*pow(2,obj->level);
3486     obj->level++;
3487     /* HERE      obj->ttl=0; */
3488 
3489     if(GameParametres(GET,GNET,0)==TRUE){
3490       /* if(GetProc()==players[obj->player].proc){ */
3491       SetModified(obj,SENDOBJALL);
3492       /* } */
3493     }
3494     obj->state=100;
3495     obj->gas=obj->gas_max;
3496     obj->engine.gascost-=.01;
3497     obj->engine.v_max++;
3498     obj->cost*=COSTINC*COSTFACTOR;
3499 
3500     mulshots=1+1./(obj->level);
3501 
3502     if(obj->weapon0.type!=CANNON0){
3503       obj->weapon0.max_n+=50;
3504       if(obj->weapon0.rate>9){
3505 	obj->weapon0.rate--;
3506       }
3507       if(obj->weapon0.nshots<4){
3508 	if(!(obj->level%2)){
3509 	  obj->weapon0.nshots++;
3510 	}
3511       }
3512       obj->weapon0.projectile.damage*=1.+.2*DAMAGEFACTOR;
3513     }
3514 
3515     if(obj->weapon1.type!=CANNON0){
3516       if(obj->weapon1.rate>9){
3517 	obj->weapon1.rate--;
3518       }
3519       if(obj->weapon1.max_n<10){ /* max 11 missiles */
3520 	obj->weapon1.max_n+=2;
3521       }
3522       obj->weapon1.projectile.damage*=1.+.2*DAMAGEFACTOR;
3523     }
3524 
3525     if(obj->weapon2.type!=CANNON0){
3526       obj->weapon2.max_n*=mulshots;
3527       if(obj->weapon2.rate>9){
3528 	obj->weapon2.rate--;
3529       }
3530       obj->weapon2.projectile.damage*=1.+.2*DAMAGEFACTOR;
3531     }
3532 
3533     if(obj->engine.gascost<.01)obj->engine.gascost=.01;
3534     if(obj->engine.v_max>VELMAX)obj->engine.v_max=VELMAX;
3535 
3536     obj->engine.v2_max=obj->engine.v_max*obj->engine.v_max;
3537 
3538     switch(obj->subtype){
3539     case FIGHTER:
3540 
3541       switch(obj->level){
3542       case 1:
3543 	if(obj->weapon1.type==CANNON0){
3544 	  NewWeapon(&obj->weapon1,CANNON8);
3545 	}
3546 	break;
3547       case 2:
3548 	if(obj->weapon2.type==CANNON0){
3549 	  NewWeapon(&obj->weapon2,CANNON9);
3550 	}
3551 	break;
3552       default:
3553 	break;
3554       }
3555       obj->shield+=(.9-obj->shield)/3.;
3556       obj->engine.a_max*=1.10;
3557       break;
3558     case FREIGHTER:
3559       obj->cargo.capacity*=1.2;
3560       obj->engine.a_max*=1.15;
3561       obj->shield+=(.95-obj->shield)/2.;
3562       if(obj->shield>.95)obj->shield=.95;
3563       break;
3564     default:
3565       obj->shield+=(.9-obj->shield)/3.;
3566       if(obj->shield>.9)obj->shield=.9;
3567       break;
3568 
3569 
3570     }
3571 
3572   }
3573 }
3574 
PrintObj(Object * obj)3575 void PrintObj(Object *obj){
3576   printf("obj id:%d pid: %d type: %d stype: %d\n",
3577 	 obj->id,obj->pid,obj->type,obj->subtype);
3578 }
3579 
Type(Object * obj)3580 char Type(Object *obj){
3581   /*
3582     returns:
3583     a char
3584   */
3585 
3586   char mode=' ';
3587   if (obj==NULL)return(mode);
3588 
3589   if(obj->type==SHIP){
3590     switch (obj->subtype){
3591     case FIGHTER:
3592       mode='F';
3593       break;
3594     case EXPLORER:
3595       mode='E';
3596       break;
3597     case TOWER:
3598       mode='T';
3599       break;
3600     case QUEEN:
3601       mode='Q';
3602       break;
3603     case FREIGHTER:
3604       mode='C';
3605       break;
3606     case PILOT:
3607       mode='A';
3608       break;
3609     case SATELLITE:
3610       mode='S';
3611       break;
3612     default:
3613       mode='O';
3614       break;
3615     }
3616   }
3617   return(mode);
3618 }
3619 
TypeCad(Object * obj)3620 char *TypeCad(Object *obj){
3621   /*
3622     returns:
3623     a cad with the type of ship
3624   */
3625 
3626   static char cad[16]="";
3627   if (obj==NULL)return(cad);
3628 
3629   if(obj->type==SHIP){
3630     switch (obj->subtype){
3631     case FIGHTER:
3632       strcpy(cad,"FIGHTER");
3633       break;
3634     case EXPLORER:
3635       strcpy(cad,"EXPLORER");
3636       break;
3637     case TOWER:
3638       strcpy(cad,"TOWER");
3639       break;
3640     case QUEEN:
3641       strcpy(cad,"QUEEN");
3642       break;
3643     case PILOT:
3644       strcpy(cad,"PILOT");
3645       break;
3646     default:
3647       strcpy(cad,"");
3648       break;
3649     }
3650   }
3651   return(cad);
3652 }
3653 
3654 
MarkObjs(struct HeadObjList * lh,Space reg,Object * cv,int ctrl)3655 Object *MarkObjs(struct HeadObjList *lh,Space reg,Object *cv,int ctrl){
3656   /*
3657     Set the selected mark on in all ship inside the region reg.
3658     return a pointer to the first selected obj
3659     if cv is selected returns cv.
3660 
3661   */
3662 
3663   struct ObjList *ls;
3664   int n=0;
3665   Rectangle rect;
3666   int x,y;
3667   Point a,b;
3668   int sw1=0; /* first selected */
3669   Object *ret;
3670 
3671   if(lh==NULL)return(NULL);
3672 
3673   ret=NULL;
3674   rect.x=reg.rect.x;
3675   rect.y=reg.rect.y;
3676   rect.width=reg.rect.width;
3677   rect.height=reg.rect.height;
3678 
3679   if(reg.rect.width<0){
3680     rect.x+=reg.rect.width;
3681     rect.width*=-1;
3682   }
3683 
3684   if(reg.rect.height<0){
3685     rect.y+=reg.rect.height;
3686     rect.height*=-1;
3687   }
3688 
3689   if(reg.habitat>0){ /* select a region inside a planet */
3690 
3691     a.x=rect.x;
3692     a.y=rect.y-rect.height;
3693     b.x=rect.x+rect.width;
3694     b.y=rect.y;
3695 
3696   }
3697   else{ /* select a region in map view */
3698 
3699     a.x=rect.x;
3700     a.y=rect.y;
3701     b.x=rect.x+rect.width;
3702     b.y=rect.y+rect.height;
3703   }
3704 
3705   ls=lh->list;
3706   while(ls!=NULL){
3707     if(ctrl==FALSE)ls->obj->selected=FALSE;
3708     if(ls->obj->player!=actual_player){ls=ls->next;continue;}
3709     if(ls->obj->type!=SHIP){ls=ls->next;continue;}
3710 
3711     if(reg.habitat>0){  /* select a region inside a planet */
3712       if(ls->obj->habitat==H_SPACE){ls=ls->next;continue;}
3713       if(reg.habitat!=ls->obj->in->id){ls=ls->next;continue;}
3714 
3715       if(ls->obj->x > a.x && ls->obj->x < b.x ){
3716 	if(ls->obj->y+ls->obj->radio > a.y && ls->obj->y+ls->obj->radio < b.y ){
3717 	  if(sw1==0){
3718 	    if(ls->obj->habitat!=H_SHIP){
3719 	      ret=ls->obj;
3720 	      sw1++;
3721 	    }
3722 	  }
3723 	  ls->obj->selected=TRUE;
3724 	  n++;
3725 	}
3726       }
3727     }
3728     else{ /* select a region in free space */
3729       if(ls->obj->habitat==H_PLANET){
3730 	x=ls->obj->in->planet->x;
3731 	y=ls->obj->in->planet->y;
3732       }
3733       else{
3734 	x=ls->obj->x;
3735 	y=ls->obj->y;
3736       }
3737 
3738       if(x > a.x && x < b.x ){
3739 	if(y > a.y && y < b.y ){
3740 	  if(sw1==0){
3741 	    if(ls->obj->habitat!=H_SHIP){
3742 	      ret=ls->obj;
3743 	      sw1++;
3744 	    }
3745 	  }
3746 	  ls->obj->selected=TRUE;
3747 	  n++;
3748 	}
3749       }
3750     }
3751     ls=ls->next;
3752   }
3753   if(cv!=NULL){
3754     if(cv->selected==TRUE)return(cv);
3755   }
3756   return(ret);
3757 }
3758 
3759 
UnmarkObjs(struct HeadObjList * lh)3760 void UnmarkObjs(struct HeadObjList *lh){
3761   /*
3762     unmark all objects
3763   */
3764 
3765   struct ObjList *ls;
3766 
3767   if(lh==NULL)return;
3768   ls=lh->list;
3769   while(ls!=NULL){
3770     ls->obj->selected=FALSE;
3771     ls=ls->next;
3772   }
3773   return;
3774 }
3775 
3776 
PrintSelected(struct HeadObjList * lh)3777 int PrintSelected(struct HeadObjList *lh){
3778   /*
3779     printf the selected ships
3780     return the number of selected ships
3781   */
3782 
3783   struct ObjList *ls;
3784   int n=0;
3785 
3786   if(lh==NULL)return(0);
3787   ls=lh->list;
3788   while(ls!=NULL){
3789     if(ls->obj->selected==TRUE){
3790       printf("\t%c %d\n",Type(ls->obj),ls->obj->pid);
3791       n++;
3792     }
3793     ls=ls->next;
3794   }
3795   return n;
3796 }
3797 
NearMaxLevelObj(Object * obj,struct HeadObjList * lh)3798 int NearMaxLevelObj(Object *obj,struct HeadObjList *lh){
3799   /*
3800      Not USED.
3801      return the max level of the objects in the list
3802      that belongs to same player that obj.
3803      pilots are not counted
3804   */
3805 
3806   struct ObjList *ls;
3807   int maxlevel =0;
3808 
3809 
3810   if(lh==NULL)return(0);
3811   ls=lh->list;
3812   while(ls!=NULL){
3813     if(obj==ls->obj){ls=ls->next;continue;}
3814     if(ls->obj->player!=obj->player){ls=ls->next;continue;}
3815     if(ls->obj->type==SHIP && ls->obj->subtype==PILOT){ls=ls->next;continue;}
3816     if(ls->obj->level>maxlevel)maxlevel=ls->obj->level;
3817     ls=ls->next;
3818   } /* while(ls1!=NULL) */
3819   while(ls!=NULL);
3820   return(maxlevel);
3821 }
3822 
IsPlanetEmpty(Object * planet,Object * obj)3823 int IsPlanetEmpty(Object *planet,Object *obj){
3824   /*
3825      don't count obj
3826      don't count pilots
3827      returns:
3828      0 if the planet is totally empty.
3829      1 if there are only allies landed.
3830      2 if there are enemy ships landed.
3831 
3832   */
3833 
3834   struct ObjList *ls;
3835   int gnet;
3836   int ret=0;
3837   struct Player *players;
3838 
3839 
3840   if(obj==NULL)return(-1);
3841   if(planet==NULL)return(-1);
3842   if(planet->player==0)return(0); /* planet never conquered */
3843 
3844   players=GetPlayers();
3845   gnet=GameParametres(GET,GNET,0);
3846   ls=listheadobjs.list;
3847   while(ls!=NULL){
3848     if(ls->obj->in==planet){
3849       if(ls->obj->type!=SHIP){ls=ls->next;continue;}
3850       if(ls->obj->subtype==PILOT){ls=ls->next;continue;}
3851       if(ls->obj->mode!=LANDED){ls=ls->next;continue;}
3852       if(ls->obj==obj){ls=ls->next;continue;}
3853       if(gnet && ls->obj->ttl<MINTTL){ls=ls->next;continue;}
3854       if(ls->obj->state <= 0){ls=ls->next;continue;}
3855       if(players[ls->obj->player].team!=players[obj->player].team){
3856 	return(2);
3857       }
3858       else{
3859 	if(ls->obj->player!=obj->player)ret=1;
3860       }
3861     }
3862     ls=ls->next;
3863   }
3864   return(ret);
3865 }
3866 
UpdateCell(struct HeadObjList * lh,int * cell)3867 int UpdateCell(struct HeadObjList *lh,int *cell){
3868   /*
3869      version 02 080411
3870   */
3871   struct ObjList *ls;
3872   Object *obj;
3873   int n=0;
3874   int dx,dy;
3875   int nx0,ny0,nx,ny;
3876   int nydx;
3877   int dx2,dy2;
3878   int i,j;
3879   int value;
3880   int gnet;
3881   struct Player *players;
3882 
3883   players=GetPlayers();
3884   dx=GameParametres(GET,GULX,0)/DL;
3885   dy=GameParametres(GET,GULY,0)/DL;
3886   dx2=dx/2;
3887   dy2=dy/2;
3888   gnet=GameParametres(GET,GNET,0);
3889   ls=lh->list;
3890   while(ls!=NULL){
3891     if(ls->obj->habitat==H_PLANET){
3892       ls=ls->next;continue;
3893     }
3894 
3895     obj=ls->obj;
3896     switch(obj->type){
3897     case SHIP:
3898       if(gnet==TRUE && obj->ttl<MINTTL){ls=ls->next;continue;}
3899       value=1<<(players[obj->player].team+3);
3900       if(obj->subtype==PILOT)value=4;
3901       break;
3902     case PROJECTILE:
3903       if(obj->subtype==EXPLOSION){
3904 	ls=ls->next;continue;
3905       }
3906       value=1<<(players[obj->player].team+3);
3907       break;
3908     case PLANET:
3909       value=1;
3910       break;
3911     case ASTEROID:
3912       value=2;
3913       break;
3914     default:
3915       ls=ls->next;
3916       continue;
3917       break;
3918     }
3919 
3920     nx0=(obj->x/DL+dx2);
3921     ny0=(obj->y/DL+dy2);
3922 
3923     for(j=-1;j<=1;j++){
3924       ny=ny0+j;
3925       if(ny<0)ny=0;
3926       else{
3927 	if(ny>=dy)ny=dy-1;
3928       }
3929       nydx=ny*dx;
3930 
3931       for(i=-1;i<=1;i++){
3932 	nx=nx0+i;
3933 	if(nx<0)nx=0;
3934 	else{
3935 	  if(nx>=dx)nx=dx-1;
3936 	}
3937 
3938 	if((cell[nx+nydx]&value)==0){
3939 	  cell[nx+nydx]+=value;
3940 	}
3941       }
3942     }
3943     n++;
3944     ls=ls->next;
3945   }
3946   return(n);
3947 }
3948 
3949 
ValueCell(int * cell,Object * obj,int gulx,int guly)3950 int ValueCell(int *cell,Object *obj,int gulx,int guly){
3951   /*
3952     The space is divided in cells usefull to create the lists of
3953     objects.
3954     HERECOM
3955   */
3956 
3957   int x,y;
3958   int dx,dy;
3959   int nx,ny;
3960   int index;
3961 
3962 
3963   if(cell==NULL){
3964     fprintf(stderr,"ERROR: ValueCell(): cell NULL\n");
3965     return(0);
3966   }
3967   if(obj==NULL){
3968     fprintf(stderr,"ERROR: ValueCell(): obj NULL\n");
3969     exit(-1);
3970     return(0);
3971   }
3972 
3973   dx=gulx/DL;
3974   dy=guly/DL;
3975 
3976 
3977   if(obj->habitat==H_PLANET){
3978     x=obj->in->planet->x;
3979     y=obj->in->planet->y;
3980   }
3981   else{
3982     x=obj->x;
3983     y=obj->y;
3984   }
3985 
3986   nx=((int)x+(gulx)/2)/DL;
3987   ny=((int)y+(guly)/2)/DL;
3988   if(nx<0)nx=0;
3989   if(ny<0)ny=0;
3990   if(nx>=dx)nx=dx-1;
3991   if(ny>=dy)ny=dy-1;
3992 
3993   index=nx+ny*dx;
3994 
3995   if(index<0||index>=dx*dy){
3996     fprintf(stderr,"Error in ValueCell()\n");
3997     fprintf(stderr,"\tx:%f y:%f  %d %d\n",obj->x,obj->y,nx,ny);
3998     exit(-1);
3999     return(0);
4000   }
4001   return(cell[index]);
4002 }
4003 
4004 
4005 
ShipProperties(Object * obj,int stype,Object * in)4006 void ShipProperties(Object *obj,int stype,Object *in){
4007   /*
4008     TODO add only physical properties.
4009 
4010   */
4011 
4012   switch(stype){
4013   case EXPLORER: /* EXPLORER */
4014     obj->radar=2*RADAR_RANGE;
4015     obj->gas_max=1000;
4016     obj->gas=obj->gas_max;
4017     obj->shield=0;
4018     obj->state=90;
4019     obj->mass=MASSEXPLORER;
4020     obj->cargo.capacity=30;
4021     obj->radio=10;
4022     obj->ai=1;
4023     obj->damage=25;
4024     obj->cost=COSTEXPLORER*COSTFACTOR;
4025     break;
4026   case SHIP0: /* not used */
4027     /* HERE there are SHIP0 */
4028   case FIGHTER: /*  FIGHTER */
4029     obj->gas_max=1000;
4030     obj->gas=obj->gas_max;
4031     obj->shield=0;
4032     obj->state=90;
4033     obj->mass=MASSFIGHTER;
4034 
4035     if(stype==FIGHTER && obj->level>=MINLEVELPILOT) {
4036       obj->items=obj->items|ITSURVIVAL;
4037     }
4038     obj->cargo.capacity=30;
4039     obj->radio=10;
4040     obj->ai=1;
4041     obj->damage=25;
4042     obj->cost=COSTFIGHTER*COSTFACTOR;
4043 
4044     /*       NewWeapon(&obj->weapon1,CANNON8); */
4045     /*       NewWeapon(&obj->weapon2,CANNON9); */
4046     break;
4047   case QUEEN: /*  cargo queen ship */
4048     obj->radar=3*RADAR_RANGE;
4049     obj->gas_max=2000;
4050     obj->gas=obj->gas_max;
4051     obj->shield=0.9;
4052     obj->state=90;
4053     obj->mass=MASSQUEEN;
4054     obj->cargo.capacity=100;
4055     obj->radio=20;
4056     obj->ai=1;
4057     obj->damage=25;
4058     obj->cost=COSTQUEEN*COSTFACTOR;
4059     break;
4060 
4061   case FREIGHTER: /*  FREIGHTER */
4062     obj->radar=2*RADAR_RANGE;
4063     obj->gas_max=2000;
4064     obj->gas=obj->gas_max;
4065     obj->shield=0.8;
4066     obj->state=90;
4067     obj->mass=MASSFREIGHTER;
4068     obj->cargo.capacity=200;
4069     obj->radio=20;
4070     obj->ai=1;
4071     obj->damage=25;
4072     obj->cost=COSTFREIGHTER*COSTFACTOR;
4073     break;
4074 
4075   case SATELLITE: /* SATELLITE: */
4076     obj->radar=3*RADAR_RANGE;
4077     obj->durable=TRUE;
4078     obj->life=LIFESATELLITE;
4079     obj->gas_max=500;
4080     obj->gas=obj->gas_max;
4081     obj->shield=0;
4082     obj->state=99;
4083     obj->mass=MASSSATELLITE;
4084     obj->damage=10;
4085     obj->cargo.capacity=0;
4086     obj->radio=5;
4087     obj->ai=1;
4088     obj->in=in;
4089     obj->planet=NULL;
4090     obj->cost=COSTSATELLITE*COSTFACTOR;
4091     break;
4092   case TOWER: /* TOWER: */
4093     /*       obj->radar=8*RADAR_RANGE; */
4094     obj->gas_max=1000;
4095     obj->gas=obj->gas_max;
4096     obj->shield=0.5;
4097     obj->state=99;
4098     obj->mass=MASSTOWER;
4099     obj->cargo.capacity=0;
4100     obj->radio=10;
4101     obj->ai=1;
4102     obj->in=in;
4103     obj->damage=25;
4104     obj->cost=COSTTOWER*COSTFACTOR;
4105     break;
4106   case PILOT: /* PILOT */
4107     obj->gas_max=0;
4108     obj->gas=obj->gas_max;
4109     /* obj->shield=0; keep shield */
4110     obj->state=100;
4111     obj->mass=MASSPILOT;
4112     obj->cargo.capacity=0;
4113     obj->radio=10;
4114     obj->ai=0;
4115     /*    obj->habitat=obj->parent->habitat; */
4116     obj->in=in;
4117     obj->damage=5;
4118     obj->cost=COSTPILOT*COSTFACTOR;
4119     break;
4120 
4121   case GOODS: /* GOODS */
4122     obj->radar=0;
4123     obj->durable=TRUE;
4124     obj->life=LIFEGOODS;
4125     obj->gas_max=0;
4126     obj->gas=obj->gas_max;
4127     obj->shield=0;
4128     obj->state=99;
4129     obj->mass=MASSGOODS;
4130     obj->damage=5;
4131     obj->cargo.capacity=0;
4132     obj->radio=2;
4133     obj->ai=0;
4134     obj->in=in;
4135     obj->planet=NULL;
4136     obj->cost=COSTGOODS*COSTFACTOR;
4137     break;
4138 
4139   default:
4140     fprintf(stderr,"ERROR ShipProperties(): unknown subtype %d\n",stype);
4141     exit(-1);
4142     break;
4143   }
4144 }
4145 
4146 
CreatePilot(Object * obj)4147 int CreatePilot( Object *obj){
4148 
4149   /*
4150     when the ship obj is destroyed and it has a survival pod it is
4151     ejected.
4152     returns:
4153     0 if the ship has not a survival pod
4154     1 if its created.
4155   */
4156 
4157   if(obj==NULL)return(0);
4158   if((obj->items & ITSURVIVAL)==0)return(0);
4159 
4160   /* check */
4161   if(obj->type==SHIP && obj->subtype!=FIGHTER){
4162     fprintf(stderr,"ERROR in CreatePilot() type: %d stype: %d\n",obj->type,obj->subtype);
4163     fprintf(stderr,"\t pilot not created\n");
4164     return(0);
4165   }
4166 
4167   obj->gas=500;
4168   if(obj->habitat==H_PLANET){
4169     obj->y+=20;
4170     obj->vy+=10;
4171     if(obj->vy<10)obj->vy=10;
4172     obj->mode=NAV;
4173   }
4174   if(obj->habitat==H_SPACE){
4175     obj->vx=obj->vx*.65+4*Random(-1)-2;
4176     obj->vy=obj->vy*.65+4*Random(-1)-2;
4177   }
4178 
4179   obj->subtype=PILOT;
4180   ShipProperties(obj,obj->subtype,obj->in);
4181   obj->items=0;
4182   obj->ai=0;
4183   obj->accel=0;
4184   obj->ang_a=0;
4185   obj->damage=5;
4186   obj->durable=TRUE;
4187   obj->life=LIFEPILOT;
4188   obj->radio=10;
4189 
4190   obj->state=100;
4191   obj->weapon0.n=0;
4192   obj->weapon1.n=0;
4193   obj->weapon2.n=0;
4194   return(1);
4195 }
4196 
4197 
CountSelected(struct HeadObjList * lh,int player)4198 int CountSelected(struct HeadObjList *lh,int player){
4199   /*
4200     printf the selected ships
4201     return the number of selected ships
4202   */
4203 
4204   struct ObjList *ls;
4205   int n=0;
4206 
4207   if(lh==NULL)return(0);
4208   ls=lh->list;
4209   while(ls!=NULL){
4210     if(ls->obj->selected==TRUE && ls->obj->player==player){
4211       n++;
4212     }
4213     ls=ls->next;
4214   }
4215   return n;
4216 }
CountNSelected(struct HeadObjList * lh,int player)4217 int CountNSelected(struct HeadObjList *lh,int player){
4218   /*
4219     Count the number of selected objects.
4220     returns:
4221     0 if no objects selected.
4222     1 one object selected.
4223     2 more than one object selected.
4224   */
4225 
4226   struct ObjList *ls;
4227   int n=0;
4228 
4229   ls=lh->list;
4230   while(ls!=NULL){
4231     if(ls->obj->player!=player || ls->obj->type!=SHIP){ls=ls->next;continue;}
4232     if(ls->obj->selected==TRUE){
4233       n++;
4234       if(n>1)return(2);
4235     }
4236     ls=ls->next;
4237   }
4238   return(n);
4239 }
4240 
4241 
FirstSelected(struct HeadObjList * lh,int player)4242 Object *FirstSelected(struct HeadObjList *lh,int player){
4243   /*
4244     printf the selected ships
4245     return the first selected ship
4246   */
4247 
4248   struct ObjList *ls;
4249 
4250   if(lh==NULL)return(0);
4251   ls=lh->list;
4252   while(ls!=NULL){
4253     if(ls->obj->selected==TRUE && ls->obj->player==player){
4254       return(ls->obj);
4255     }
4256     ls=ls->next;
4257   }
4258   return(NULL);
4259 }
4260 
Distance2(Object * obj1,Object * obj2)4261 float Distance2(Object *obj1,Object *obj2){
4262   /*
4263     version 0.2
4264     Calc the distance between 2 objects.
4265     Returns:
4266     distance pow 2
4267   */
4268 
4269   float x1,x2,y1,y2,rx,ry,r2;
4270 
4271   if(obj1==NULL)return(-1);
4272   if(obj2==NULL)return(-1);
4273 
4274   if(obj1->habitat==H_SHIP)obj1=obj1->in;
4275   if(obj2->habitat==H_SHIP)obj2=obj2->in;
4276 
4277 
4278   if(obj1->in==obj2->in){
4279     x1=obj1->x;
4280     y1=obj1->y;
4281     x2=obj2->x;
4282     y2=obj2->y;
4283   }
4284   else{
4285     switch(obj1->habitat){
4286     case H_PLANET:
4287       x1=obj1->in->x;
4288       y1=obj1->in->y;
4289       break;
4290     case H_SPACE:
4291       x1=obj1->x;
4292       y1=obj1->y;
4293       break;
4294     default:
4295       fprintf(stderr,"ERROR in AreEnemy() habitat unknown\n");
4296       exit(-1);
4297     }
4298 
4299     switch(obj2->habitat){
4300     case H_PLANET:
4301       x2=obj2->in->x;
4302       y2=obj2->in->y;
4303       break;
4304     case H_SPACE:
4305       x2=obj2->x;
4306       y2=obj2->y;
4307       break;
4308     default:
4309       fprintf(stderr,"ERROR in AreEnemy() habitat unknown\n");
4310       exit(-1);
4311     }
4312   }
4313 
4314   rx=x1 - x2;
4315   ry=y1 - y2;
4316   r2=rx*rx+ry*ry;
4317   return(r2);
4318 }
4319 
GameOver(struct HeadObjList * lhead,struct Player * players,int player)4320 int GameOver(struct HeadObjList *lhead,struct Player *players,int player){
4321   /*
4322      Conditions for GAME OVER :
4323      -no ships or (only pilots and gold less than 1100)
4324   */
4325   int n=0;
4326   n=CountObjs(lhead,player,SHIP,-1);
4327   if(n==0)return(1);
4328 
4329   if(players[player].gold<GetPrice(NULL,FIGHTER,ENGINE4,CANNON4)){
4330     if(n==CountObjs(lhead,player,SHIP,PILOT)){ /* there are only pilots */
4331       return(1);
4332     }
4333   }
4334   return(0);
4335 }
4336 
CheckObjsId(void)4337 int CheckObjsId(void){
4338   /* check if 2 objects has the same id */
4339 
4340   struct ObjList *ls;
4341   int *tabla;
4342   int i,j,n,id_i;
4343 
4344   n=listheadobjs.n;
4345 
4346   tabla=malloc(n*sizeof(int));
4347   if(tabla==NULL){
4348     fprintf(stderr,"ERROR in malloc Check()\n");
4349     exit(-1);
4350   }
4351 
4352   for(i=0;i<n;i++){
4353     tabla[i]=0;
4354   }
4355 
4356   ls=listheadobjs.list;
4357   for(i=0;i<n;i++){
4358     tabla[i]=ls->obj->id;
4359     ls=ls->next;
4360   }
4361 
4362   for(i=0;i<n-1;i++){
4363     id_i=tabla[i];
4364     for(j=i+1;j<n;j++){
4365       if(tabla[j]==id_i && id_i !=-1){
4366 	printf("Check(): indice duplicado: i: %d j:%d id:%d \n",i,j,id_i);
4367       }
4368     }
4369   }
4370   free(tabla);
4371   tabla=NULL;
4372   return(0);
4373 }
4374 
4375 
4376 /*********/
4377 /* Cargo */
4378 /*********/
4379 
CargoAdd(Object * obj1,Object * obj2)4380 int CargoAdd(Object *obj1,Object *obj2){
4381   /*
4382     Add obj2 to obj1 cargo list
4383     returns:
4384     0 if there are no room, is already in list
4385     1 if obj2 is added
4386   */
4387 
4388   struct Player *players;
4389 
4390   players=GetPlayers();
4391 
4392   if(obj1==NULL || obj2==NULL){
4393     return(0);
4394   }
4395 
4396   if(CargoIsObj(obj1,obj2)){
4397     printf("CargoAdd: already in list\n");
4398     return(0);
4399   }
4400 
4401   if(obj1->cargo.capacity==0)return(0);
4402 
4403   if(obj1->cargo.mass + obj2->mass + obj2->cargo.mass > obj1->cargo.capacity){
4404     fprintf(stderr,"No room for %d in %d %d %d\n",
4405 	    obj2->id,obj1->id,
4406 	    obj2->mass+obj2->cargo.mass,obj1->cargo.capacity);
4407     return(0);
4408   }
4409 
4410 
4411   if(players[obj1->player].team != players[obj2->player].team){
4412     fprintf(stderr,"ERROR in CargoAdd()\n");
4413     fprintf(stderr,"\t%d %d %d %d, %d %d %d %d\n",
4414 	    players[obj1->player].team,obj1->player,obj1->type,obj1->subtype,
4415 	    players[obj2->player].team,obj2->player,obj2->type,obj2->subtype);
4416     exit(-1);
4417   }
4418 
4419   if(obj1->cargo.hlist==NULL){
4420     obj1->cargo.hlist = malloc(sizeof(struct HeadObjList));
4421     if(obj1->cargo.hlist==NULL){
4422       fprintf(stderr,"ERROR in malloc CargoAdd\n");
4423       exit(-1);
4424     }
4425     MemUsed(MADD,sizeof(struct HeadObjList));
4426     obj1->cargo.hlist->n=0;
4427     obj1->cargo.hlist->update=0;
4428     obj1->cargo.hlist->list=NULL;
4429   }
4430 
4431   Add2ObjList(obj1->cargo.hlist,obj2);
4432 
4433   obj1->cargo.mass+=obj2->mass + obj2->cargo.mass;
4434 
4435   obj1->cargo.n++;
4436 
4437   return(1);
4438 }
4439 
4440 
CargoGet(Object * obj1,int type,int subtype)4441 Object *CargoGet(Object *obj1,int type,int subtype){
4442 
4443   /*
4444     Remove the first obj of type type from obj1 cargo list
4445     returns:
4446     a pointer to the removed object.
4447   */
4448 
4449   struct ObjList *ls;
4450   Object *obj0;
4451 
4452   if(obj1==NULL){
4453     return(NULL);
4454   }
4455   if(obj1->cargo.hlist==NULL){
4456     return(NULL);
4457   }
4458 
4459   ls=obj1->cargo.hlist->list;
4460   while(ls!=NULL){
4461 
4462     if(ls->obj->type==type && ls->obj->subtype==subtype){
4463       obj0=ls->obj;
4464       CargoRem(obj1,ls->obj);
4465       return(obj0);
4466     }
4467     ls=ls->next;
4468   }
4469   return(NULL);
4470 }
4471 
4472 
4473 
CargoRem(Object * obj1,Object * obj2)4474 int CargoRem(Object *obj1,Object *obj2){
4475 
4476   /*
4477     Remove obj2 from obj1 cargo list
4478     returns:
4479     the number of elements removed.
4480   */
4481 
4482   struct ObjList *ls0,*ls;
4483 
4484   if(obj1==NULL){
4485     return(0);
4486   }
4487   if(obj2==NULL){
4488     return(0);
4489   }
4490   if(obj1->cargo.hlist==NULL){
4491     return(0);
4492   }
4493 
4494   ls=obj1->cargo.hlist->list;
4495   ls0=ls;
4496 
4497 
4498   while(ls!=NULL){
4499 
4500     if(ls->obj==obj2){
4501       if(ls==ls0){ /* first element */
4502 	obj1->cargo.hlist->list=ls->next;
4503 	free(ls);
4504 	ls=NULL;
4505 	obj1->cargo.n--;
4506 	obj1->cargo.mass-=obj2->mass-obj2->cargo.mass;
4507 	if(obj1->cargo.n==0){
4508 	  free(obj1->cargo.hlist);
4509 	  obj1->cargo.hlist=NULL;
4510 	}
4511 	return(1);
4512       }
4513       ls0->next=ls->next;
4514       obj1->cargo.n--;
4515       obj1->cargo.mass-=obj2->mass-obj2->cargo.mass;
4516       free(ls);
4517       ls=NULL;
4518       if(obj1->cargo.n==0){
4519 	free(obj1->cargo.hlist);
4520 	obj1->cargo.hlist=NULL;
4521       }
4522       return(1);
4523     }
4524     ls0=ls;
4525     ls=ls->next;
4526   }
4527   return(0);
4528 }
4529 
4530 
CargoCheck(struct HeadObjList * hol,Object * cvobj)4531 void CargoCheck(struct HeadObjList *hol,Object *cvobj){
4532   /*
4533      check if  destroyed or solded ship has objects.
4534   */
4535 
4536   struct ObjList *ls;
4537   int sw=0;
4538   int gnet;
4539   int proc=0;
4540   struct Player *players;
4541 
4542   players=GetPlayers();
4543 
4544   ls=hol->list;
4545   gnet=GameParametres(GET,GNET,0);
4546   proc=GetProc();
4547 
4548   while(ls!=NULL){
4549     sw=0;
4550     if(proc!=players[ls->obj->player].proc){ls=ls->next;continue;}
4551 
4552     if(ls->obj->state<=0){
4553       sw=1;
4554     }
4555 
4556     if(sw&& (ls->obj->cargo.hlist!=NULL)){
4557       CargoEjectObjs(ls->obj,-1,-1);
4558       /* ls->obj->items=(ls->obj->items)&(~ITPILOT); */
4559     }
4560 
4561     /***** ship destroyed Create Pilot****/
4562     if(sw && (ls->obj->items & ITSURVIVAL)){
4563       sw=0;
4564       /* GetPointsObj(hol,players,ls->obj);/\* points and experience *\/ */
4565       if(CreatePilot(ls->obj)){
4566 	Explosion(&listheadobjs,cvobj,ls->obj,0);
4567 #if SOUND
4568 	if(ls->obj->habitat==H_PLANET)
4569 	  Play(ls->obj,EXPLOSION0,1);
4570 #endif
4571 	if(ls->obj->player==actual_player){
4572 	  printf("%s %d\n",GetLocale(L_EJECTING),ls->obj->pid);
4573 	}
4574       }
4575 
4576       DelAllOrder(ls->obj);
4577       if(gnet==TRUE){
4578 	ls->obj->modified=SENDOBJALL;
4579       }
4580     }
4581     ls=ls->next;
4582   }
4583   return;
4584 }
4585 
4586 
CargoDestroy(Object * obj)4587 int CargoDestroy(Object *obj){
4588   /*
4589     use when load a game
4590     remove all the cargo list
4591     returns:
4592     the number of elements removed from list.
4593   */
4594   struct ObjList *ls,*ls0;
4595   int n=0;
4596 
4597   if(obj==NULL){
4598     return(0);
4599   }
4600   if(obj->cargo.hlist==NULL){
4601     return(0);
4602   }
4603 
4604   ls=obj->cargo.hlist->list;
4605 
4606   while(ls!=NULL){
4607     n++;
4608     ls0=ls;
4609 
4610     /* ls->obj->in=obj->in; */
4611     /* ls->obj->habitat=obj->habitat; */
4612 
4613     ls=ls->next;
4614     free(ls0);
4615     ls0= NULL;
4616   }
4617   free(obj->cargo.hlist);
4618   obj->cargo.hlist=NULL;
4619   obj->cargo.n=0;
4620   obj->cargo.mass=0;
4621   return(n);
4622 }
4623 
4624 
4625 
CargoEjectObjs(Object * obj,int type,int subtype)4626 int CargoEjectObjs(Object *obj,int type,int subtype){
4627   /*
4628     Eject objects from ship obj cargo list.
4629 
4630     if obj is dead:
4631         obj LANDED: Rescue pilots, destroy other objects.
4632 	obj is NAVigating: eject all.
4633 
4634     if obj is not dead:
4635         obj LANDED: Rescue pilots, keep other objects.
4636 	obj is NAVigating: eject all.
4637 
4638     if type and subtype are different of -1: only eject that type objects.
4639 
4640     returns:
4641     the number of objects ejected.
4642   */
4643 
4644   struct ObjList *ls;
4645   Object *obj1;       /* object in cargo list */
4646   Segment *s;
4647   float r;
4648   int n=0;
4649   int gnet;
4650   int sw=0;
4651 
4652   int rescuepilots=0;
4653   int keepothers=0;
4654   int destroyothers=0;
4655   int ejectall=0;
4656 
4657   if(obj==NULL)return(0);
4658   if(obj->cargo.hlist==NULL)return(0);
4659 
4660 
4661   if(type!=-1 && subtype !=-1)sw=1;  /* eject all */
4662   gnet=GameParametres(GET,GNET,0);
4663   ls=obj->cargo.hlist->list;
4664   while(ls!=NULL){
4665 
4666     obj1=ls->obj;
4667     if(obj1->in!=obj){
4668       fprintf(stderr,"ERROR CargoEjectObjs(): not in. Ejecting anyway...\n");
4669     }
4670     if(sw){
4671       if(obj1->type!=type || obj1->subtype!=subtype){
4672 	ls=ls->next;continue;
4673       }
4674     }
4675 
4676     switch(obj->mode){
4677     case LANDED:
4678       if(obj->state>0){
4679 	rescuepilots=1;
4680 	keepothers=1;
4681       }
4682       else{
4683 	rescuepilots=1;
4684 	destroyothers=1;
4685       }
4686       break;
4687     case NAV:
4688       ejectall=1;
4689       break;
4690     case SOLD:
4691       rescuepilots=1;
4692       destroyothers=1;
4693       break;
4694     default:
4695       fprintf(stderr,"Not implemented. CargoEjectObjs() %d\n",obj->mode);
4696       exit(-1);
4697       break;
4698 
4699     }
4700 
4701     if(ejectall){
4702       obj1->in=obj->in;
4703       obj1->planet=NULL;
4704       obj1->habitat=obj->habitat;
4705       obj1->mode=NAV;
4706       obj1->x=obj->x;
4707       obj1->y=obj->y;
4708       obj1->vx=0.75*obj->vx+6*Random(-1)-3;
4709       if(obj->habitat==H_PLANET){
4710 	obj1->vy=fabs(0.75*obj->vy+6*Random(-1)-3)+10;
4711       }
4712       else{
4713 	obj1->vy=0.75*obj->vy+6*Random(-1)-3;
4714       }
4715       obj1->a=obj->a;
4716       obj1->ai=0;
4717       obj1->items=0;
4718       if(obj1->player==actual_player)printf("Pilot %d ejected from ship %d\n",obj1->pid,obj->pid);
4719 
4720       DelAllOrder(obj1);
4721       CargoRem(obj,obj1);
4722       if(gnet==TRUE){
4723 	SetModified(obj1,SENDOBJALL);
4724 	if(obj1->modified!=SENDOBJALL){
4725 	  printf("PILOT EJECT mod: %d\n",obj1->modified);
4726 	}
4727       }
4728       n++;
4729       ls=ls->next;continue;
4730     }
4731 
4732 
4733 
4734     if(obj1->type==SHIP && obj1->subtype==PILOT){
4735       if(rescuepilots){
4736 	s=LandZone(obj->in->planet);
4737 
4738 	if(s==NULL){
4739 	  fprintf(stderr,"ERROR EjectPilots(): Segment==NULL\n");
4740 	  exit(-1);
4741 	}
4742 	r=s->x1-s->x0-2*obj1->radio;
4743 	obj1->in=obj->in;
4744 	obj1->habitat=H_PLANET;
4745 	obj1->experience=0;
4746 	obj1->pexperience=0;
4747 	obj1->planet=NULL;
4748 	obj1->mode=LANDED;
4749 	obj1->x=s->x0+obj1->radio+r*(Random(-1));
4750 	obj1->y=obj->y;
4751 	obj1->x0=obj1->x;
4752 	obj1->y0=obj1->y;
4753 	obj1->accel=0;
4754 	obj1->ang_v=obj1->ang_a=0;
4755 	obj1->vx=obj1->vy=0;
4756 	obj1->a=0;
4757 	obj1->ai=0;
4758 	obj1->items=0;
4759 	/* pilot->selected=FALSE; */
4760 	Experience(obj,obj1->level*30); /* experience for rescue a pilot*/
4761 	if(obj1->player==actual_player){
4762 	  printf("%s %d %s %d\n",
4763 		 GetLocale(L_PILOT),
4764 		 obj1->pid,
4765 		 GetLocale(L_SAVEDINPLANET),
4766 		 obj1->in->id);
4767 	}
4768 	DelAllOrder(obj1);
4769 	CargoRem(obj,obj1);
4770 	if(gnet==TRUE){
4771 	  SetModified(obj1,SENDOBJALL);
4772 	}
4773 	n++;
4774 
4775       }
4776     }
4777     else{ /* it is not a PILOT */
4778       if(keepothers){
4779 
4780       }
4781       if(destroyothers){
4782 	/* destroy rest of the objects */
4783 	obj1->in=obj->in;
4784 	obj1->planet=NULL;
4785 	obj1->habitat=obj->habitat;
4786 	obj1->mode=NAV;
4787 	obj1->state=0;
4788 	DelAllOrder(obj1);
4789 	CargoRem(obj,obj1);
4790 	printf("OBJ %d EJECT %d\n",obj1->pid,obj->subtype);
4791 	if(gnet==TRUE){
4792 	  SetModified(obj1,SENDOBJALL);
4793 	  if(obj1->modified!=SENDOBJALL){
4794 	    printf("OBJ EJECT mod: %d\n",obj1->modified);
4795 	  }
4796 	}
4797 	n++;
4798       }
4799     }
4800     ls=ls->next;
4801   }
4802   return(n);
4803 }
4804 
4805 
CargoIsObj(Object * obj,Object * obj2)4806 int CargoIsObj(Object *obj,Object *obj2){
4807   /*
4808     look for obj2 in obj cargo list
4809     returns:
4810     1 if is in the list
4811     0 if not.
4812   */
4813   struct ObjList *ls;
4814 
4815   if(obj->cargo.hlist==NULL || obj==NULL || obj2==NULL){
4816     return(0);
4817   }
4818 
4819   if(obj->cargo.n<=0){
4820     fprintf(stderr,"ERROR in cargo list %d %d (%d,%d) %f\n",
4821 	    obj->player,obj->id,
4822 	    obj->type,obj->subtype,
4823 	    obj->state);
4824     fprintf(stderr,"\tERROR in cargo list %d %d (%d,%d) %f\n",
4825 	    obj2->player,obj2->id,
4826 	    obj2->type,obj2->subtype,
4827 	    obj2->state);
4828   }
4829   ls=obj->cargo.hlist->list;
4830 
4831   while(ls!=NULL){
4832     if(ls->obj==obj2)return(1);
4833     ls=ls->next;
4834   }
4835   return(0);
4836 }
4837 
4838 
CargoPrint(Object * obj)4839 int CargoPrint(Object *obj){
4840   /*
4841     Print cargo listremove all the cargo list
4842     returns:
4843     the number of elements of the list.
4844   */
4845   struct ObjList *ls;
4846   int n=0;
4847 
4848   if(obj==NULL){
4849     return(0);
4850   }
4851   if(obj->cargo.hlist==NULL){
4852     printf("cargo: %d %d(%d)\n",obj->id,obj->pid,obj->cargo.n);
4853     return(0);
4854   }
4855 
4856   ls=obj->cargo.hlist->list;
4857 
4858   printf("cargo: %d (%d,%d,%d)->",obj->id,
4859 	 obj->cargo.mass,obj->cargo.capacity,
4860 	 obj->cargo.n);
4861   while(ls!=NULL){
4862     n++;
4863     printf("%d %d,",ls->obj->id,ls->obj->pid);
4864     ls=ls->next;
4865   }
4866   printf("\n");
4867   return(n);
4868 }
4869 
CargoGetMass(Object * obj)4870 int CargoGetMass(Object *obj){
4871   /*
4872     Get the total mass of the objects in cargo. Don't count goods
4873     returns:
4874     the mass of cargo.
4875   */
4876   struct ObjList *ls;
4877   int mass=0;
4878 
4879   if(obj==NULL){
4880     return(0);
4881   }
4882   if(obj->cargo.hlist==NULL){
4883     return(0);
4884   }
4885 
4886   ls=obj->cargo.hlist->list;
4887 
4888   while(ls!=NULL){
4889     mass+=ls->obj->mass;
4890     ls=ls->next;
4891   }
4892   return(mass);
4893 }
4894 
4895 
4896 
CargoBuild(Object * obj)4897 int CargoBuild(Object *obj){
4898 
4899   /*
4900     Build the cargo list of object obj
4901   */
4902 
4903   struct ObjList *ls;
4904 
4905   ls=listheadobjs.list;
4906   while(ls!=NULL){
4907     switch(ls->obj->habitat){
4908     case H_PLANET:
4909     case H_SPACE:
4910       break;
4911     case H_SHIP:
4912       if(ls->obj->in==obj){
4913 	CargoAdd(obj,ls->obj);
4914       }
4915       break;
4916     default:
4917       exit(-1);
4918     }
4919     ls=ls->next;
4920   }
4921 
4922 
4923   return(0);
4924 }
4925 
4926