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

TABLE OF CONTENTS

  1. GalaxyNG/areValidOrders
  2. GalaxyNG/at_order
  3. GalaxyNG/checkOrders
  4. GalaxyNG/copyOrders
  5. GalaxyNG/doOrders
  6. GalaxyNG/eq_order
  7. GalaxyNG/generateErrorMessage
  8. GalaxyNG/getDestination
  9. GalaxyNG/getReturnAddress
  10. GalaxyNG/getTurnNumber
  11. GalaxyNG/l_order
  12. GalaxyNG/mistake
  13. GalaxyNG/phase1orders
  14. GalaxyNG/phase2orders
  15. GalaxyNG/preComputeGroupData
  16. GalaxyNG/removeDeadPlayer
  17. GalaxyNG/runTurn
  18. GalaxyNG/u_order
  19. GalaxyNG/v_order
  20. GalaxyNG/w_order

GalaxyNG/areValidOrders

NAME
   areValidOrders -- check if orders are valid and load game.
SYNOPSIS
   int areValidOrders(FILE *ordersFile, 
                      char **command, game **game, 
                      char **nationName, char **password)
FUNCTION
   Scans through a file with orders until a line that starts
   with "#" is found.  The the rest of the line is then
   used to determine the name of the game, the nation the orders
   are for, and the password for the nation.
   The given game is loaded.  It is checked that the given
   player exists in this game, and that the given password
   is equal to the stored password.
INPUTS
   ordersFile     - pointer to a opened file with orders.
   theTurnNumber  - turn number the orders are supposed to be for.
RESULT
   result      - return code:
      RES_NO_ORDERS - no line containing "#GALAXY" was found.
      RES_PASSWORD  - password was incorrect.
      RES_PLAYER    - no such player (Nation) exists.
      RES_NO_GAME   - no such game exists.
      RES_TURNRAN   - orders are for a turn that already ran.
      RES_OK        - everything was OK.
   aGame       - game Structure loaded from disk
   nationName  - name of the nation the orders are for.
   password    - given password of the nation.

   ordersFile  - points to the line after the #GALAXY line.
   
   If the result is RES_OK then the game and its configuration
   file are loaded from disk.
SEE ALSO
   CMD_report(), CMD_check(), CMD_relay()
SOURCE
    int
    areValidOrders(
                    FILE * ordersFile,
                    game **aGame,
                    char **nationName, char **password,
                    int theTurnNumber
    )
    {
      int             resNumber, foundOrders;
      char           *gameName, *isRead;
    
      gameName = NULL;
    
      foundOrders = FALSE;
      for (isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, ordersFile);
           isRead;
           isRead = fgets(lineBuffer, LINE_BUFFER_SIZE, ordersFile)) {
        if (noCaseStrncmp("#GALAXY", lineBuffer, 7) == 0) {
          foundOrders = TRUE;
          break;
        }
      }
    
      if (foundOrders) {
        getstr(lineBuffer);
        gameName = strdup(getstr(NULL));
        *nationName = strdup(getstr(NULL));
        *password = strdup(getstr(NULL));
        plog(LPART, "%s %s %s\n", gameName, *nationName, *password);
        if ((*aGame = loadgame(gameName, LG_CURRENT_TURN))) {
          player         *aPlayer;
    
          loadConfig(*aGame);
          aPlayer = findElement(player, (*aGame)->players, *nationName);
    
          if (aPlayer) {
            if (noCaseStrcmp(aPlayer->pswd, *password) eq 0) {
              if ((theTurnNumber >= (*aGame)->turn + 1) ||
                  (theTurnNumber eq LG_CURRENT_TURN)) {
                resNumber = RES_OK;
              }
              else {
                resNumber = RES_TURNRAN;
              }
            }
            else {
              resNumber = RES_PASSWORD;
            }
          }
          else {
            resNumber = RES_PLAYER;
          }
        }
        else {
          resNumber = RES_NO_GAME;
        }
      }
      else {
        resNumber = RES_NO_ORDERS;
      }
    
      if ((resNumber == RES_NO_GAME) || (resNumber == RES_NO_ORDERS)) {
        *aGame = allocStruct(game);
    
        setName(*aGame, "UnknownGame");
        loadConfig(*aGame);
        if (gameName)
          setName(*aGame, gameName);
      }
      return resNumber;
    }    

