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

TABLE OF CONTENTS

  1. Create/Add_Center_Planet
  2. Create/Add_Circle_Home_Planet
  3. Create/Add_Circle_Stuff_Planets
  4. Create/Add_Core_Home_Planet
  5. Create/Add_Empty_Planets
  6. Create/Add_Extra_Circle_Stuff_Planets
  7. Create/Add_Extra_Home_Planets
  8. Create/Add_Stuff_Planets
  9. Create/CalcCirclegalaxysize
  10. Create/Randomize_Planet_Numbers
  11. Create/createGameDirectories
  12. Create/createPlayer
  13. Create/creategame
  14. Create/printGameSpecs
  15. Create/printPlanetStats
  16. Create/readGameSpec
  17. Create/swap_data
  18. GalaxyNG/Create

Create/Add_Center_Planet

NAME
   Add_Center_Planet -- add a planet in the exact centre of the galaxy.
SOURCE
    void
    Add_Center_Planet(game *aGame, int *planet_name)
    {
      planet         *p;
    
      p = addplanet(aGame);
      (*planet_name)++;
      p->x = round2(aGame->galaxysize / 2.0);
      p->y = round2(aGame->galaxysize / 2.0);
      p->size = 100.0;
      p->producing = PR_DRIVE;
      p->resources = round2(pow(2.0, frand2()));
    }    

Create/Add_Circle_Home_Planet

NAME
   Add_Circle_Home_Planet
NOTES
   Currently not used since the code to create a circle game
   has not yet been added to creategame().

Create/Add_Circle_Stuff_Planets

NAME
   Add_Circle_Stuff_Planets --

Create/Add_Core_Home_Planet

NAME
   Add_Core_Home_Planet -- add a core home planet for a nation.
FUNCTION
   Each nation has atleast one home planet. This is it's core home
   planet. The other home planets are located around it.  This
   function allocates a core home planet. It makes sure that there
   is a minimum distance between all core home planets.  The core
   home planets are all located on a big disc that fits inside the
   square galaxy.  The disc is used to prevent nations ending up in
   one of the corners.
INPUTS
   aGame        -- game to add the planet to.
   min_dist     -- minimum distance between the core planets.
   planet_name  -- name of the previously added planet.
   aPlayer      -- nation the core planet will belong to.
RESULT
   A core plane is added to the game's planet list.  planet_name is
   modified, will have the name (number) of this planet.

Create/Add_Empty_Planets

NAME
   Add_Empty_Planets -- add some good size empty planets.
FUNCTION
   This adds a number of good (relatively big sized) planets
   around the core home planet of a nation.
   The sum of the sizes of all these planets is about the
   same for each nation.
SOURCE
    void
    Add_Empty_Planets(
                       game *aGame,
                       int nplanets, double empty_dist,
                       double x, double y,
                       int *planet_name,
                       double low_range, double up_range)
    {
      double          tot_mass;
      double         *planet_sizes;
      int             cur_planet_nr;
      double          cur_total_size;
      planet         *p;
    
      printf("o Adding empty planets.\n");
      planet_sizes = alloc(nplanets * sizeof(double));
    
      for (cur_planet_nr = 0;
           cur_planet_nr < nplanets;
           cur_planet_nr++)
        planet_sizes[cur_planet_nr] = frand(MAXPOP - 80) + 80.0;
    
    /* Adjust the Planet sizes in order to make sure that each players get * * 
     * 
     * *  * *  * * about the same total amount */
    
      for (cur_total_size = 0.0, cur_planet_nr = 0;
           cur_planet_nr < nplanets;
           cur_planet_nr++)
        cur_total_size += planet_sizes[cur_planet_nr];
    
      for (;
           (cur_total_size < nplanets * low_range) ||
           (cur_total_size > nplanets * up_range);
          ) {
        int             pl_sel;
    
        pl_sel = frand3(nplanets);
        if (planet_sizes[pl_sel] > 100.0 && planet_sizes[pl_sel] < 980.0) {
          if (cur_total_size > nplanets * up_range) {
            (planet_sizes[pl_sel]) -= 10.0;
            cur_total_size -= 10.0;
          }
          else {
            (planet_sizes[pl_sel]) += 10.0;
            cur_total_size += 10.0;
          }
        }
      }
    
      for (cur_planet_nr = 0, tot_mass = 0.0;
           cur_planet_nr < nplanets;
           cur_planet_nr++) {
        double          radius, angle;
        double          new_x, new_y;
        int             is_ok;
    
        for (is_ok = FALSE; !is_ok;) {
          is_ok = TRUE;
          radius = 2.0 + frand(empty_dist - 2.0);
          angle = frand(360.0) * (2 * 3.141592654 / 360.0);
          new_x = x + sin(angle) * radius;
          new_y = y + cos(angle) * radius;
          if (new_x < 0 || new_x >= aGame->galaxysize)
            is_ok = FALSE;
          if (new_y < 0 || new_y >= aGame->galaxysize)
            is_ok = FALSE;
        }
        p = addplanet(aGame);
        (*planet_name)++;
        p->x = round2(new_x);
        p->y = round2(new_y);
        p->size = planet_sizes[cur_planet_nr];
        p->resources = round2(0.3 + pow(8.0, frand2()));
        p->producing = PR_CAP;
        tot_mass += (p->size) / (10.0 + 1.0 / p->resources);
        printPlanetStats(p);
      }
      printf("  Total production mass: %.2f\n", tot_mass);
      free(planet_sizes);
    }    

