Generated from /home/galaxyng/NG/Source/create.c with ROBODoc v4.0.18 on Mon Jan 05 22:26:09 2004

TABLE OF CONTENTS


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

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;
      int             team = 0;
    
      srand((int) time(NULL));
      aGameSpec = allocStruct(gamespecification);
    
      setName(aGameSpec, "TestGame");
      aGameSpec->gameOptions.gameOptions = 0;
      aGameSpec->galaxySize = 200;
      aGameSpec->numberOfHomePlanets = 2;
      aGameSpec->numberOfEmptyPlanets = 6;
      aGameSpec->numberOfStuffPlanets = 5;
      aGameSpec->minDist = 25.0;
      aGameSpec->radiusEmptyPlanets = 30.0;
      aGameSpec->radiusSecondaryPlanets = 3.0;
      aGameSpec->players = NULL;
      aGameSpec->numberOfPlayers = 0;
      aGameSpec->coreSizes = malloc(2 * sizeof(double));
      aGameSpec->teamGame = FALSE;
      aGameSpec->coreSizes[0] = 1000.0;
      aGameSpec->coreSizes[1] = 400.0;
      aGameSpec->gameOptions.initial_drive = 1.0;
      aGameSpec->gameOptions.initial_weapons = 1.0;
      aGameSpec->gameOptions.initial_shields = 1.0;
      aGameSpec->gameOptions.initial_cargo = 1.0;
    
      for (isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, specfile);
           isRead; isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, specfile)) {
    
        key = getstr(lineBuffer);
        printf("Game options => %ld ; key : %s\n",
               aGameSpec->gameOptions.gameOptions, key);
    
        if (key[0] != '\0') {
          if (noCaseStrcmp("player", key) == 0) {
            newplayer      *aNewPlayer;
            char            nationName[20];
    
            aNewPlayer = allocStruct(newplayer);
    
            aNewPlayer->addr = strdup(getstr(0));
            aNewPlayer->team = team;
            (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("rows", key) == 0) {
            value = getstr(0);
            aGameSpec->numberOfRows = atoi(value);
          }
          else if (noCaseStrcmp("columns", key) == 0) {
            value = getstr(0);
            aGameSpec->numberOfColumns = atoi(value);
          }
          else if (noCaseStrcmp("team", key) == 0) {
            value = getstr(0);
            team = atoi(value);
          }
          else if (noCaseStrcmp("empty_radius", key) == 0) {
            value = getstr(0);
            aGameSpec->radiusEmptyPlanets = atof(value);
          }
          else if (noCaseStrcmp("secondary_radius", key) == 0) {
            value = getstr(0);
            aGameSpec->radiusSecondaryPlanets = 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("teamgame", key) == 0) {
            aGameSpec->teamGame = TRUE;
          }
          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 if (noCaseStrcmp("initialtechlevels", key) == 0) {   /* CB-20010407 
                                                                     * ; no
                                                                     * verification 
                                                                     * at all */
            aGameSpec->gameOptions.initial_drive = atof(getstr(0)); /* seems
                                                                     * strtod
                                                                     * is not
                                                                     * portable 
                                                                     */
            aGameSpec->gameOptions.initial_weapons = atof(getstr(0));
            aGameSpec->gameOptions.initial_shields = atof(getstr(0));
            aGameSpec->gameOptions.initial_cargo = atof(getstr(0));
            if (aGameSpec->gameOptions.initial_drive < 1.0) {
              aGameSpec->gameOptions.initial_drive = 1.0;
            }
            if (aGameSpec->gameOptions.initial_weapons < 1.0) {
              aGameSpec->gameOptions.initial_weapons = 1.0;
            }
            if (aGameSpec->gameOptions.initial_shields < 1.0) {
              aGameSpec->gameOptions.initial_shields = 1.0;
            }
            if (aGameSpec->gameOptions.initial_cargo < 1.0) {
              aGameSpec->gameOptions.initial_cargo = 1.0;
            }
          }
          else if (noCaseStrcmp("fullbombing", key) == 0) {
            aGameSpec->gameOptions.gameOptions |= GAME_NONGBOMBING;
          }
          else if (noCaseStrcmp("keepproduction", key) == 0) {
            aGameSpec->gameOptions.gameOptions |= GAME_KEEPPRODUCTION;
          }
          else if (noCaseStrcmp("createcircle", key) == 0) {        /* Don't
                                                                     * know if 
                                                                     * still
                                                                     * used
                                                                     * ???? CB 
                                                                     * 20010425 */
            aGameSpec->gameOptions.gameOptions |= GAME_CREATECIRCLE;
          }
          else if (noCaseStrcmp("dontdropdead", key) == 0) {
            aGameSpec->gameOptions.gameOptions |= GAME_NODROP;
          }
          else if (noCaseStrcmp("savereportcopy", key) == 0) {
            aGameSpec->gameOptions.gameOptions |= GAME_SAVECOPY;
          }
          else if (noCaseStrcmp("sphericalgalaxy", key) == 0) {     /* CB-20010401 
                                                                     * ; see
                                                                     * galaxy.h 
                                                                     */
            /* printf ("*==> %ld\n", aGameSpec->gameOptions); */
            aGameSpec->gameOptions.gameOptions |= GAME_SPHERICALGALAXY;
            /* printf ("*==> %ld\n", aGameSpec->gameOptions); */
          }
          else {
            printf("Unknown key %s\n", key);
          }
        }
      }
      return aGameSpec;
    }
    