GalaxyNG/at_order

NAME
   at_order -- write message to a nation
SOURCE
    void
    at_order(game *aGame, player *P, strlist **s)
    {
      char           *ns;
      alliance       *a;
      alliance       *plist;
      player         *P2;
    
      pdebug(DFULL, "at_order\n");
      ns = getstr(0);               /* for whom is the message */
      if (ns[0]) {
        for (plist = NULL;
             ns[0];
             ns = getstr(0)) {
          if ((P2 = findElement(player, aGame->players, ns))) {
            a = allocStruct(alliance);
    
            a->who = P2;
            addList(&plist, a);
          }
          else
            mistake(P, *s, "Nation not recognized");
        }
        for (a = plist; a; a = a->next)
          addList(&a->who->messages, makestrlist("-message starts-"));
    
        for (*s = (*s)->next;
             (*s) && ((*s)->str[0] != '@');
             *s = (*s)->next) {
          for (a = plist; a; a = a->next)
            addList(&a->who->messages, makestrlist((*s)->str));
        }
        for (a = plist; a; a = a->next)
          addList(&a->who->messages, makestrlist("-message ends-"));
        freelist(plist);
      }
      else {                        /* Message is global */
        addList(&(aGame->messages), makestrlist("-message starts-"));
    
        for (*s = (*s)->next;
             (*s) && ((*s)->str[0] != '@');
             *s = (*s)->next) {
          addList(&(aGame->messages), makestrlist((*s)->str));
        }
        addList(&(aGame->messages), makestrlist("-message ends-"));
      }
    }    

GalaxyNG/checkOrders

NAME
   checkOrders --  check orders
SYNOPSIS
   int checkOrders(char *ordersFileName)
   resNumber = checkOrders(ordersFileName)
FUNCTION
   Checks a file with orders and prints a report with a forecast and 
   any errors found in the orders to stdout.
   It is checked that the orders contain a valid game name, nation
   name and password.
   A copy of the orders is stored in the directory orders/<gameName>. 

   If the orders start with #REPORT instead of #GALAXY a copy
   of the previous turn report is send to stdout.
INPUTS
   ordersFileName - name of the file with the orders.
RESULT
   resNumber -- return code:
      RES_NO_ORDERS - no line containing "#GALAXY" or #REPORT was found.
      RES_PASSWORD  - password was incorrect.
      RES_PLAYER    - no such player (Nation) exists.
      RES_NO_GAME   - no such game exists.
      RES_TURNRAN   - orders are for a turn that already ran.
      RES_OK        - everything was OK.
BUGS
   Does not handle machine reports or xml reports.
SEE ALSO
   areValidOrders(), copyOrders() 
SOURCE
    void
    checkOrders(game *aGame, char *nationName, FILE * forecast)
    {
      player         *aPlayer;
      struct fielddef fields;
    
      pdebug(DFULL, "check orders\n");
      aPlayer = findElement(player, aGame->players, nationName);
    
      fields.destination = forecast;
      tagVisiblePlanets(aGame->planets, aPlayer);
    
      checkIntegrity(aGame);
    
      doOrders(aGame, aPlayer, phase1orders, 1);
      doOrders(aGame, aPlayer, phase2orders, 2);
    
      (aGame->turn)++;
      joinphase(aGame);
      loadphase(aGame);
      fleetphase(aGame);
      checkIntegrity(aGame);
      interceptphase(aGame);
      movephase(aGame);
      joinphase(aGame);
      producephase(aGame);
      unloadphase(aGame);
      joinphase(aGame);
      fleetphase(aGame);
    
      preComputeGroupData(aGame);
      sortphase(aGame);
      checkIntegrity(aGame);
      nationStatus(aGame);
      reportGlobalMessages(aGame->messages, &fields);
      reportMessages(aPlayer, &fields);
      reportOrders(aPlayer, &fields);
      reportMistakes(aPlayer, &fields);
      yourStatusForecast(aGame->planets, aPlayer, &fields);
      if (aPlayer->flags & F_SHIPTYPEFORECAST) {
        reportYourShipTypes(aPlayer, &fields);
      }
      if (aPlayer->flags & F_PLANETFORECAST) {
        yourPlanetsForecast(aGame->planets, aPlayer, &fields);
        reportProdTable(aGame->planets, aPlayer, &fields);
      }
      if (aPlayer->flags & F_ROUTESFORECAST) {
        reportRoutes(aGame->planets, aPlayer, &fields);
      }
      if (aPlayer->flags & F_GROUPFORECAST) {
        reportYourGroups(aGame->planets, aPlayer, &fields);
        reportFleets(aPlayer, &fields);
      }
    }    

