Generated from phase.c with ROBODoc v3.2.2 on Sun Aug 27 19:47:34 2000

TABLE OF CONTENTS

  1. GalaxyNG/Phase
  2. Phase/bombPlanet
  3. Phase/bombphase
  4. Phase/cktech
  5. Phase/convertcap
  6. Phase/determineOwnership
  7. Phase/fleetphase
  8. Phase/ftrunc2
  9. Phase/interceptphase
  10. Phase/joinphase
  11. Phase/kill
  12. Phase/loadphase
  13. Phase/movephase
  14. Phase/mustBomb
  15. Phase/nametocargotype
  16. Phase/produceMatCap
  17. Phase/producePopulation
  18. Phase/produceShip
  19. Phase/produceTechnology
  20. Phase/producephase
  21. Phase/sortphase
  22. Phase/unloadcap
  23. Phase/unloadcol
  24. Phase/unloadgroup
  25. Phase/unloadphase

GalaxyNG/Phase

NAME
   Phase -- functions to compute the different phases in a turn.
BUGS
   At the moment the intercept phase is pretty buggy.
   If there are loops or paths, that is a group intercepts
   on a planet where there are groups that intercept an 
   another planet the outcome of the algorithm is pretty random.

Phase/bombPlanet

NAME
   bombPlanet -- bomb a planet.
FUNCTION
   Depending on the preferences of the GM all live and industry
   on the planet is 
   (a) completely destroyed, cap and mat are wiped out too.
   (b) reduced to 25%,  cap and mat are untouched.
SOURCE
    void
    bombPlanet(game *aGame, planet *p)
    {
      p->col = 0;
      p->producing = PR_CAP;
      p->producingshiptype = 0;
      p->inprogress = 0;
      memset(p->routes, 0, sizeof(p->routes));
    
      if (aGame->gameOptions & GAME_NONGBOMBING) {
        p->pop = 0;
        p->ind = 0;
        p->cap = 0;
        p->mat = 0;
        p->spent = 0;
      }
      else {
        p->pop = p->pop * 0.25;
        p->ind = p->ind * 0.25;
        p->spent = 0;
        convertcap(p);
      }
    }    

Phase/bombphase

NAME
   bombphase -- bomb planets
SYNOPSIS
   void bombphase(game *aGame)
FUNCTION
   Examine which nations have armed ships over a planet.
   If there are any, the planets are bombed and it is 
   determined who should own the planet.
SOURCE
    void
    bombphase(game *aGame)
    {
      player         *aPlayer;
    
      for (aPlayer = aGame->players;
           aPlayer;
           aPlayer = aPlayer->next) {
        group          *attackGroup;
    
        for (attackGroup = aPlayer->groups;
             attackGroup;
             attackGroup = attackGroup->next) {
          if (mustBomb(aPlayer, attackGroup)) {
            planet         *targetPlanet;
            bombing        *aBombing;
            player         *viewingPlayer;
    
            targetPlanet = attackGroup->location;
            aBombing = allocStruct(bombing);
    
            setName(aBombing, targetPlanet->name);
            /* This should be a function */
            aBombing->where = targetPlanet;
            aBombing->owner = targetPlanet->owner;
            aBombing->pop = targetPlanet->pop;
            aBombing->ind = targetPlanet->ind;
            aBombing->producing = targetPlanet->producing;
            aBombing->producingshiptype = targetPlanet->producingshiptype;
            aBombing->cap = targetPlanet->cap;
            aBombing->mat = targetPlanet->mat;
            aBombing->col = targetPlanet->col;
            aBombing->viewers = NULL;
    
            for (viewingPlayer = aGame->players;
                 viewingPlayer;
                 viewingPlayer = viewingPlayer->next) {
              if (canseeplanet(viewingPlayer, targetPlanet)) {
                alliance       *a;
                a = allocStruct(alliance);
    
                a->who = viewingPlayer;
                addList(&aBombing->viewers, a);
              }
            }
    
            if (aGame->gameOptions & GAME_NONGBOMBING) {
              targetPlanet->owner = NULL;
            }
            else {
              targetPlanet->owner =
                  determineOwnership(aGame, targetPlanet, aPlayer);
            }
    
            plog(LPART, "Nation %s bombs planet %s\n",
                 aPlayer->name, targetPlanet->name);
    
            if (targetPlanet->owner) {
              plog(LPART, "Ownership goes to %s\n", targetPlanet->owner->name);
              aBombing->who = targetPlanet->owner;
            }
            else {
              plog(LPART, "Ownership goes to nobody, planet neutral\n");
              aBombing->who = aPlayer;
            }
            addList(&(aGame->bombings), aBombing);
    
            bombPlanet(aGame, targetPlanet);
    
          }
        }
      }
    }    

