#include "galaxy.h"

/* thie file contains the loadgame() function and support functions.
   requires functions from util.c */


/* internal globals */

int             lastc;

/* internal functions */

int      rc _PROTO((void));
void     rs _PROTO((char *s));
int      ri _PROTO((void));
double   rf _PROTO((void));
void     rtext _PROTO((strlist ** sp));


#ifdef __STDC__
int
rc (void)
#else
int
rc ()
#endif
{
   lastc = fgetc(f);
   assert(lastc != (char)EOF);
   return lastc;
}

#ifdef __STDC__
void 
rs (char *s)
#else
void 
rs (s)
char *s;
#endif
{
   if (lastc == ',') {
      rc();
      if (isspace(lastc)) {
         *s = 0;
         return;
      }
   }
   while (isspace(lastc))
      rc();
   while (!isspace(lastc) && lastc != ',') {
      if (lastc == '_')
         lastc = ' ';
      *s++ = lastc;
      rc();
   }
   *s = 0;
}

#ifdef __STDC__
int
ri (void)
#else
int
ri ()
#endif
{
   rs(buf);
   return atoi(buf);
}

#ifdef __STDC__
double 
rf (void)
#else
double 
rf ()
#endif
{
   rs(buf);
   return atof(buf);
}


#ifdef __STDC__
void 
rtext (strlist ** sp)
#else
void 
rtext (sp)
strlist ** sp;
#endif
{
   int             i;
   strlist        *s;

   while (lastc != '\n')
      rc();
   for (;;) {
      getbuf();
      for (i = 0; isspace(buf[i]); i++);
      if (buf[i] == '@')
         break;
      s = makestrlist(buf);
      addlist2(sp, s);
   }
   *sp = 0;
}