Create/Add_Extra_Circle_Stuff_Planets

NAME
   Add_Extra_Circle_Stuff_Planets

Create/Add_Extra_Home_Planets

NAME
   Add_Extra_Home_Planets
FUNCTION
   In addition to its core home planet a nation can have
   a number of additional home planets. This functions adds these.
   They are added randomly on a donut shape disk centered around
   the core home planet. The donut hole has a radius of 1, and the
   donut disk has a radius of 3.
NOTES
   The radius number 1 and 3 should be configurable.
SOURCE
    void
    Add_Extra_Home_Planets(
                            game *aGame,
                            newplayer *aNewPlayer,
                            double x, double y,
                            int *planet_name,
                            player *aPlayer)
    {
      int             cur_extra_home;
      planet         *p;
    
      printf("o Adding secondary home planets.\n");
      for (cur_extra_home = 1;
           cur_extra_home < aNewPlayer->numberOfHomePlanets;
           cur_extra_home++) {
        double          radius, angle;
        double          new_x, new_y;
        int             is_ok;
    
        for (is_ok = FALSE; !is_ok;) {
          is_ok = TRUE;
          radius = 1.0 + frand(2.0);
          angle = frand(360.0) * (2 * 3.141592654 / 360.0);
          new_x = x + sin(angle) * radius;
          new_y = y + cos(angle) * radius;
          if (new_x < 0 || new_x >= aGame->galaxysize)
            is_ok = FALSE;
          if (new_y < 0 || new_y >= aGame->galaxysize)
            is_ok = FALSE;
        }
        p = addplanet(aGame);
        (*planet_name)++;
        p->x = round2(new_x);
        p->y = round2(new_y);
        p->owner = aPlayer;
        p->size = aNewPlayer->coreSizes[cur_extra_home];
        p->producing = PR_DRIVE;
        p->resources = 10;
        p->pop = aNewPlayer->coreSizes[cur_extra_home];
        p->ind = aNewPlayer->coreSizes[cur_extra_home];
        printPlanetStats(p);
      }
    }    
    

Create/Add_Stuff_Planets

NAME
   Add_Stuff_Planets -- add a number of stuff planets.
SYNOPSIS
  void Add_Stuff_Planets(game *, int, int *)
       Add_Stuff_Planets(aGame, stuff_planets, planet_name)
FUNCTION
   Stuff planets are small useless planets that are randomly
   scattered accross the galaxy to fill up the empty space
   between the empires.
INPUTS
   aGame         -- game to add the planets to.
   stuff_planets -- the number of stuff planets to be added.
   planet_name   -- the name (number) of the previous planet.
RESULT
   A number of planet are added to the game's planet list.
   planet_name is modified, will have the name (number) of
   the last planet that was added. 