Phase/cktech

NAME
   cktech -- check tech levels of a group.
 FUNCION
   Clip all tech levels of a group to two decimal points.
   Set tech levels of zero components to zero.
NOTES
   This should be in util.c
SOURCE
    void
    cktech(group *g)
    {
      shiptype       *t;
    
      t = g->type;
      g->drive = ftrunc2(g->drive);
      g->weapons = ftrunc2(g->weapons);
      g->shields = ftrunc2(g->shields);
      g->cargo = ftrunc2(g->cargo);
      if (!t->drive)
        g->drive = 0;
      if (!t->attacks)
        g->weapons = 0;
      if (!t->shields)
        g->shields = 0;
      if (!t->cargo)
        g->cargo = 0;
    }    

Phase/convertcap

NAME
   convertcap -- convert capital into industry.
SYNOPSIS
   void convertcap(planet *p)
SOURCE
    void
    convertcap(planet *p)
    {
      double          indinc;
    
      indinc = p->pop - p->ind;
      if (indinc > p->cap)
        indinc = p->cap;
      p->cap -= indinc;
      p->ind += indinc;
    }    

Phase/determineOwnership

NAME
   determineOwnership -- determine ownership of planet after bombing.
FUNCTION
   Determines which nation should get a planet after it is bombed.

Phase/fleetphase

NAME
   fleetphase -- update fleet data
FUNCTION
   Remove fleets that have no groups left.  Recompute the speed of
   each fleet. The speed might have changed due to upgrades or loss
   of slow ships in battles.
SEE ALSO
   fleetSpeed()
SOURCE
    void
    fleetphase(game *aGame)
    {
      player         *P;
      fleetname      *fl, *fl2;
      group          *g;
    
      /* double          shipspeed; */
      int             hasships;
    
      pdebug(DFULL, "Fleet Phase\n");
    
      for (P = aGame->players; P; P = P->next) {
        for (fl = P->fleetnames; fl; fl = fl2) {
          fl2 = fl->next;
          hasships = FALSE;
          for (g = P->groups; g; g = g->next) {
            if (g->thefleet eq fl) {
              fl->fleetspeed = groupSpeed(g);       /* This can be * * removed 
                                                     * I * * * think! FS */
              hasships = TRUE;
              break;
            }
          }
          fl->fleetspeed = fleetSpeed(fl, P->groups);       /* CB-19980922  *  */
          pdebug(DFULL, "Fleet %s  speed %f\n", fl->name, fl->fleetspeed);
          if (!hasships) {
            pdebug(DFULL, "Removing Fleet %s\n", fl->name);
            remList(&P->fleetnames, fl);
          }
        }
      }
    }    

Phase/ftrunc2

NAME
   ftrunc2 -- clip a number to two decimal points. 
SYNOPSIS
   double ftrunc2(double x)
NOTES
   Should use lineBuffer.
SOURCE
    double
    ftrunc2(double x)
    {
      char            buf[32];
    
      sprintf(buf, "%0.2f", x);
      return atof(buf);
    }    

Phase/interceptphase

NAME
   interceptphase -- compute the destination of intercepting groups and
                     fleets.
SYNOPSIS
   void interceptphase(game *aGame)
FUNCTION
   Compute the destination of all groups and fleets that have been 
   given the intercept command.
NOTES
   This does not work perfectly, groups can end up unexpected locations.