#ifdef __STDC__
int
loadgame (char *gamename)
#else
int
loadgame (gamename)
char  		  *gamename;
#endif
{
   char           *F;
   int             maxno, i;
   planet         *p, **pp;
   player         *P, **Pp;
   alliance       *a, **ap;
   group          *g, **gp;
   shiptype       *t, **tp;
   fleetname      *fl,**fp;
   battle         *b, **bp;
   bombing        *B, **Bp;
   participant    *r, **rp;
   Aplanet        *Ap, *Aplanets, **App;
   Aalliance      *Aa, *Aalliances, **Aap;

   sprintf(buf, "data/%s", gamename);
   F = findfirst(buf);
   if (!F) {
/*      printf("No turn files for game %s\n", gamename);
      gamename[0] = 0; */
      return 1;
   }
   maxno = 0;
   do {
      i = atoi(F);
      if (i > maxno)
         maxno = i;
      F = findnext();
   }
   while (F);

   sprintf(buf, "data/%s/%d", gamename, maxno);
   f = Fopen(buf, "r");
/*   printf("Loading game %s turn %d...\n", gamename, maxno); */
   lastc = ' ';

   turn = ri();
   if (turn != maxno)
/*      printf("Warning, file %d is actually for turn %d\n", maxno, turn); */
   galaxysize = rf();

   rtext(&messages);

   pp = &planets;
   App = &Aplanets;
   Aplanets = 0;
   for (;;) {
      rs(buf);
      if (buf[0] == '@')
         break;
      p = alloc(sizeof(planet));
      Ap = alloc(sizeof(Aplanet));
      Ap->p = p;
      strcpy(p->name, buf);
      rs(Ap->ownername);
      p->x = rf();
      p->y = rf();
      p->size = rf();
      p->resources = rf();
      p->pop = rf();
      p->ind = rf();
      p->producing = ri();
      rs(Ap->producingshiptypename);
      p->cap = rf();
      p->mat = rf();
      p->col = rf();
      p->inprogress = rf();
      p->spent = 0;
      for (i = 0; i != MAXCARGO; i++)
         rs(Ap->routenames[i]);
      addlist2(pp, p);
      addlist2(App, Ap);
   }
   *pp = 0;
   *App = 0;

   Pp = &players;
   Aap = &Aalliances;
   Aalliances = 0;
   for (;;) {
      rs(buf);
      if (buf[0] == '@')
         break;
      P = alloc(sizeof(player));
      strcpy(P->name, buf);
      rs(P->addr);
      rs(P->pswd);
      P->pswdstate = 0;
      P->drive = rf();
      P->weapons = rf();
      P->shields = rf();
      P->cargo = rf();
      P->mx = rf();
      P->my = rf();
      P->msize = rf();
      P->prodtable = ri ();
      P->autounload = ri ();
      P->fleettables = ri();
      P->sortgroups = ri();
      P->underscores = ri();
      P->twocol = ri();
      P->namecase = ri();
      P->lastorders = ri();
      P->orders = 0;

      tp = &P->shiptypes;
      for (;;) {
         rs(buf);
         if (buf[0] == '@')
            break;
         t = alloc(sizeof(shiptype));
         strcpy(t->name, buf);
         t->drive = rf();
         t->attacks = ri();
         t->weapons = rf();
         t->shields = rf();
         t->cargo = rf();
         addlist2(tp, t);
      }
      *tp = 0;

      fp = &P->fleetnames;
      for (;;) {
	 rs (buf);
	 if (buf[0] == '@')
	    break;
         fl = alloc (sizeof (fleetname));
	 strcpy (fl->name, buf);
	 fl->fleetspeed = 1000.0;
	 addlist2 (fp, fl);
      }
      *fp = 0;

      /* End of Fleet Stuff */

      ap = &P->allies;
      for (;;) {
         rs(buf);
         if (buf[0] == '@')
            break;
         a = alloc(sizeof(alliance));
         Aa = alloc(sizeof(Aalliance));
         Aa->a = a;
         strcpy(Aa->whoname, buf);
         addlist2(ap, a);
         addlist2(Aap, Aa);
      }
      *ap = 0;

      gp = &P->groups;
      for (;;) {
         rs(buf);
         if (buf[0] == '@')
            break;
         g = alloc(sizeof(group));
         g->type = nametop(P->shiptypes, buf);
         assert(g->type);
         g->drive = rf();
         g->weapons = rf();
         g->shields = rf();
         g->cargo = rf();
         g->loadtype = ri();
         g->load = rf();
         rs(buf);
         g->from = nametop(planets, buf);
         assert(g->from);
         rs(buf);
         g->where = nametop(planets, buf);
         assert(g->where);
         g->dist = rf();
         g->ships = ri();

	 rs(buf);
	 if (buf[0]) {
	    fl = identify (P->fleetnames, buf);
	    g->thefleet = fl;
         }
	 else
	    g->thefleet = 0;

         addlist2(gp, g);
      }
      *gp = 0;

      rtext(&P->messages);

      rtext(&P->mistakes);

      addlist2(Pp, P);
   }
   *Pp = 0;
   *Aap = 0;

   bp = &battles;
   for (;;) {
      rs(buf);
      if (buf[0] == '@')
         break;
      b = alloc(sizeof(battle));
      b->where = nametop(planets, buf);
      assert(b->where);

      rp = &b->participants;
      for (;;) {
         rs(buf);
         if (buf[0] == '@')
            break;
         r = alloc(sizeof(participant));
         r->who = nametop(players, buf);
         assert(r->who);

         gp = &r->groups;
         for (;;) {
            rs(buf);
            if (buf[0] == '@')
               break;
            g = alloc(sizeof(group));
            g->type = nametop(r->who->shiptypes, buf);
            assert(g->type);
            g->drive = rf();
            g->weapons = rf();
            g->shields = rf();
            g->cargo = rf();
            g->loadtype = ri();
            g->load = rf();
            g->ships = ri();
            g->left = ri();
            addlist2(gp, g);
         }
         *gp = 0;

         addlist2(rp, r);
      }
      *rp = 0;

      addlist2(bp, b);
   }
   *bp = 0;

   Bp = &bombings;
   for (;;) {
      rs(buf);
      if (buf[0] == '@')
         break;
      B = alloc(sizeof(bombing));
      B->who = nametop(players, buf);
      assert(B->who);
      rs(B->name);
      rs(buf);
      B->owner = nametop(players, buf);
      assert(B->owner);
      B->pop = rf();
      B->ind = rf();
      B->producing = ri();
      rs(buf);
      B->producingshiptype = nametop(B->owner->shiptypes, buf);
      B->cap = rf();
      B->mat = rf();
      B->col = rf();

      ap = &B->viewers;
      for (;;) {
         rs(buf);
         if (buf[0] == '@')
            break;
         a = alloc(sizeof(alliance));
         a->who = nametop(players, buf);
         assert(a->who);
         addlist2(ap, a);
      }
      *ap = 0;

      addlist2(Bp, B);
   }
   *Bp = 0;

   fclose(f);

   for (Ap = Aplanets; Ap; Ap = Ap->next) {
      p = Ap->p;
      p->owner = nametop(players, Ap->ownername);
      p->producingshiptype = 0;
      if (p->owner)
         p->producingshiptype = nametop(p->owner->shiptypes, Ap->producingshiptypename);
      assert(p->producing != PR_SHIP || p->producingshiptype);
      for (i = 0; i != MAXCARGO; i++)
         p->routes[i] = nametop(planets, Ap->routenames[i]);
   }
   freelist(Aplanets);

   for (Aa = Aalliances; Aa; Aa = Aa->next) {
      Aa->a->who = nametop(players, Aa->whoname);
      assert(Aa->a->who);
   }
   freelist(Aalliances);

   return 0;
}