SOURCE
    void
    Add_Stuff_Planets(game *aGame, int stuff_planets, int *planet_name)
    {
      int             cur_planet_nr;
      planet         *p;
    
      for (cur_planet_nr = 0;
           cur_planet_nr < stuff_planets;
           cur_planet_nr++) {
        p = addplanet(aGame);
        (*planet_name)++;
        p->x = round2(frand(aGame->galaxysize));
        p->y = round2(frand(aGame->galaxysize));
        p->size = 2.0 + frand(170.0);
        p->resources = round2(pow(2.0, frand2()));
        p->producing = PR_CAP;
      }
    }    

Create/CalcCirclegalaxysize

NAME
   CalcCirclegalaxysize

Create/Randomize_Planet_Numbers

NAME
   Randomize_Planet_Numbers -- shuffle planet names.
FUNCTION
   Randomly shuffle the planet names.  The method used is randomly
   selecting two planets and swapping all their data. This process
   is repeated 2000 times.  The names are randomized to prevent
   players from guessing which planets are the good planets and bad
   planets around the nations core home planets.
NOTES
   This is not a particular good or speedy way of shuffling.  
   Someone suggested a much faster method, but that got misplaced.
SOURCE
    void
    Randomize_Planet_Numbers(game *aGame)
    {
      int             total_nr_of_planets;
      planet         *p;
      int             randomizor;
    
      for (p = aGame->planets, total_nr_of_planets = 0; p; p = p->next) {
        total_nr_of_planets++;
      }
    
      for (randomizor = 0; randomizor < 2000; randomizor++) {
        int             pln1, pln2, nm;
        planet         *p1, *p2;
    
        pln1 = rand() % total_nr_of_planets;
        pln2 = rand() % total_nr_of_planets;
        for (p1 = aGame->planets, nm = 0;
             nm < pln1;
             p1 = p1->next, nm++);
        for (p2 = aGame->planets, nm = 0;
             nm < pln2;
             p2 = p2->next, nm++);
    
        if (!p1->owner && !p2->owner) {
          player         *temp;
    
          temp = p2->owner;
          p2->owner = p1->owner;
          p1->owner = temp;
          swap_data(&p1->x, &p2->x);
          swap_data(&p1->y, &p2->y);
          swap_data(&p1->size, &p2->size);
          swap_data(&p1->pop, &p2->pop);
          swap_data(&p1->ind, &p2->ind);
          swap_data(&p1->resources, &p2->resources);
        }
      }
    }    

Create/createGameDirectories

NAME
   createGameDirectories --
FUNCTION
   Creates a number of sub directories that are used to store
   files of a game. Each subdirectory has the same name as
   the game. They are created in the directories:
      reports/
      orders/
      statistics/
INPUTS
    name -- name of the game
SOURCE
    int
    createGameDirectories(char *name)
    {
      sprintf(lineBuffer, "%s/data/%s", galaxynghome, name);
      if (GOS_mkdir(lineBuffer, 0700)) {
    // fprintf(stderr, "Warning a game under that name already exists\n");
        // fprintf(stderr, "Do you want to continue [y/n]?\n");
        // scanf("%s", lineBuffer);
        // if (*lineBuffer != 'y')
        // return FALSE;
      }
      else {
        sprintf(lineBuffer, "%s/reports/%s", galaxynghome, name);
        GOS_mkdir(lineBuffer, 0700);
        sprintf(lineBuffer, "%s/orders/%s", galaxynghome, name);
        GOS_mkdir(lineBuffer, 0700);
        sprintf(lineBuffer, "%s/statistics/%s", galaxynghome, name);
        GOS_mkdir(lineBuffer, 0700);
      }
      return TRUE;
    }    

Create/createPlayer

NAME
   createPlayer -- allocate and initialize a player structure.
SYNOPSIS
    player *createPlayer(game *aGame, newplayer *aNewPlayer)
FUNCTION
RESULT
   Pointer to an initialized player structure. 