SOURCE
    void
    interceptphase(game *aGame)
    {
      player         *curPlayer, *otherPlayer;
      double         *massPerPlanet;
      int             noPlanets;
    
      pdebug(DFULL, "Intercept Phase\n");
    
      noPlanets = numberOfElements(aGame->planets);
      massPerPlanet = (double *) alloc((noPlanets + 1) * sizeof(double));
    
      for (curPlayer = aGame->players;
           curPlayer;
           curPlayer = curPlayer->next) {
        group          *inGroup;
    
        for (inGroup = curPlayer->groups; inGroup; inGroup = inGroup->next) {
          if (inGroup->flags & GF_INTERCEPT) {
            double          maxDist, maxMass;
            planet         *inPlanet, *targetPlanet, *curPlanet;
            int             planetIndex;
    
            if (inGroup->thefleet)
              maxDist = 2 * inGroup->thefleet->fleetspeed;
            else
              maxDist = 2 * groupSpeed(inGroup);
    
            inPlanet = inGroup->where;
            if (inGroup->thefleet) {
              pdebug(DFULL, "Fleet %s Intercept on Planet %s max Dist %f\n",
                     inGroup->thefleet->name,
                     inPlanet->name,
                     maxDist);
            }
            else {
              pdebug(DFULL, "Group %d Intercept on Planet %s max Dist %f\n",
                     inGroup->number,
                     inPlanet->name,
                     maxDist);
            }
    /* 
     * Compute the total mass per destination planet, of all groups departing
     * from the planet the intercept command was issued on.  Destination
     * planet have to be with in two turn range. */
            memset(massPerPlanet, 0, (noPlanets + 1) * sizeof(double));
    
            for (otherPlayer = aGame->players;
                 otherPlayer;
                 otherPlayer = otherPlayer->next) {
              if (otherPlayer != curPlayer) {
                group          *aGroup;
    
                for (aGroup = otherPlayer->groups;
                     aGroup;
                     aGroup = aGroup->next) {
                  if ((aGroup->dist) &&
                      (aGroup->location eq inPlanet) &&
                      (dist(aGroup->where, inGroup->location) < maxDist)) {
                    massPerPlanet[ptonum(aGame->planets, aGroup->where)] +=
                        aGroup->ships * shipmass(aGroup);
                  }
                }
              }
            }
    /* 
     * Find the destination planet of the largest outgoing mass.  */
            targetPlanet = NULL;
            for (curPlanet = aGame->planets, planetIndex = 1, maxMass = 0;
                 curPlanet;
                 planetIndex++, curPlanet = curPlanet->next) {
              assert(planetIndex < (noPlanets + 1));
              if (massPerPlanet[planetIndex] > maxMass) {
                targetPlanet = curPlanet;
                maxMass = massPerPlanet[planetIndex];
              }
            }
    
            if (targetPlanet) {
              pdebug(DFULL, "Result: Planet %s (%f ly away).\n",
                     targetPlanet->name,
                     dist(inGroup->where, targetPlanet));
              inGroup->where = inGroup->from;
              send(inGroup, targetPlanet);
            }
            inGroup->flags &= ~GF_INTERCEPT;        /* Remove the * *
                                                     * intercept * * *  *  * * 
                                                     * flag. */
          }
        }
      }
      free(massPerPlanet);
    }    

Phase/joinphase

NAME
   joinphase -- join similar groups into a single group.
SYNOPSIS
   void joinphase(game *aGame)

Phase/kill

NAME
   kill --
NOTES
   Should be in battle.c I guess.

Phase/loadphase

NAME
   loadphase -- upload cargo from planet onto ships
FUNCTION
   Takes care of all cargo routes. 

Phase/movephase

NAME
   movephase -- ships move through hyperspace
FUNCTION
   Advance all ships (groups and fleets) through hyperspace. 
   The distance they travel depend on the drive, drive tech,
   and total mass of the ship (including cargo).
NOTES
   Should use groupSpeed() and fleetSpeed()
SEE ALSO
   shipmass() 

Phase/mustBomb

NAME
   mustBomb -- must a nation bomb a planet?
SYNOPSIS
   int mustBomb(player *P, group *g)
FUNCTION
   Determine of a nation is obliged to bomb a planet.
RESULT
   TRUE   -- yes the nation should bomb.
   FALSE  -- no the nation should not.
SOURCE
    int
    mustBomb(player *P, group *g)
    {
      int             must_bomb;
    
      must_bomb = g->location && g->location->owner && g->ships &&
          g->type->attacks && atwar(P, g->location->owner);
      return must_bomb;
    }    