GalaxyNG/copyOrders

NAME
   copyOrders -- copy incomming orders to file.
SYNOPSIS
 void copyOrders(game *aGame, FILE *orders, char *nationName, 
                 char *password, int theTurnNumber)
FUNCTION
   Copy the orders to a file called 
     GAMEHOME/orders/<game name>/<nation name>.<turn number>
   If and #END line is missing one is generated.
INPUTS
   orderFile      - should point to the line after the #GALAXY line.
   aGame 
   nationName
   password
   theTurnNumber
SOURCE
    void
    copyOrders(
                game *aGame,
                FILE * orders,
                char *nationName, char *password,
                int theTurnNumber)
    {
      strlist        *s;
      char           *copyFileName;
      FILE           *copyFile;
      player         *aPlayer;
    
      aPlayer = findElement(player, aGame->players, nationName);
    
      aPlayer->orders = NULL;
      copyFileName = alloc(strlen(aGame->name) + strlen(aPlayer->name) +
                           strlen(galaxynghome) + strlen("/orders//") + 20);
    #ifdef WIN32
      sprintf(copyFileName, "%s\\orders\\%s\\%s.%d",
              galaxynghome, aGame->name, aPlayer->name,
              theTurnNumber);
    #else
      sprintf(copyFileName, "%s/orders/%s/%s.%d",
              galaxynghome, aGame->name, aPlayer->name,
              theTurnNumber);
    #endif
      copyFile = Fopen(copyFileName, "w");
      savefprintf(copyFile, "#GALAXY %s %s %s\n",
                  aGame->name, nationName, password);
      getLine(orders);
      for (; !feof(orders) && noCaseStrncmp("#END", lineBuffer, 4);) {
        char           *c;
    
        savefprintf(copyFile, "%s", lineBuffer);
        for (c = lineBuffer; *c; c++) {
          if (*c == '\n')
            *c = ' ';
        }
        s = makestrlist(lineBuffer);
        addList(&(aPlayer->orders), s);
        getLine(orders);
      }
      if (feof(orders))
        savefprintf(copyFile, "#END\n");
      else
        savefprintf(copyFile, "%s\n", lineBuffer);
    
      free(copyFileName);
    }    

GalaxyNG/doOrders

NAME
   doOrders -- carry out all orders.
SYNOPSIS
   void doOrders(game *aGame, player *aPlayer, 
                 orderinfo *orderInfo, int phase)
FUNCTION
   Carry out all orders for one player. 
SOURCE
    void
    doOrders(game *aGame, player *aPlayer, orderinfo *orderInfo, int phase)
    {
      strlist        *s;
      orderinfo      *op;
    
      pdebug(DFULL, "doOrders\n");
      pdebug(DFULL2, "  Phase %d Nation %s\n", phase, aPlayer->name);
      for (s = aPlayer->orders; s;) {
        char           *order;
    
        pdebug(DFULL2, "  Order %s\n", s->str);
        for (order = getstr(s->str);
             (s) && (phase eq 2) && (*order eq '@');
            ) {
          for (s = s->next; s; s = s->next) {
            order = getstr(s->str);
            if (*order eq '@')
              break;
          }
          if (s) {
            s = s->next;
            if (s)
              order = getstr(s->str);
          }
        }
    
        if (s) {
          order = getstr(s->str);
          for (op = orderInfo; op->name != 0; op++) {
            if (noCaseStrncmp(op->name, order, ORDER_SIZE) == 0) {
              (*(op->func)) (aGame, aPlayer, &s);
              break;
            }
          }
        }
        if (s)
          s = s->next;
      }
    }    

GalaxyNG/eq_order

NAME
   eq_order -- set real name