SOURCE
    player         *
    createPlayer(game *aGame, newplayer *aNewPlayer)
    {
      player         *aPlayer;
    
      aPlayer = allocStruct(player);
    
      setName(aPlayer, aNewPlayer->name);
      aPlayer->pswd = strdup(aNewPlayer->pswd);
      aPlayer->addr = strdup(aNewPlayer->addr);
      aPlayer->realName = strdup("none");
      aPlayer->pswdstate = 1;
      aPlayer->drive = 1;
      aPlayer->weapons = 1;
      aPlayer->shields = 1;
      aPlayer->cargo = 1;
      aPlayer->msize = aGame->galaxysize;
      aPlayer->flags =
          F_ANONYMOUS | F_AUTOUNLOAD | F_PRODTABLE | F_SORTGROUPS |
          F_GROUPFORECAST | F_PLANETFORECAST | F_SHIPTYPEFORECAST |
          F_ROUTESFORECAST;
    /* | F_XMLREPORT ; */
    /* F_MACHINEREPORT */
      return aPlayer;
    }    

Create/creategame

NAME
   creategame -- create a game based on a gamespecification.
SYNOPSIS
   game     *creategame(gamespecification *)
   newGame = creategame(aGameSpec)
FUNCTION
   Creates all nations. For each nation a number 
   of planets are created and intialized. The number
   of nations and number of planets are defined in the 
   game specification.
RESULT
   Pointer to an initialized game structure.
SOURCE
    game           *
    creategame(gamespecification *aGameSpec)
    {
      if (createGameDirectories(aGameSpec->name)) {
        int             planet_name;
        newplayer      *aNewPlayer;
        game           *aGame;
    
        srand((int) time(NULL));
        resetErnie(197162622 + (rand() & 0xFF));
        aGame = allocStruct(game);
    
        setName(aGame, aGameSpec->name);
        aGame->turn = 0;
        aGame->galaxysize = aGameSpec->galaxySize;
        planet_name = 1;            /* Do not change this! planets can be * *
                                     * * looked up by number and this function 
                                     * *  *  * * expects the first planet to
                                     * have * number  *  * * 1 */
        for (aNewPlayer = aGameSpec->players;
             aNewPlayer;
             aNewPlayer = aNewPlayer->next) {
          planet         *core_planet;
          player         *aPlayer;
    
          aPlayer = createPlayer(aGame, aNewPlayer);
          printf("o Adding player %s\n", aPlayer->name);
          addList(&(aGame->players), aPlayer);
          if ((core_planet =
               Add_Core_Home_Planet(aGame, aGameSpec->minDist,
                                    &planet_name, aPlayer,
                                    aNewPlayer->coreSizes[0]))) {
            double          x, y;
    
            x = core_planet->x;
            y = core_planet->y;
            if (aNewPlayer->numberOfHomePlanets > 1) {
              Add_Extra_Home_Planets(aGame, aNewPlayer, x, y,
                                     &planet_name, aPlayer);
            }
            if (aGameSpec->numberOfEmptyPlanets) {
              Add_Empty_Planets(aGame, aGameSpec->numberOfEmptyPlanets,
                                aGameSpec->radiusEmptyPlanets, x, y,
                                &planet_name,
                                600.0, 700.0);
            }
            if (aGameSpec->numberOfStuffPlanets) {
              Add_Stuff_Planets(aGame,
                                aGameSpec->numberOfStuffPlanets,
                                &planet_name);
            }
          }
          else {
            printf("Can't space homeworlds at least %f light years apart.\n",
                   aGameSpec->minDist);
            printf("Please try again with a larger sized galaxy.\n");
            return NULL;
          }
        }
    /* Add_Center_Planet(aGame, &planet_name); */
        Randomize_Planet_Numbers(aGame);
        preComputeGroupData(aGame);
        nationStatus(aGame);
        return aGame;
      }
      else {
        return NULL;
      }
    }    

Create/printGameSpecs

NAME
   printGameSpecs -- print the game specs.
SYNOPSIS
   void printGameSpecs(gamespecification *aGameSpec)