Phase/nametocargotype

NAME
   nametocargotype --
SYNOPSIS
   int nametocargotype(char *s) 
NOTES
   Should be in Util

Phase/produceMatCap

NAME
   produceMatCap -- Produce CAP or MAT.
 NOTE
   The function to compute the CAP increase is a tricky one.
SOURCE
    void
    produceMatCap(planet *aPlanet, double industry)
    {
      double          materialDemand;
    
      switch (aPlanet->producing) {
      case PR_CAP:
        materialDemand = industry / INDPERCAP;      /* 1 unit of MAT per 1 CAP 
                                                     * 
                                                     * *  * *  */
        if (materialDemand > aPlanet->mat)
          materialDemand = aPlanet->mat;
        industry -= materialDemand * INDPERCAP;
        aPlanet->cap += materialDemand;
        aPlanet->mat -= materialDemand;
        aPlanet->cap += industry / (INDPERCAP + 1 / aPlanet->resources);
        break;
      case PR_MAT:
        aPlanet->mat += industry * aPlanet->resources;
        break;
      default:
        assert(0);
      }
      aPlanet->inprogress = 0.0;
    }    

Phase/producePopulation

NAME
   producePopulation -- growth of population and colonists.
FUNCTION
   Lets the population of a planet grow. Excess population
   (growth beyond the size of the planet) is turned into colonists
   by condensing a number of persons into one colonist.
SOURCE
    void
    producePopulation(planet *aPlanet)
    {
      double          popinc, poproom;
    
      if (aPlanet->owner) {
        popinc = aPlanet->pop * POPINC;
        poproom = aPlanet->size - aPlanet->pop;
        if (poproom > popinc)
          poproom = popinc;
        aPlanet->pop += poproom;
        aPlanet->col += (popinc - poproom) / POPPERCOL;
        convertcap(aPlanet);
      }
    }    

Phase/produceShip

NAME
   produceShip -- try to produce some ships.
FUNCTION
   Computes based on the amount of industry (points) how many ships
   can be build. If this is 1 or more the ships are produces and a
   new group with these ships is created. If it is less than 1 the
   production is delayed to the next turn.
 NOTE
   Because of MAT the expression to compute the number of ships 
   that can be produced is a tricky one.
SOURCE
    void
    produceShip(planet *aPlanet, double industry)
    {
      int             n, numberOfShips;
      shiptype       *typeProduced;
      double          typeMass, indForProduction, indForMaterials;
    
      typeProduced = aPlanet->producingshiptype;
      typeMass = typemass(typeProduced);
      typeMass = typeMass - 0.01; /* Fudge Factor, cause people
      keep on building those 99.01 ships and then complain they get not
      build */
                
      for (n = (int) (industry / (typeMass * INDPERSHIP)) + 1, numberOfShips = 0;
           n >= 0;
           n--) {
        indForProduction = n * typeMass * INDPERSHIP;
        indForMaterials = (n * typeMass - aPlanet->mat) / aPlanet->resources;
        if (indForMaterials < 0)
          indForMaterials = 0;
        if (indForProduction + indForMaterials <= industry) {
          numberOfShips = n;
          break;
        }
      }
    
      if (numberOfShips == 0) {
        /* Delay Construction to next turn */
        aPlanet->inprogress = industry;
      }
      else {
        group          *aGroup;
        player         *aPlayer;
    
        aPlayer = aPlanet->owner;
        indForProduction = numberOfShips * typeMass * INDPERSHIP;
        indForMaterials = (numberOfShips * typeMass - aPlanet->mat)
            / aPlanet->resources;
        if (indForMaterials < 0) {
          indForMaterials = 0;
          aPlanet->mat -= numberOfShips * typeMass;
        }
        else {
          aPlanet->mat = 0;
        }
        industry -= indForProduction + indForMaterials;
        aPlanet->inprogress = industry;
    /* This Should be a function */
        aGroup = allocStruct(group);
    
        aGroup->ships = numberOfShips;
        aGroup->type = typeProduced;
        aGroup->drive = aPlayer->drive;
        aGroup->weapons = aPlayer->weapons;
        aGroup->shields = aPlayer->shields;
        aGroup->cargo = aPlayer->cargo;
        cktech(aGroup);
        aGroup->load = 0;
        aGroup->loadtype = CG_EMPTY;
        aGroup->from = aGroup->where = aPlanet;
        aGroup->dist = 0;
        aGroup->thefleet = NULL;
        aGroup->defense = 0.0;
        aGroup->attack = 0.0;
        aGroup->flags = 0;
        aGroup->location = aPlanet;
        numberGroup(aPlayer, aGroup);
        addList(&aPlayer->groups, aGroup);
        aPlayer->massproduced += numberOfShips * typemass(typeProduced);
      }
    }    