SOURCE
    void
    eq_order(game *aGame, player *P, strlist **s)
    {
      char           *ns;
    
      pdebug(DFULL, "eq_order\n");
      ns = getstr(0);
      if (!ns[0]) {
        mistake(P, *s, "No name provided.");
        return;
      }
      if (P->realName)
        free(P->realName);
      P->realName = strdup(ns);
    }    

GalaxyNG/generateErrorMessage

NAME
   generateErrorMessage -- create error message for faulty orders.
FUNCTION
   
INPUTS
    resNumber -- The kind of error.
    forecast  -- file to write the message to.
SOURCE
    void
    generateErrorMessage(int resNumber, game *aGame,
                         char *nationName, int theTurnNumber, FILE * forecast)
    {
      switch (resNumber) {
      case RES_NO_ORDERS:
        fprintf(
                 forecast,
                 "O wise leader your mail did not contain any orders.\n"
                 "Remember orders start with,\n"
                 " #GALAXY <Galaxy Name> <Nation Name> <Password>\n"
                 "and end with,\n #END\n");
        break;
      case RES_ERR_GALAXY:
        fprintf(
                 forecast,
          "O wise leader you must supply your nation name and galaxy name.\n"
                 "Remember orders start with,\n"
                 " #GALAXY <Galaxy Name> <Nation Name> <Password>\n"
                 "and end with,\n #END\n");
        break;
      case RES_NO_GAME:
        fprintf(
                 forecast,
                 "O wise leader there is no galaxy called %s.\n"
                 "This probably means that you mispelled the galaxy name "
                 "in your orders\n", aGame->name);
        break;
      case RES_PASSWORD:
        fprintf(
                 forecast,
                 "O wise leader the password you gave is incorrect.\n");
        break;
      case RES_PLAYER:
        fprintf(forecast,
                "O wise leader there is no nation called %s.\n"
                "This probably means that you mispelled your nation name.\n",
                nationName);
        break;
      case RES_TURNRAN:
        fprintf(
                 forecast,
                 "O wise leader you sent in orders for turn %d, that turn already ran.\n",
                 theTurnNumber);
        break;
      case RES_DESTINATION:
        fprintf(
                 forecast,
                 "O wise leader the recipient of the message you sent does not exist.\n");
        break;
      case RES_NODESTINATION:
        fprintf(
                 forecast,
        "O wise leader you failed to give a destination for your message.\n");
      }
      fprintf(
               forecast,
               "\nYour orders have been discarded!\n"
               "Please correct the mistake and retransmit your orders.\n");
    }    

GalaxyNG/getDestination

NAME
   getDestination -- get Destination for the message
FUNCTION
   Extract the destination of a relay message from a players
   email.
 NOTE
   The message should contain the line
      Subject:   relay <nation name>

GalaxyNG/getReturnAddress

NAME
   getReturnAddress
FUNCTION
   Extract the return address from a players email.

GalaxyNG/getTurnNumber

NAME
   getTurnNumber -- get the turn number
FUNCTION
   Scans an incomming email for the From: line.
   If it is found it looks for the word "order" or "report"
   It then looks if there is a number after this word.
   If there is this number is returned.
   If no From: line was found the program aborts.
RESULT
   >= 0             -- the turn number
   LG_CURRENT_TURN  -- no turn number was specified

GalaxyNG/l_order

NAME
   l_order -- load cargo onto a group of ships.