Create/printGameSpecs

NAME

   printGameSpecs -- print the game specs.

SYNOPSIS

   void printGameSpecs(gamespecification *aGameSpec)

SOURCE

    void
    printGameSpecs(gamespecification *aGameSpec)
    {
      newplayer      *curNewPlayer;
    
      /* aGameSpec->gameOptions = 0; CB-20010407 */
      printf("Galaxy:               %s\n", aGameSpec->name);
      if (aGameSpec->teamGame) {
        printf("TeamGame:                 Yes\n");
      }
      else {
        printf("TeamGame:                 No\n");
      }
      printf("Size:                     %.0f x %.0f\n",
             aGameSpec->galaxySize, aGameSpec->galaxySize);
    
      printf("Full bombing     :         %s\n",
             (aGameSpec->gameOptions.
              gameOptions & GAME_NONGBOMBING ? "ON" : "OFF"));
      printf("Keep production  :         %s\n",
             (aGameSpec->gameOptions.
              gameOptions & GAME_KEEPPRODUCTION ? "ON" : "OFF"));
      printf("Drop dead players:         %s\n",
             (aGameSpec->gameOptions.
              gameOptions & GAME_NODROP ? "ON" : "OFF"));
      printf("Save report copy :         %s\n",
             (aGameSpec->gameOptions.
              gameOptions & GAME_SAVECOPY ? "ON" : "OFF"));
      printf("Spherical Galaxy :         %s\n",
             (aGameSpec->gameOptions.
              gameOptions & GAME_SPHERICALGALAXY ? "ON" : "OFF"));
    
      printf("Initial tech levels:\n\
                * Drive:     %5.2f,\n\
                * Weapons:   %5.2f,\n\
                * Shields:   %5.2f,\n\
                * Cargo:     %5.2f.\n", aGameSpec->gameOptions.initial_drive, aGameSpec->gameOptions.initial_weapons, aGameSpec->gameOptions.initial_shields, aGameSpec->gameOptions.initial_cargo);
    
      printf("Nations:                  %d\n", aGameSpec->numberOfPlayers);
      printf("Home planets/nation:      %d\n", aGameSpec->numberOfHomePlanets);
      printf("Spacing nations:          %.1f\n", aGameSpec->minDist);
      printf("Secondary planet radius:  %.1f\n",
             aGameSpec->radiusSecondaryPlanets);
      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/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;
        int             created_ok;
    
        game           *aGame;
    
        srand((int) time(NULL));
        resetErnie(197162622 + (rand() & 0xFF));
        aGame = allocStruct(game);
    
        setName(aGame, aGameSpec->name);
        aGame->turn = 0;
        aGame->gameOptions.gameOptions = aGameSpec->gameOptions.gameOptions;
        aGame->gameOptions.initial_drive =
            aGameSpec->gameOptions.initial_drive;
        aGame->gameOptions.initial_weapons =
            aGameSpec->gameOptions.initial_weapons;
        aGame->gameOptions.initial_shields =
            aGameSpec->gameOptions.initial_shields;
        aGame->gameOptions.initial_cargo =
            aGameSpec->gameOptions.initial_cargo;
    
        /* Do not change this! planets can be looked up by number and this
         * function expects the first planet to have number 1 */
        planet_name = 1;
        if (aGameSpec->teamGame) {
          created_ok = createCheckeredLayout(aGameSpec, aGame, planet_name);
          if (created_ok)
            setTeamAllies(aGame->players);
        }
        else {
          created_ok = createStandardLayout(aGameSpec, aGame, planet_name);
        }
    
        if (created_ok) {
          Randomize_Planet_Numbers(aGame);
          preComputeGroupData(aGame);
          nationStatus(aGame);
          return aGame;
        }
        else {
          freegame(aGame);
          return NULL;
        }
      }
      else {
        return NULL;
      }
    }
    