Phase/produceTechnology

NAME
   produceTechnology -- produce different kind of technologies.
SOURCE
    void
    produceTechnology(planet *aPlanet, double industry)
    {
      player         *aPlayer;
    
      aPlayer = aPlanet->owner;
      switch (aPlanet->producing) {
      case PR_DRIVE:
        aPlayer->drive += industry / 5000.0;
        plog(LFULL, "Producing DRIVE %lf\n", industry / 5000.0);
        break;
      case PR_WEAPONS:
        aPlayer->weapons += industry / 5000.0;
        plog(LFULL, "Producing WEAPONS %lf\n", industry / 5000.0);
        break;
      case PR_SHIELDS:
        aPlayer->shields += industry / 5000.0;
        plog(LFULL, "Producing SHIELDS %lf\n", industry / 5000.0);
        break;
      case PR_CARGO:
        aPlayer->cargo += industry / 2500.0;
        plog(LFULL, "Producing CARGO %lf\n", industry / 2500.0);
        break;
      default:
        assert(0);
      }
      aPlanet->inprogress = 0.0;
    }    

Phase/producephase

NAME
   producephase -- planets produce their products.
FUNCTION
   Iterate over all planets and let each planet produce its thing.
   Also takes care of the population and colonist increase.
SOURCE
    void
    producephase(game *aGame)
    {
      planet         *aPlanet;
    
      pdebug(DFULL, "Produce Phase\n");
    
      for (aPlanet = aGame->planets;
           aPlanet;
           aPlanet = aPlanet->next) {
        if (aPlanet->owner) {
          double          industry;
    
          switch (aPlanet->producing) {
          case PR_SHIP:
            industry = aPlanet->ind * .75 + aPlanet->pop * .25 - aPlanet->spent +
                aPlanet->inprogress;
            aPlanet->spent = 0.0;
            produceShip(aPlanet, industry);
            break;
          case PR_MAT:
          case PR_CAP:
            industry = aPlanet->ind * .75 + aPlanet->pop * .25 - aPlanet->spent +
                aPlanet->inprogress;
            aPlanet->spent = 0.0;
            produceMatCap(aPlanet, industry);
            break;
          }
        }
      }
    
      for (aPlanet = aGame->planets;
           aPlanet;
           aPlanet = aPlanet->next) {
        if (aPlanet->owner) {
          double          industry;
    
          switch (aPlanet->producing) {
          case PR_DRIVE:
          case PR_WEAPONS:
          case PR_SHIELDS:
          case PR_CARGO:
            industry = aPlanet->ind * .75 + aPlanet->pop * .25 - aPlanet->spent +
                aPlanet->inprogress;
            aPlanet->spent = 0.0;
            produceTechnology(aPlanet, industry);
            break;
          }
          producePopulation(aPlanet);
        }
      }
    }    

Phase/sortphase

NAME
   sortphase -- renumber the groups
SYNOPSIS
   void sortphase(game *aGame)
FUNCTION
   Renumber the groups such that they are sorted according
   to planet. In particular they are number in the following
   order:
     (1) groups at planets owned by the nation,
     (2) groups at planets owned by other nations,
     (3) groups at all other planets, 
     (4) groups that are part of a fleet.