FUNCTION
SOURCE
    void
    l_order(game *aGame, player *P, strlist **s)
    {
      group          *g;
      group          *g2;
      double          x, amount;
      double          y;
      int             amountFlag;
      planet         *p;
      int             numberOfShips;
      int             typeOfCargo;
      char           *ns;
    
      amountFlag = FALSE;
    
      pdebug(DFULL, "l_order\n");
      g = findgroup(P, getstr(0));
      if (!g) {
        mistake(P, *s, "Group not recognized.");
        return;
      }
      p = g->where;
    
      typeOfCargo = nametocargotype(getstr(0));
      if (g->type->cargo == 0) {
        mistake(P, *s, "Group cannot carry cargo.");
        return;
      }
      if (g->dist) {
        mistake(P, *s, "Group is in hyperspace.");
        return;
      }
      if (cargospace(g) <= g->load) {
        /* '<=' is used cause we deal with doubles here */
        mistake(P, *s, "Group is fully loaded.");
        return;
      }
      if (typeOfCargo < 0 || typeOfCargo > 2) {
        mistake(P, *s, "Cargo type not recognized.");
        return;
      }
      if (g->load && g->loadtype != typeOfCargo) {
        mistake(P, *s, "Group is already carrying a different load.");
        return;
      }
      /* Determine the number of ships to load the cargo on */
    
      numberOfShips = g->ships;     /* Start-off with using all ships */
      ns = getstr(0);
      if ((ns[0] != '\0') &&
          (noCaseStrcmp("amount", ns) != 0) &&
          (isdigit(ns[0]))) {
        numberOfShips = atoi(ns);
        if (numberOfShips != 0) {
          if (numberOfShips > g->ships) {
            mistake(P, *s, "Not enough ships, all available used.");
            numberOfShips = g->ships;
          }
          if (numberOfShips <= 0) { /* KDW July 1999 */
            mistake(P, *s, "You must specify > 0 ships, all available used.");
            numberOfShips = g->ships;
          }
        }
        ns = getstr(0);
      }
      /* Determine the amount of cargo to be loaded per ship */
      if (ns[0] != '\0') {
        if (noCaseStrcmp("amount", ns) == 0) {
          ns = getstr(0);
          if (ns[0] != '\0') {
            amount = atof(ns);
            if (amount > (cargospace(g) - g->load)) {
              mistake(P, *s,
                   "Not enough cargo space available to carry this amount.");
              return;
            }
          }
          else {
            mistake(P, *s, "Keyword AMOUNT should be followed by a number.");
            return;
          }
        }
        else {
          mistake(P, *s, "Expected the keyword AMOUNT.");
          return;
        }
        amountFlag = TRUE;
      }
      else {
        amount = cargospace(g) - g->load;
      }
    
      if (amount < AMOUNTMIN) {
        mistake(P, *s,
                "You should load at least %f per ship,"
                " you are trying to loading %f.", AMOUNTMIN, amount);
        return;
      }
      /* Check if the planet has enough of the goods requested. */
    
      switch (typeOfCargo) {
      case CG_CAP:
        y = p->cap;
        break;
      case CG_MAT:
        y = p->mat;
        break;
      case CG_COL:
        y = p->col;
        break;
      }
    
      /* Total amount that has to be uploaded */
      x = amount * numberOfShips;
      if (y == 0.0) {
        mistake(P, *s,
                "No cargo of this type available on \"%s\".", p->name);
        return;
      }
      if (y / numberOfShips < AMOUNTMIN) {
        mistake(P, *s,
                "Not enough cargo available on \"%s\" to"
                " load at least %f per ship.", p->name, AMOUNTMIN);
        return;
      }
      if (y < x) {
        if (amountFlag) {
          mistake(P, *s,
                  "Not enough cargo available on \"%s\" to"
                  " load %.2f per ship,\nloading %.2f per ship.",
                  p->name, amount, y / numberOfShips);
        }
        amount = y / numberOfShips;
      }
      /* Everything is OK, break of a group, and load cargo */
    
      if (numberOfShips != g->ships) {
        g2 = allocStruct(group);
    
        *g2 = *g;
        numberGroup(P, g2);
        addList(&P->groups, g2);
        assert(numberOfShips < g->ships);
        g->ships -= numberOfShips;
        g2->ships = numberOfShips;
        g = g2;
      }
      switch (typeOfCargo) {
      case CG_CAP:
        if (y > x)
          y = x;
        g->load += y / g->ships;
        p->cap -= y;
        break;
      case CG_MAT:
        if (y > x)
          y = x;
        g->load += y / g->ships;
        p->mat -= y;
        break;
      case CG_COL:
        if (y > x)
          y = x;
        g->load += y / g->ships;
        p->col -= y;
        break;
      }
      g->loadtype = typeOfCargo;
    }    

GalaxyNG/mistake

NAME
   mistake -- generate an error message about an order.
FUNCTION
   Dynamically generate an error message and add it to
   the list of mistakes of a player.
