Generated from process.c with ROBODoc v3.2.2 on Sun Aug 27 19:47:34 2000
TABLE OF CONTENTS
- GalaxyNG/areValidOrders
- GalaxyNG/at_order
- GalaxyNG/checkOrders
- GalaxyNG/copyOrders
- GalaxyNG/doOrders
- GalaxyNG/eq_order
- GalaxyNG/generateErrorMessage
- GalaxyNG/getDestination
- GalaxyNG/getReturnAddress
- GalaxyNG/getTurnNumber
- GalaxyNG/l_order
- GalaxyNG/mistake
- GalaxyNG/phase1orders
- GalaxyNG/phase2orders
- GalaxyNG/preComputeGroupData
- GalaxyNG/removeDeadPlayer
- GalaxyNG/runTurn
- GalaxyNG/u_order
- GalaxyNG/v_order
- GalaxyNG/w_order
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;
}
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-"));
}
}
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);
}
}
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);
}
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;
}
}
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);
}
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");
}
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>
NAME
getReturnAddress
FUNCTION
Extract the return address from a players email.
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
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;
}
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);
}
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}
};
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}
};
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);
}
}
}
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\
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;
}
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);
}
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);
}
}
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;
}
}
}