SOURCE
    void
    sortphase(game *aGame)
    {
      player         *P;
      group          *g;
      planet         *p;
      fleetname      *fl;
      int             n;
    
      pdebug(DFULL, "Sort Phase\n");
    
      for (P = aGame->players; P; P = P->next) {
        n = 1;
        if (P->flags & F_SORTGROUPS) {
          /* Groups at planets owned by the nation */
          for (p = aGame->planets; p; p = p->next) {
            if (p->owner == P) {
              for (g = P->groups; g; g = g->next) {
                if (g->location == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
              for (g = P->groups; g; g = g->next) {
                if (!g->location && g->where == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
            }
          }
          /* Groups at planets owned by other nations */
          for (p = aGame->planets; p; p = p->next) {
            if (p->owner && p->owner != P) {
              for (g = P->groups; g; g = g->next) {
                if (g->location == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
              for (g = P->groups; g; g = g->next) {
                if (!g->location && g->where == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
            }
          }
          /* Groups at all other planets */
          for (p = aGame->planets; p; p = p->next) {
            if (!p->owner) {
              for (g = P->groups; g; g = g->next) {
                if (g->location == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
              for (g = P->groups; g; g = g->next) {
                if (!g->location && g->where == p && !g->thefleet) {
                  g->number = n;
                  n++;
                }
              }
            }
          }
    
          /* Groups that are part of fleets */
          for (fl = P->fleetnames; fl; fl = fl->next) {
            for (g = P->groups; g; g = g->next) {
              if (g->thefleet eq fl) {
                g->number = n;
                n++;
              }
            }
          }
        }
      }
    }    

Phase/unloadcap

NAME
   unloadcap -- unload capital.
SYNOPSIS
   void unloadcap(planet *p, double x)
FUNCTION
   Unload capital unto a planet and if possible use it to
   increase the industry.
SOURCE
    void
    unloadcap(planet *p, double x)
    {
      p->cap += x;
      convertcap(p);
    }    

Phase/unloadcol

NAME
   unloadcol -- unload colonists.
FUNCTION
   Unload colonists unto a planet defrost them and turn
   them into population.
SOURCE
    void
    unloadcol(planet *p, double x, player *P)
    {
      double          y;
    
      x *= POPPERCOL;
      y = p->size - p->pop;
      if (y > x)
        y = x;
      p->pop += y;
      x -= y;
      p->col += x / POPPERCOL;
      if (!p->owner)
        p->owner = P;
      convertcap(p);
    }    

Phase/unloadgroup

NAME
   unloadgroup --
SYNOPSIS
   void unloadgroup(group *g, player *P, double amount)
FUNCTION
SOURCE
    void
    unloadgroup(group *g, player *P, double amount)
    {
      double          x;
      planet         *p;
    
      x = amount * g->ships;
      p = g->where;
      switch (g->loadtype) {
      case CG_CAP:
        unloadcap(p, x);
        break;
      case CG_MAT:
        p->mat += x;
        break;
      case CG_COL:
        unloadcol(p, x, P);
        break;
      }
      g->load -= amount;
      if (g->load < AMOUNTMIN) {
        g->loadtype = CG_EMPTY;
        g->load = 0.0;
      }
    }    

Phase/unloadphase

NAME
   unloadphase -- unload cargo unto planet
SOURCE
    void
    unloadphase(game *aGame)
    {
      planet         *p, *p2;
      player         *cur_player;
      group          *g;
      int             i;
    
      pdebug(DFULL, "Unload Phase\n");
    
    /* Auto Unload */
    
      for (p = aGame->planets; p; p = p->next) {
        for (cur_player = aGame->players;
             cur_player;
             cur_player = cur_player->next) {
          if (cur_player->flags & F_AUTOUNLOAD) {
            for (g = cur_player->groups; g; g = g->next) {
              if (g->where == p && g->dist == 0 && g->ships) {
                if ((p->owner && p->owner == cur_player) ||
                    !p->owner) {
                  unloadgroup(g, cur_player, g->load);
                }
              }
            }
          }
        }
      }
    
    /* Routes */
    
      for (p = aGame->planets; p; p = p->next) {
        if (p->owner) {
          for (i = 0; i != CG_EMPTY; i++) {
            p2 = p->routes[i];
            for (g = p->owner->groups; g; g = g->next) {
              if (g->where == p2 &&
                  g->dist == 0 &&
                  g->loadtype == i &&
                  g->ships) {
                unloadgroup(g, p->owner, g->load);
              }
            }
          }
        }
      }
    }