SOURCE
    void
    mistake(player *P, strlist *s, char *format,...)
    {
      int             n;
      va_list         ap;
    
      va_start(ap, format);
      addList(&P->mistakes, makestrlist(s->str));
    #ifdef WIN32
      vsprintf(lineBuffer, format, ap);
    #else
      n = vsnprintf(lineBuffer, LINE_BUFFER_SIZE, format, ap);
      assert(n != -1);
    #endif
      addList(&P->mistakes, makestrlist(lineBuffer));
      va_end(ap);
    }    

GalaxyNG/phase1orders

NAME
   phase1orders -- map of all phase 1 orders.
FUNCTION
   A map that maps an order name to the corresponding function
   that executes the order.  
SOURCE
    orderinfo       phase1orders[] =
    {
      {"@", &at_order},
      {"=", &eq_order},             /* FS 1999/12 set real name */
      {"a", &a_order},
      {"b", &b_order},
      {"d", &d_order},
      {"e", &e_order},
      {"f", &f_order},
      {"h", &h_order},              /* CB-19980923, to recall (halt) a group */
      {"i", &i_order},
      {"j", &j_order},
      {"l", &l_order},
      {"m", &m_order},
      {"o", &o_order},
      {"p", &p_order},
      {"q", &q_order},
      {"r", &r_order},
      {"s", &s_order},
      {"u", &u_order},
      {"v", &v_order},
      {"w", &w_order},
      {"x", &x_order},
      {"y", &y_order},
      {"z", &z_order},
      {NULL, NULL}
    };    

GalaxyNG/phase2orders

NAME
   phase2orders -- map of all phase 2 orders.
FUNCTION
   A map that maps an order name to the corresponding function
   that executes the order.  
SOURCE
    orderinfo       phase2orders[] =
    {
      {"c", &c_order},
      {"g", &g_order},
      {"n", &n_order},
      {"t", &t_order},
      {NULL, NULL}
    };    

GalaxyNG/preComputeGroupData

NAME
   preComputeGroupData -- precompute some frequently used values.
FUNCTION
   This is a very nasty function that precomputes some properties of
   groups.  This speeds up turn processing but also creates some
   serious problems when the function is not called at the right
   time.  A very nice case of premature optimization.
SOURCE
    void
    preComputeGroupData(game *aGame)
    {
      player         *aPlayer;
      group          *aGroup;
    
      for (aPlayer = aGame->players;
           aPlayer;
           aPlayer = aPlayer->next) {
        for (aGroup = aPlayer->groups;
             aGroup;
             aGroup = aGroup->next) {
          aGroup->attack = groupAttack(aGroup);
          aGroup->defense = groupDefense(aGroup);
          aGroup->location = groupLocation(aGroup);
        }
      }
    }    

GalaxyNG/removeDeadPlayer

NAME
   removeDeadPlayer -- Removes idle players 
FUNCTION
   Check if a player last sent-in orders, and if this was too
   long ago the player is removed from the game. 