Create/createCheckeredLayout


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)) {
    #if 0
        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;
    #endif
      }
      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);
        sprintf(lineBuffer, "%s/forecasts/%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(gamespecification *aGameSpec, game *aGame,
                 newplayer *aNewPlayer)
    {
      player         *aPlayer;
    
      aPlayer = allocStruct(player);
    
      setName(aPlayer, aNewPlayer->name);
      aPlayer->pswd = strdup(aNewPlayer->pswd);
      aPlayer->addr = strdup(aNewPlayer->addr);
      aPlayer->team = aNewPlayer->team;
      aPlayer->realName = strdup("none");
      aPlayer->pswdstate = 1;
      aPlayer->drive = aGameSpec->gameOptions.initial_drive;
      aPlayer->weapons = aGameSpec->gameOptions.initial_weapons;
      aPlayer->shields = aGameSpec->gameOptions.initial_shields;
      aPlayer->cargo = aGameSpec->gameOptions.initial_cargo;
      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_TXTREPORT ;
      /* F_MACHINEREPORT */
      return aPlayer;
    }
    

Create/printPlanetStats

NAME

   printPlanetStats

SOURCE

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

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;
    
      double          new_x, new_y;
      int             is_ok;
    
      for (cur_planet_nr = 0; cur_planet_nr < stuff_planets; cur_planet_nr++) {
    
        unode = (struct uniq_avl *) malloc(sizeof(struct uniq_avl));
    
        for (is_ok = FALSE; !is_ok;) {
          is_ok = TRUE;
          new_x = round2(frand(aGame->galaxysize));
          new_y = round2(frand(aGame->galaxysize));
          if (new_x < 0 || new_x >= aGame->galaxysize) {
            is_ok = FALSE;
            continue;
          }
          if (new_y < 0 || new_y >= aGame->galaxysize) {
            is_ok = FALSE;
            continue;
          }
          sprintf(unode->key, "%08d%08d", (int) (new_x * 100),
                  (int) (new_y * 100));
          if (avl_search(&unique, (avl *) unode, avliter) == 0) {
            avl_insert(&unique, (avl *) unode);
          }
          else {
            printf("x, y: %.2f,%.2f  ;; key: %s\n", new_x, new_y, unode->key);
            is_ok = FALSE;
            continue;
          }
        }
    
        p = addplanet(aGame);
        (*planet_name)++;
        p->x = new_x;
        p->y = new_y;
        p->size = 2.0 + frand(170.0);
        p->resources = round2(pow(2.0, frand2()));
        p->producing = PR_CAP;
      }
    }
    

Create/Add_Circle_Stuff_Planets

NAME

   Add_Circle_Stuff_Planets --

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/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.
 RESULTS
   A core plane is added to the game's planet list.  planet_name is
   modified, will have the name (number) of this planet.
   NULL if something went wrong.

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_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 max_radius.