SOURCE
    void
    printGameSpecs(gamespecification *aGameSpec)
    {
      newplayer      *curNewPlayer;
    
      aGameSpec->gameOptions = 0;
      printf("Galaxy:               %s\n", aGameSpec->name);
      printf("Size:                 %.0f x %.0f\n",
             aGameSpec->galaxySize, aGameSpec->galaxySize);
      printf("Nations:              %d\n", aGameSpec->numberOfPlayers);
      printf("Home planets/nation:  %d\n", aGameSpec->numberOfHomePlanets);
      printf("Spacing nations:      %.1f\n", aGameSpec->minDist);
      printf("Empty planets/nation: %d\n", aGameSpec->numberOfEmptyPlanets);
      printf("Located in within a:  %.1f radius\n", aGameSpec->radiusEmptyPlanets);
      printf("Stuff planets/nation: %d\n", aGameSpec->numberOfStuffPlanets);
    
      for (curNewPlayer = aGameSpec->players;
           curNewPlayer;
           curNewPlayer = curNewPlayer->next) {
        printf("%s played by %s with password %s\n",
               curNewPlayer->name, curNewPlayer->addr, curNewPlayer->pswd);
      }
    }    

Create/printPlanetStats

NAME
   printPlanetStats
SOURCE
    void
    printPlanetStats(planet *p)
    {
      printf("  Planet %s %.2f %.2f %.2f %.2f\n",
             p->name, p->size, p->pop,
             p->ind, p->resources);
    }    

Create/readGameSpec

SYNOPSIS
   gamespecification *readGameSpec(FILE *)
   spec    =          readGameSpec(specfile)
FUNCTION
   Reads and interprets a file that specifies the layout of the 
   galaxy, and information about the players.
   
RESULT
   Pointer to a gamespecification structure. Any parameters
   not defined in the specification file are given some
   "sensible" default.
SEE ALSO
   See Doc/example.glx for information on the layout of such a file. 
   CMD_template()
SOURCE
    gamespecification *
    readGameSpec(FILE * specfile)
    {
      gamespecification *aGameSpec;
      char           *isRead;
      char           *key;
      char           *value;
    
      srand((int) time(NULL));
      aGameSpec = allocStruct(gamespecification);
    
      setName(aGameSpec, "TestGame");
      aGameSpec->gameOptions = 0;
      aGameSpec->galaxySize = 200;
      aGameSpec->numberOfHomePlanets = 2;
      aGameSpec->numberOfEmptyPlanets = 6;
      aGameSpec->numberOfStuffPlanets = 5;
      aGameSpec->minDist = 25.0;
      aGameSpec->radiusEmptyPlanets = 30.0;
      aGameSpec->players = NULL;
      aGameSpec->numberOfPlayers = 0;
      aGameSpec->coreSizes = malloc(2 * sizeof(double));
    
      aGameSpec->coreSizes[0] = 1000.0;
      aGameSpec->coreSizes[1] = 400.0;
    
      for (isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, specfile);
           isRead;
           isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, specfile)) {
    
        key = getstr(lineBuffer);
    
        if (key[0] != '\0') {
          if (noCaseStrcmp("player", key) == 0) {
            newplayer      *aNewPlayer;
            char            nationName[20];
    
            aNewPlayer = allocStruct(newplayer);
    
            aNewPlayer->addr = strdup(getstr(0));
            (aGameSpec->numberOfPlayers)++;
            sprintf(nationName, "Nation_%d", aGameSpec->numberOfPlayers);
            setName(aNewPlayer, nationName);
            sprintf(nationName, "P%d", rand());
            aNewPlayer->pswd = strdup(nationName);
            addList(&(aGameSpec->players), aNewPlayer);
    
            for (value = getstr(0), aNewPlayer->numberOfHomePlanets = 0;
                 value[0] != '\0';
                 value = getstr(0), aNewPlayer->numberOfHomePlanets++);
            if (aNewPlayer->numberOfHomePlanets) {
              int             i;
    
              aNewPlayer->coreSizes =
                  malloc(aNewPlayer->numberOfHomePlanets * sizeof(double));
    
              getstr(lineBuffer);
              getstr(0);            /* skip address */
              for (value = getstr(0), i = 0;
                   value[0] != '\0';
                   value = getstr(0), i++) {
                aNewPlayer->coreSizes[i] = atof(value);
              }
            }
            else {
              int             i;
    
              aNewPlayer->coreSizes =
                  malloc(aGameSpec->numberOfHomePlanets * sizeof(double));
    
              for (i = 0;
                   i < aGameSpec->numberOfHomePlanets;
                   i++) {
                aNewPlayer->coreSizes[i] = aGameSpec->coreSizes[i];
              }
              aNewPlayer->numberOfHomePlanets = aGameSpec->numberOfHomePlanets;
            }
          }
          else if (noCaseStrcmp("size", key) == 0) {
            value = getstr(0);
            aGameSpec->galaxySize = atof(value);
          }
          else if (noCaseStrcmp("nation_spacing", key) == 0) {
            value = getstr(0);
            aGameSpec->minDist = atof(value);
          }
          else if (noCaseStrcmp("empty_planets", key) == 0) {
            value = getstr(0);
            aGameSpec->numberOfEmptyPlanets = atoi(value);
          }
          else if (noCaseStrcmp("stuff_planets", key) == 0) {
            value = getstr(0);
            aGameSpec->numberOfStuffPlanets = atoi(value);
          }
          else if (noCaseStrcmp("empty_radius", key) == 0) {
            value = getstr(0);
            aGameSpec->radiusEmptyPlanets = atof(value);
          }
          else if (noCaseStrcmp("nation_spacing", key) == 0) {
            value = getstr(0);
            aGameSpec->minDist = atof(value);
          }
          else if (noCaseStrcmp("name", key) == 0) {
            setName(aGameSpec, getstr(0));
          }
          else if (noCaseStrcmp("core_sizes", key) == 0) {
            int             number;
    
            for (value = getstr(0), aGameSpec->numberOfHomePlanets = 0;
                 value[0] != '\0';
                 value = getstr(0), aGameSpec->numberOfHomePlanets++);
            aGameSpec->coreSizes =
                malloc(aGameSpec->numberOfHomePlanets * sizeof(double));
    
            getstr(lineBuffer);
            for (value = getstr(0), number = 0;
                 value[0] != '\0';
                 value = getstr(0), number++) {
              aGameSpec->coreSizes[number] = atof(value);
            }
          }
          else {
            printf("Unknown key %s\n", key);
          }
        }
      }
      return aGameSpec;
    }    