SOURCE
    void
    removeDeadPlayer(game *aGame)
    {
      player         *P;
      player         *P3;
      int             allowedOrderGap;
    
      pdebug(DFULL, "removeDeadPlayer\n");
      allowedOrderGap = (aGame->turn < ENDPHASE1TURN) ? ORDERGAP1 : ORDERGAP2;
      for (P = aGame->players; P; P = P3) {
        P3 = P->next;
        if (P->addr[0]) {
          int             idleTurns;
    
          idleTurns = (P->lastorders) ? aGame->turn - P->lastorders :
              allowedOrderGap + 1;
          plog(LFULL, "Player %s idle turns %d\n", P->name, idleTurns);
          if (idleTurns != 0) {
            if (idleTurns < allowedOrderGap) {
              sprintf(lineBuffer,
                      "\n\

GalaxyNG/runTurn

NAME
   runTurn -- run a turn.
SYNOPSIS
   int runTurn(game *, char *)
   result = runTurn(aGame, ordersFileName)
FUNCTION
   Move one turn forward in time. All orders sent in by the nations
   are executed and the different phases are executed.  
   Nations that did not sent in orders for a number of consecutive
   turns are removed from the game.
   Although we can assume all the orders are correct, since they
   have been processed by checkorders(), we stil do some sanity
   checks.
INPUTS
   aGame --
   ordersFileName -- name of the file that contains the orders
                     of _all_ the nations.
RESULT
   aGame->turn is increased by one.
   aGame       contains the new situation, including battles,
               bombings and messages.
   result 
     FALSE -- Error occured during turn processing
     TRUE  -- All OK
 NOTE
   The turn is not saved and no reports are generated, this is handled
   by seperate functions.  This function should be split in parts.
SOURCE
    int
    runTurn(game *aGame, char *ordersFileName)
    {
      player         *P;
      char           *oGameName;
      char           *nationName;
      char           *password;
      FILE           *ordersFile;
    
      plog(LPART, "Reading orders from file %s\n", ordersFileName);
    
      ordersFile = Fopen(ordersFileName, "r");
    
      getLine(ordersFile);
      for (; !feof(ordersFile);) {
        if (noCaseStrncmp("#GALAXY", lineBuffer, 7) == 0) {
          player         *aPlayer;
    
          getstr(lineBuffer);
          oGameName = strdup(getstr(NULL));
          nationName = strdup(getstr(NULL));
          password = strdup(getstr(NULL));
          if (noCaseStrcmp(oGameName, aGame->name) == 0) {
            aPlayer = findElement(player, aGame->players, nationName);
    
            if (aPlayer) {
              aPlayer->lastorders = aGame->turn + 1;
              if (noCaseStrcmp(aPlayer->pswd, password) == 0) {
                aPlayer->orders = NULL;
                getLine(ordersFile);
                for (; !feof(ordersFile) &&
                     noCaseStrncmp("#GALAXY", lineBuffer, 7) &&
                     noCaseStrncmp("#END", lineBuffer, 4);) {
                  strlist        *s;
                  char           *c;
    
                  for (c = lineBuffer; *c; c++)
                    if (*c == '\n')
                      *c = ' ';
                  s = makestrlist(lineBuffer);
                  addList(&(aPlayer->orders), s);
                  getLine(ordersFile);
                }
              }
              else {
                plog(LPART, "Password Incorrect.\n");
              }
            }
            else {
              plog(LPART, "Unrecognized player %s.\n", nationName);
            }
          }
          else {
            plog(LPART, "Orders are not for game %s.\n", aGame->name);
          }
          free(oGameName);
          free(nationName);
          free(password);
        }
        getLine(ordersFile);
      }
      fclose(ordersFile);
    
      (aGame->turn)++;
    
      if (!checkIntegrity(aGame))
        return FALSE;
    
      plog(LPART, "Orders read, processing...\n");
      plog(LFULL, "# Phase 1 Orders\n");
      for (P = aGame->players; P; P = P->next) {
        doOrders(aGame, P, phase1orders, 1);
      }
    
      if (!checkIntegrity(aGame))
        return FALSE;
    
      plog(LFULL, "# Phase 2 Orders\n");
      for (P = aGame->players; P; P = P->next) {
        doOrders(aGame, P, phase2orders, 2);
      }
    
      if (!checkIntegrity(aGame))
        return FALSE;
    
      plog(LFULL, "# joinphase I\n");
      joinphase(aGame);
      preComputeGroupData(aGame);
      plog(LFULL, "# fightphase I\n");
      fightphase(aGame, GF_INBATTLE1);
      plog(LFULL, "# bombphase I\n");
      bombphase(aGame);
      plog(LFULL, "# loadphase\n");
      loadphase(aGame);
      plog(LFULL, "# fleetphase I \n");
      fleetphase(aGame);
      if (!checkIntegrity(aGame))
        return FALSE;
      plog(LFULL, "# interceptphase\n");
      interceptphase(aGame);
      plog(LFULL, "# movephase\n");
      movephase(aGame);
      plog(LFULL, "# joinphase II\n");
      joinphase(aGame);
      preComputeGroupData(aGame);
      plog(LFULL, "# fightphase II\n");
      fightphase(aGame, GF_INBATTLE2);
      plog(LFULL, "# bombphase II\n");
      bombphase(aGame);
      plog(LFULL, "# producephase\n");
      producephase(aGame);
      plog(LFULL, "# unloadphase\n");
      unloadphase(aGame);
      plog(LFULL, "# joinphase III\n");
      joinphase(aGame);
      plog(LFULL, "# fleetphase II\n");
      fleetphase(aGame);
      if (!checkIntegrity(aGame))
        return FALSE;
      preComputeGroupData(aGame);
      sortphase(aGame);
    
      if (!(aGame->gameOptions & GAME_NODROP))
        removeDeadPlayer(aGame);
      nationStatus(aGame);
    
      return TRUE;
    }    

GalaxyNG/u_order

NAME
   u_order -- unload cargo
SOURCE
    void
    u_order(game *aGame, player *P, strlist **s)
    {
      group          *g;
      group          *g2;
      int             numberOfShips;
      double          amount;
      char           *ns;
    
      pdebug(DFULL, "u_order\n");
    
      g = findgroup(P, getstr(0));
      if (!g) {
        mistake(P, *s, "Group not recognized.");
        return;
      }
      if (g->loadtype == CG_EMPTY) {
        mistake(P, *s, "No cargo on board.");
        return;
      }
      if (g->dist) {
        mistake(P, *s, "Group is in hyperspace.");
        return;
      }
    /* Determine how many ships are unloaded */
      numberOfShips = g->ships;     /* Start-of with all ships */
      ns = getstr(0);
      if ((ns[0] != '\0') &&
          (noCaseStrcmp("amount", ns) != 0) &&
          (isdigit(ns[0]))) {
        numberOfShips = atoi(ns);
        if (numberOfShips != 0) {
          if (numberOfShips > g->ships) {
            mistake(P, *s, "Not enough ships, all available used.");
            numberOfShips = g->ships;
          }
          if (numberOfShips <= 0) { /* KDW July 1999 */
            mistake(P, *s, "You must specify > 0 ships, all available used.");
            numberOfShips = g->ships;
          }
        }
        ns = getstr(0);
      }
    /* Determine the amount of cargo to be unloaded per ship */
      if (ns[0] != '\0') {
        if (noCaseStrcmp("amount", ns) == 0) {
          ns = getstr(0);
          if (ns[0] != '\0') {
            amount = atof(ns);
            if (amount > g->load) {
              amount = g->load;
              mistake(P, *s,
                   "Group does not carry that much cargo, using amount=%.2f",
                      amount);
            }
            if (amount < AMOUNTMIN) {
              mistake(P, *s,
                      "Unload atleast %.2f per ship.", AMOUNTMIN);
              return;
            }
          }
          else {
            mistake(P, *s, "Keyword AMOUNT should be followed by a number.");
            return;
          }
        }
        else {
          mistake(P, *s, "Expected the keyword AMOUNT.");
          return;
        }
      }
      else {
        amount = g->load;
      }
    
      if (numberOfShips != g->ships) {
        g2 = allocStruct(group);
    
        *g2 = *g;
        numberGroup(P, g2);
        addList(&P->groups, g2);
        assert(numberOfShips < g->ships);
        g->ships -= numberOfShips;
        g2->ships = numberOfShips;
        g = g2;
      }
      unloadgroup(g, P, amount);
    }    

GalaxyNG/v_order

NAME
   v_order -- claim a planet.
SOURCE
    void
    v_order(game *aGame, player *P, strlist **s)
    {
      planet         *p;
      planet_claim   *pclaim;
    
      pdebug(DFULL, "v_order\n");
    
      p = findPlanet(aGame, getstr(0));
      if (!p) {
        mistake(P, *s, "Planet not recognized.");
      }
      else {
        plog(LFULL, "Nation %s claims planet %s\n", P->name, p->name);
        pclaim = allocStruct(planet_claim);
    
        pclaim->planet_claimed = p;
        addList(&(P->claimed_planets), pclaim);
      }
    }    

GalaxyNG/w_order

NAME
   w_order -- declare war on another nation.
SOURCE
    void
    w_order(game *aGame, player *P, strlist **s)
    {
      player         *P2;
      alliance       *a;
    
      pdebug(DFULL, "w_order\n");
    
      P2 = findElement(player, aGame->players, getstr(0));
    
      if (!P2) {
        mistake(P, *s, "Nation not recognized.");
        return;
      }
      for (a = P->allies; a; a = a->next) {
        if (a->who == P2) {
          remList(&P->allies, a);
          return;
        }
      }
    }