SOURCE

    void
    Add_Extra_Home_Planets(game *aGame,
                           double x, double y,
                           double size,
                           double max_radius,
                           int *planet_name, player *aPlayer)
    {
      planet         *p;
    
      double          radius, angle;
      double          new_x, new_y;
      int             is_ok;
    
      unode = (struct uniq_avl *) malloc(sizeof(struct uniq_avl));
    
      for (is_ok = FALSE; !is_ok;) {
        is_ok = TRUE;
        radius = 1.0 + frand(max_radius - 1.0);
        angle = frand(360.0) * (2 * 3.141592654 / 360.0);
        new_x = round2(x + sin(angle) * radius);
        new_y = round2(y + cos(angle) * radius);
        if (new_x < 0 || new_x >= aGame->galaxysize) {
          is_ok = FALSE;
          continue;
        }
        if (new_y < 0 || new_y >= aGame->galaxysize) {
          is_ok = FALSE;
          continue;
        }
        sprintf(unode->key, "%08d%08d", (int) (new_x * 100),
                (int) (new_y * 100));
        if (avl_search(&unique, (avl *) unode, avliter) == 0) {
          avl_insert(&unique, (avl *) unode);
        }
        else {
          printf("x, y: %.2f,%.2f  ;; key: %s\n", new_x, new_y, unode->key);
          is_ok = FALSE;
          continue;
        }
      }
      p = addplanet(aGame);
      (*planet_name)++;
      p->x = round2(new_x);
      p->y = round2(new_y);
      p->owner = aPlayer;
      p->size = size;
      p->producing = PR_DRIVE;
      p->resources = 10;
      p->pop = size;
      p->ind = size;
      printPlanetStats(p);
    }
    

Create/Add_Extra_Circle_Stuff_Planets

NAME

   Add_Extra_Circle_Stuff_Planets

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 = 5000.0;
      p->producing = PR_DRIVE;
      p->resources = round2(pow(2.0, frand2()));
    }
    

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_total_size = 0.0, cur_planet_nr = 0; cur_planet_nr < nplanets; cur_planet_nr++) {
        planet_sizes[cur_planet_nr] = frand(MAXPOP - 80) + 80.0;
        cur_total_size += planet_sizes[cur_planet_nr];
      }
    
      /* Adjust the Planet sizes in order to make sure that each players get
       * about the same total amount */
    
      for (;
           (cur_total_size < nplanets * low_range) ||
           (cur_total_size > nplanets * up_range);) {
        int             pl_sel;
        float           adj_factor;
    
        adj_factor = 7.5 + frand(5);
        pl_sel = frand3(nplanets);
        if (cur_total_size > nplanets * up_range) {
          (planet_sizes[pl_sel]) -= adj_factor;
          cur_total_size -= adj_factor;
        }
        else {
          (planet_sizes[pl_sel]) += adj_factor;
          cur_total_size += adj_factor;
        }
    
        if (planet_sizes[pl_sel] < 20.0) {
          planet_sizes[pl_sel] += adj_factor;
          cur_total_size += adj_factor;
        }
    
        if (planet_sizes[pl_sel] > 980.0) {
          planet_sizes[pl_sel] -= adj_factor;
          cur_total_size -= adj_factor;
        }
    
      }
    
      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;
    
        unode = (struct uniq_avl *) malloc(sizeof(struct uniq_avl));
    
        for (is_ok = FALSE; !is_ok;) {
          is_ok = TRUE;
          radius = 0.2 + frand(empty_dist - 0.2);
          angle = frand(360.0) * (2 * 3.141592654 / 360.0);
          new_x = round2(x + sin(angle) * radius);
          new_y = round2(y + cos(angle) * radius);
          if (new_x < 0 || new_x >= aGame->galaxysize) {
            is_ok = FALSE;
            continue;
          }
          if (new_y < 0 || new_y >= aGame->galaxysize) {
            is_ok = FALSE;
            continue;
          }
          sprintf(unode->key, "%08d%08d", (int) (new_x * 100),
                  (int) (new_y * 100));
          if (avl_search(&unique, (avl *) unode, avliter) == 0) {
            avl_insert(&unique, (avl *) unode);
          }
          else {
            printf("x, y: %.2f,%.2f  ;; key: %s\n", new_x, new_y, unode->key);
            is_ok = FALSE;
            continue;
          }
    
        }
        p = addplanet(aGame);
        (*planet_name)++;
        p->x = new_x;
        p->y = 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/swap_data

NAME

   swap_data -- swap two doubles

SYNOPSIS

   void swap_data(double *v1, double *v2)

Create/CalcCirclegalaxysize

NAME

   CalcCirclegalaxysize