Create/swap_data

NAME
   swap_data -- swap two doubles
SYNOPSIS
   void swap_data(double *v1, double *v2)

GalaxyNG/Create

NAME
    Create -- create a new galaxy
NOTES
    This code was developed since we found that the old code
    sometimes created galaxies that left some nations in rather
    unfair positions.  That is some nations would have their home
    planet located far away from other planets, while others nations
    home planets were located near a whole bunch of good planets.
    The code tries to provide all player with an equal chance on
    success, while still keeping the layout of the galaxy diverse
    and interesting.

    How is this accomplised:

    (1) Each nation will get the same number of planets within a
        circle of a given radius.   The size of these planets differ
        but the total sum of the sizes is the same for all nations.
        The resources of the planets are still chosen random.

    (2) The home world can be spaced widely from eachother, ensuring
        that a nation isn't kicked out in the first few turns.

    (3) To improve the tactical possibilities a number of `stuff
        planets' will be scattered across the galaxy.  These are
        small useless planets that provide players with different
        routes to attack their enemies.

    (4) In addition it is possible to let the nations start with
        more than one home planet, this will speed up the game.

    All these options can be controled with a set of variables
    that you will be asked to supply when you the galaxy
    program to create a new galaxy.  A large number of
    different galaxies is thus possible. Try to experiment a
    little before you settle on a galaxy you like.

    Notice that as opposed to the original code the names of
    the nations at turn zero will not be  Player_xx   but
    Nation_xx.

    Added the option to space out the empires along the edge of
    a large circle, in order to make certain that no one got
    a better placement geographically than any other player.
    No attempt was made to ensure any seeding of players. If
    you get stuck between Jacco and Frans, you are still toast. :)
    Tommy 980629
AUTHOR
    Frans, Rogerio Fung, Tommy
BUGS
    You found bugs?
    Catch them in a jar and send them to fslothouber@acm.org