Generated from galaxyng.c with ROBODoc v3.2.2 on Sun Aug 27 19:47:33 2000
TABLE OF CONTENTS
- Galaxy/GalaxyNG
- GalaxyNG/CMD_check
- GalaxyNG/CMD_checkFile
- GalaxyNG/CMD_create
- GalaxyNG/CMD_dump
- GalaxyNG/CMD_graph
- GalaxyNG/CMD_mail0
- GalaxyNG/CMD_relay
- GalaxyNG/CMD_report
- GalaxyNG/CMD_run
- GalaxyNG/CMD_score
- GalaxyNG/CMD_selftest
- GalaxyNG/CMD_template
- GalaxyNG/CMD_test
- GalaxyNG/checkTime
- GalaxyNG/galaxynghome
- GalaxyNG/lineBuffer
- GalaxyNG/logFile
- GalaxyNG/logLevel
- GalaxyNG/main
- GalaxyNG/options
- GalaxyNG/productname
- GalaxyNG/relayMessage
- GalaxyNG/tempdir
- GalaxyNG/usage
NAME
galaxyng -- Server for the play-by-email game GalaxyNG
SYNOPSIS
galaxyng [command [options]]
FUNCTION
Checks incomming orders, runs the turn, and sends out the turn
reports.
The code is divided into a number of modules:
List -- (list.c list.h) functions for manipulating lists.
Util -- (util.c util.h) frequently used functions.
Phase -- (phase.c phase.h) code for the various phases in the game.
Process -- (process.c process.h ) code for order checking,
order processing, and running a turn.
Report -- (report.c report.h)
Code to generate the turn reports.
Battle -- (battle.c battle.h) code that performs the battles.
Loadgame -- saves a turn to disk
Savegame -- load a turn from disk
GalaxyNG -- glues it all together.
AUTHOR
Created by:
o Frans Slothouber (fslothouber@acm.org)
o Christophe Barbier
o Jacco van Weert
o Tommy Lindqvist
o Rogerio Fung
o Ken Weinert
This code contains parts of the the orginal Galaxy code which was
created by Russell Wallace (RWALLACE@vax1.tcd.ie), and updated by the
Galaxy PBeM Development Group which include
o Russell Wallace (RWALLACE@vax1.tcd.ie)
o Tim Myers (tmyers@unlinfo.unl.edu),
o Robert Stone (stone@athena.cs.uga.edu),
o Mayan Moudgill (moudgill@cs.cornell.edu),
o Graeme Griffiths (graeme@abekrd.co.uk),
o K Pankhurst (k.pankhurst@ic.ac.uk).
CREATION DATE
4-Jan-1997
COPYRIGHT
This program may be freely distributed, and used to run _free_
games over electronic media. It may not be sold or used
commercially without prior written permission from me Frans
Slothouber. fslothouber@acm.org. In no case may it be used to
run commercial games.
NOTES
This is not the most pretty code around. It is a product of many
years and many people. The code hosts a lot of global variables
and many not very descriptively named function. The code is
pretty stable however.
BUGS
NAME
CMD_check -- check in comming orders.
FUNCTION
Check incomming orders and create a forecast of the
situation at the next turn.
INPUTS
Orders come in via stdin. The forecast is mailed directy to the player.
Orders are assumed to have a proper mailheader, that is start with:
To: <player>@theaddress
Subject: orders [turn number]
This header can be produced with formail (see .procmailrc file).
RESULT
Orders are stored in
$GALAXYNGHOME/orders/<game name>/<nation name>.<turn number>
Forecast is mailed to the player.
A log is kept of all order processing in log/orders_processed.txt
SOURCE
int
CMD_check(int argc, char **argv, int kind)
{
int result;
char *logName;
logLevel = LBRIEF;
result = EXIT_FAILURE;
logName = createString("%s/log/orders_processed.txt", galaxynghome);
openLog(logName, "a");
free(logName);
plogtime(LBRIEF);
if (argc >= 2) {
char *forecastName, *returnAddress, *nationName, *password;
int resNumber, theTurnNumber;
game *aGame;
FILE *forecast;
forecastName = createString("%s/NGforecast", tempdir);
if ((forecast = GOS_fopen(forecastName, "w"))) {
envelope *anEnvelope;
anEnvelope = createEnvelope();
returnAddress = getReturnAddress(stdin);
theTurnNumber = getTurnNumber(stdin);
nationName = NULL;
password = NULL;
aGame = NULL;
resNumber = areValidOrders(stdin, &aGame, &nationName,
&password, theTurnNumber);
plog(LBRIEF, "game %s\n", aGame->name);
setHeader(anEnvelope, MAILHEADER_TO, "%s", returnAddress);
plog(LBRIEF, "Orders from %s\n", returnAddress);
if (resNumber eq RES_OK) {
if ((theTurnNumber eq LG_CURRENT_TURN) ||
(theTurnNumber eq(aGame->turn) + 1)) {
copyOrders(aGame, stdin, nationName, password, (aGame->turn) + 1);
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, %s turn %d forecast for %s",
aGame->name, (aGame->turn) + 1, nationName);
plog(LBRIEF, "%s turn %d orders checked for %s.\n",
aGame->name, (aGame->turn) + 1, nationName);
checkOrders(aGame, nationName, forecast);
}
else {
copyOrders(aGame, stdin, nationName, password, theTurnNumber);
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, %s advance orders received for %s.",
aGame->name, nationName);
plog(LBRIEF, "%s advance orders received for %s.\n",
aGame->name, nationName);
fprintf(forecast, "O wise leader your orders for turn %d "
"have been received and stored.\n", theTurnNumber);
}
}
else {
setHeader(anEnvelope, MAILHEADER_SUBJECT, "Galaxy HQ, major trouble");
plog(LBRIEF, "major trouble %d\n", resNumber);
generateErrorMessage(resNumber, aGame, nationName,
theTurnNumber, forecast);
}
fprintf(forecast, "\n\n%s\n", vcid);
fclose(forecast);
result = 0;
if (kind == CMD_CHECK_REAL) {
result |= eMail(aGame, anEnvelope, forecastName);
}
else {
char *forecastFile;
forecastFile =
createString("%s/forecasts/%s",
galaxynghome, argv[2], returnAddress);
GOS_copy(forecastName, forecastFile);
}
if (nationName)
free(nationName);
if (password)
free(password);
destroyEnvelope(anEnvelope);
result |= GOS_delete(forecastName);
result = (result) ? EXIT_FAILURE : EXIT_SUCCESS;
}
else {
fprintf(stderr, "Can't open \"%s\".\n", forecastName);
}
free(forecastName);
}
else {
usage();
}
closeLog();
return result;
}
NAME
CMD_checkFile --
NOTE
This should be merged with CMD_check().
NAME
CMD_create -- create a new galaxy and game.
SYNOPSIS
galaxyng -create <game specification file>
FUNCTION
Creates a new game based on the specification found in
the specification file.
INPUTS
specificationfile -- file with the dimensions of the galaxy
and the addresses of all the players. (.glx file).
SEE
CMD_mail0(), CMD_template()
SOURCE
int
CMD_create(int argc, char **argv)
{
gamespecification *gspec;
game *aGame;
int result;
FILE *specfile;
result = EXIT_FAILURE;
if (argc == 3) {
if ((specfile = GOS_fopen(argv[2], "r"))) {
gspec = readGameSpec(specfile);
fclose(specfile);
printGameSpecs(gspec);
if ((aGame = creategame(gspec))) {
struct fielddef fields;
fields.destination = stdout;
checkIntegrity(aGame);
savegame(aGame);
reportMap(aGame, aGame->players, &fields);
printf("Number of planets: %d\n", numberOfElements(aGame->planets));
result = EXIT_SUCCESS;
}
else {
fprintf(stderr, "Can't create the game\n");
}
}
else {
fprintf(stderr, "Can't open specification file \"%s\"\n", argv[2]);
}
}
else {
usage();
}
return result;
}
NAME
CMD_dump -- dump game data.
SYNOPSIS
./galaxyng -players <game> [turn]
./galaxyng -lastorders <game> [turn]
./galaxyng -map <game> [turn]
CMD_dump(int argc, char **argv, int kind)
FUNCTION
Dump game information.
SWITCHES
kind:
CMD_DUMP_LASTORDERS
show turn when players last send in orders.
CMD_DUMP_MAP
show a map of the galaxy
CMD_DUMP_PLAYERS
show password and address of players
CMD_DUMP_HALL
show information for use in the hall of fame.
SOURCE
int
CMD_dump(int argc, char **argv, int kind)
{
game *aGame;
int result;
int turn;
result = EXIT_FAILURE;
if (argc >= 3) {
if (argc == 3) {
turn = LG_CURRENT_TURN;
}
else {
turn = atoi(argv[3]);
}
if ((aGame = loadgame(argv[2], turn))) {
player *aDummyPlayer;
struct fielddef fields;
fields.destination = stdout;
loadConfig(aGame);
switch (kind) {
case CMD_DUMP_MAP:{
aDummyPlayer = allocStruct(player);
setName(aDummyPlayer, "DummyDummy");
aDummyPlayer->msize = aGame->galaxysize;
reportMap(aGame, aDummyPlayer, &fields);
break;
}
case CMD_DUMP_LASTORDERS:{
reportLastOrders(aGame->players, &fields);
break;
}
case CMD_DUMP_PLAYERS:{
reportPlayers(aGame->players, &fields);
break;
}
case CMD_DUMP_PSCORE:{
scorePercent(aGame, &fields);
break;
}
case CMD_DUMP_HALL:{
reportHall(aGame, &fields);
break;
}
case CMD_DUMP_MAILHEADER:{
createMailToAllHeader(aGame);
break;
}
result = EXIT_SUCCESS;
}
freegame(aGame);
}
else {
fprintf(stderr, "Could not load game \"%s\".\n", argv[2]);
}
}
else {
usage();
}
return result;
}
NAME
CMD_graph -- create a data dump for a graph of a game.
NOTES
Experimental. See Tools/graphscore.tcl
SOURCE
int
CMD_graph(int argc, char **argv)
{
game *aGame;
int result;
result = EXIT_FAILURE;
if (argc == 4) {
if ((aGame = loadgame(argv[2], atoi(argv[3])))) {
player *aPlayer;
int number;
nationStatus(aGame);
for (number = 0, aPlayer = aGame->players;
aPlayer;
aPlayer = aPlayer->next, number++) {
printf("%d %d %s %f\n", aGame->turn, number, aPlayer->name,
effectiveIndustry(aPlayer->totPop, aPlayer->totInd));
}
}
else {
fprintf(stderr, "Could not load game \"%s\" turn %s\n",
argv[2], argv[3]);
}
}
else {
usage();
}
return result;
}
NAME
CMD_mail0 -- mail the turn 0 reports.
SYNOPSIS
./galaxyng -mail0 <Game Name>
int CMD_mail0(int argc, char **argv)
FUNCTION
Mail the turn 0 reports to the players.
To be run after a new game is created.
SOURCE
int
CMD_mail0(int argc, char **argv, int kind)
{
game *aGame;
int result;
result = EXIT_FAILURE;
if (argc == 3) {
if ((aGame = loadgame(argv[2], LG_CURRENT_TURN))) {
player *aPlayer;
loadConfig(aGame);
checkIntegrity(aGame);
for (aPlayer = aGame->players;
aPlayer;
aPlayer = aPlayer->next) {
aPlayer->pswdstate = 1;
if (kind == CMD_CHECK_REAL) {
mailTurnReport(aGame, aPlayer, 0);
}
if ((aGame->gameOptions & GAME_SAVECOPY) | (kind == CMD_CHECK_DUMMY)) {
saveTurnReport(aGame, aPlayer, 0);
}
if (aPlayer->flags & F_XMLREPORT) {
if (kind == CMD_CHECK_DUMMY) {
saveTurnReport(aGame, aPlayer, F_XMLREPORT);
}
else {
mailTurnReport(aGame, aPlayer, F_XMLREPORT);
}
}
if (aPlayer->flags & F_MACHINEREPORT) {
if (kind == CMD_CHECK_DUMMY) {
saveTurnReport(aGame, aPlayer, F_MACHINEREPORT);
}
else {
mailTurnReport(aGame, aPlayer, F_MACHINEREPORT);
}
}
}
result = EXIT_SUCCESS;
}
else {
fprintf(stderr, "Could not load game \"%s\"\n", argv[2]);
}
}
else {
usage();
}
return result;
}
NAME
CMD_relay -- relay a message from one nation to another.
FUNCTION
NAME
CMD_report -- send a copy of a turn report.
SYNOPSIS
./galaxyng -check < file_with_email
int CMD_report(int argc, char **argv)
FUNCTION
Recreate a turn report of a given turn. Send it to the player
that requested it.
BUGS
Does not send XML nor machine reports.
SOURCE
int
CMD_report(int argc, char **argv)
{
int result;
char *logName;
logName = createString("%s/log/orders_processed.txt", galaxynghome);
openLog(logName, "a");
free(logName);
logLevel = LBRIEF;
plogtime(LBRIEF);
result = EXIT_FAILURE;
if (argc >= 2) {
char *returnAddress, *nationName, *password;
int resNumber, theTurnNumber;
game *aGame;
FILE *report;
char *reportName;
reportName = createString("%s/temp_report_copy", tempdir);
if ((report = GOS_fopen(reportName, "w"))) {
envelope *anEnvelope;
anEnvelope = createEnvelope();
returnAddress = getReturnAddress(stdin);
setHeader(anEnvelope, MAILHEADER_TO, "%s", returnAddress);
plog(LBRIEF, "Report request from %s.\n", returnAddress);
theTurnNumber = getTurnNumber(stdin);
nationName = NULL;
password = NULL;
aGame = NULL;
resNumber =
areValidOrders(stdin, &aGame, &nationName, &password, theTurnNumber);
if ((resNumber eq RES_TURNRAN) ||
((resNumber eq RES_OK) && (theTurnNumber eq LG_CURRENT_TURN))) {
game *aGame2;
if (theTurnNumber > 0) {
aGame2 = loadgame(aGame->name, theTurnNumber - 1);
}
else if (theTurnNumber == LG_CURRENT_TURN) {
theTurnNumber = aGame->turn;
aGame2 = loadgame(aGame->name, theTurnNumber - 1);
}
else {
aGame2 = loadgame(aGame->name, 0);
}
if (aGame2) {
player *aPlayer;
int index;
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, Copy of turn %d report",
theTurnNumber);
if (theTurnNumber > 0) { /* Rerun the turn */
char *ordersName;
ordersName =
createString("%s/orders/%s/%d.all",
galaxynghome, aGame2->name, theTurnNumber);
runTurn(aGame2, ordersName);
free(ordersName);
}
/* Translate the current nation name into the name used during the turn *
* * * that is requested */
aPlayer = findElement(player, aGame->players, nationName);
index = ptonum(aGame->players, aPlayer);
aPlayer = numtop(aGame2->players, index);
if (theTurnNumber == 0)
aPlayer->pswdstate = 1;
highScoreList(aGame2);
createTurnReport(aGame2, aPlayer, report, 0);
}
else {
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, Copy of turn report request.");
fprintf(report, "\n\nThe turn you requested is no longer available...\n");
}
}
else if (resNumber eq RES_OK) {
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, Major Trouble");
fprintf(report, "You can not request a report for the next turn\n");
fprintf(report, "or any following turns,"
" I can not see into the future!\n");
}
else {
setHeader(anEnvelope, MAILHEADER_SUBJECT,
"Galaxy HQ, Major Trouble");
generateErrorMessage(
resNumber, aGame, nationName, theTurnNumber, report);
}
fclose(report);
result = eMail(aGame, anEnvelope, reportName);
destroyEnvelope(anEnvelope);
result |= ssystem("rm %s", reportName);
result = (result) ? EXIT_FAILURE : EXIT_SUCCESS;
if (nationName)
free(nationName);
if (password)
free(password);
}
else {
fprintf(stderr, "Can't open \"%s\"\n", reportName);
}
free(reportName);
}
else {
usage();
}
closeLog();
return result;
}
NAME
CMD_run -- run turn and send turn reports
SYNOPSIS
./galaxyng -run <game name> <file with all orders>
FUNCTION
Run an turn, Compute the highscore list, and send the turn reports
to all players. The GM is send a status report. If the option
SaveReportCopy is specified in the .galaxyngrc file, a copy of each
turn report is also saved in reports/
This function is also run for:
./galaxyng -dummyrun <game name> <file with all orders>
In this case the run is a dummy run, and the turn reports are stored
in reports/. Nothing is mailed. This is used to debug the server code.
OUTPUT
Turn reports are send out to the players and the turn is saved
to disk. The GM is sent a status report. A log can be found in
log/<game name>.
DIAGNOSTICS
Message to stderr in case of an error.
(Game does not exist, not the right time to run the game,
game structure is corrupted).
RESULT
EXIT_FAILURE or EXIT_SUCCESS
SOURCE
int
CMD_run(int argc, char **argv, int kind)
{
int result;
result = EXIT_FAILURE;
if (argc >= 4) {
game *aGame;
int turn;
char *logName;
logLevel = LPART;
logName = createString("%s/log/%s", galaxynghome, argv[2]);
openLog(logName, "w");
free(logName);
plogtime(LPART);
plog(LPART, "Trying to run Game \"%s\".\n", argv[2]);
aGame = NULL;
turn = (argc == 4) ? LG_CURRENT_TURN : atoi(argv[4]) - 1;
if ((aGame = loadgame(argv[2], turn))) {
player *aPlayer;
loadConfig(aGame);
if (checkTime(aGame) || (kind == CMD_RUN_DUMMY)) {
checkIntegrity(aGame);
if (runTurn(aGame, argv[3])) {
highScoreList(aGame);
result = 0;
for (aPlayer = aGame->players; aPlayer; aPlayer = aPlayer->next) {
if (kind == CMD_RUN_REAL) {
result |= mailTurnReport(aGame, aPlayer, 0);
if (aGame->gameOptions & GAME_SAVECOPY) {
saveTurnReport(aGame, aPlayer, 0);
}
}
else {
saveTurnReport(aGame, aPlayer, 0);
}
if (aPlayer->flags & F_XMLREPORT) {
if (kind == CMD_RUN_REAL) {
result |= mailTurnReport(aGame, aPlayer, F_XMLREPORT);
}
else {
saveTurnReport(aGame, aPlayer, F_XMLREPORT);
}
}
if (aPlayer->flags & F_MACHINEREPORT) {
if (kind == CMD_RUN_REAL) {
result |= mailTurnReport(aGame, aPlayer, F_MACHINEREPORT);
}
else {
saveTurnReport(aGame, aPlayer, F_MACHINEREPORT);
}
}
}
savegame(aGame);
}
else {
fprintf(stderr,
"The server has detected an error in the game data structure. The run\n"
"of the turn has been aborted. No turn reports have been send. Please\n"
"contact Frans Slothouber at fslothouber@acm.org for a solution to this\n"
"problem.\n");
result = 1;
}
plogtime(LPART);
plog(LPART, "Run is completed.\n");
result = (result) ? EXIT_FAILURE : EXIT_SUCCESS;
}
else {
plog(LBRIEF, "Error, attempt to run the game \"%s\" at the"
" wrong time.\n"
"You specified a starttime of %s in your .galaxyngrc file.\n",
argv[2], aGame->starttime);
fprintf(stderr,
"Error, attempt to run the game \"%s\" at the wrong time.\n"
"You specified a starttime of %s in your .galaxyngrc file.\n",
argv[2], aGame->starttime);
}
closeLog();
if (kind == CMD_RUN_REAL) {
mailGMReport(aGame, argv[2]);
}
freegame(aGame);
}
else {
plog(LBRIEF, "Game \"%s\" does not exist.\n", argv[2]);
fprintf(stderr, "Game \"%s\" does not exist.\n", argv[2]);
}
}
else {
usage();
}
closeLog();
return result;
}
NAME
CMD_score -- Show highscore list.
FUNCTION
Write a HTML-ized version of the highscore list to stdout.
SOURCE
int
CMD_score(int argc, char **argv)
{
int result;
game *aGameThisTurn;
game *aGamePrevTurn;
result = EXIT_FAILURE;
if (argc == 3) {
if ((aGameThisTurn = loadgame(argv[2], LG_CURRENT_TURN))) {
if ((aGamePrevTurn =
loadgame(aGameThisTurn->name, aGameThisTurn->turn - 1))) {
score(aGamePrevTurn, aGameThisTurn, TRUE, stdout);
result = EXIT_SUCCESS;
}
else {
fprintf(stderr, "Could not load game \"%s\"\n", argv[2]);
}
}
else {
fprintf(stderr, "Could not load game \"%s\" turn %d\n", argv[2],
aGameThisTurn->turn - 1);
}
}
else {
usage();
}
return result;
}
NAME
CMD_selftest -- run a series of selftests
FUNCTION
Run a series of selftest. Used for debug purposes.
NAME
CMD_template -- Create a template .glx file that the GM can edit.
SYNOPSIS
./galaxyng <name> <number of players>
FUNCTION
Creates a template .glx file.
All parameters are given some sensible default values.
The number of players is used to determine the size of the galaxy,
using the following formule
42 * ceil (sqrt(number of players))
For games with very few players this size is sometimes too small.
SOURCE
int
CMD_template(int argc, char **argv)
{
int result = EXIT_FAILURE;
if (argc == 4) {
FILE *glxfile;
char *glxname;
int numberOfPlayers;
glxname = createString("%s.glx", argv[2]);
numberOfPlayers = atoi(argv[3]);
if ((glxfile = GOS_fopen(glxname, "w"))) {
int i;
int gsize;
fprintf(glxfile, "\n\nname %s\n\n", argv[2]);
gsize = (int) (42.0 * ceil(sqrt((double) numberOfPlayers)));
gsize /= 10;
gsize *= 10;
fprintf(glxfile,
"; The following size is only approximately right.\n"
"; You probably want to experiment with different sizes to get a galaxy\n"
"; that looks right. It should not be too crowded nor too sparse.\n\n");
fprintf(glxfile, "size %d\n", gsize);
fprintf(glxfile,
"\n"
"; The engine will make sure that distance between any of primary home\n"
"; planets is atleast 30.0 light years.\n"
"\n"
"nation_spacing 30.0\n"
"\n"
"; The sizes of the core home planets for each nation.\n"
"; The following would give each nation 3 homeplanets of sizes\n"
"; 1000 250 350. The first one is the primary home planet.\n"
"; You have to define these before any of the player definitions.\n"
"\n"
"core_sizes 1000 250 350\n"
"\n"
"; Within a radius [2,r] from the primary home world the engine allocates\n"
"; a number of empty planets for the nation to colonize.\n"
"; The following two parameters define how many there are per nation,\n"
"; and in within what radius. A number between 4 and 10 and\n"
"; a radius of nation_spacing/2.0 is a good guess.\n"
"\n"
"empty_planets 6\n"
"empty_radius 15\n"
"\n"
"; It is possible to add a number of 'stuff' planets. These are useless\n"
"; planets, all of size 50 or less, that are use to fill up the empty\n"
"; space between the home worlds. They make it possible for a players to\n"
"; approach (attack) other players by different routes. The following\n"
"; parameter specifies how many there are per nation.\n"
"\n"
"stuff_planets 8\n"
";\n"
"; The list of the players, you can add here the mail address\n"
"; of each player that enrolled in your game.\n"
";\n"
"\n");
for (i = 1; i <= numberOfPlayers; i++) {
fprintf(glxfile, "player player%d@itsaddress.somehwere\n", i);
}
fprintf(glxfile,
";\n"
"; You can override the core size for a player by adding the sizes.\n"
"; For instance the following player will get one home planet\n"
"; of size 1600.0\n"
"\n"
"; player player3@itsaddress.somewhere 1600.0\n"
"\n"
"; While the following player gets 3 home planets of sizes\n"
"; 500.0, 100.0, and 1000.0\n"
"\n"
"; player player4@itsaddress.somewhere 500.0 100.0 1000.0\n\n");
fclose(glxfile);
}
else {
fprintf(stderr, "Can't open \"%s\".\n", glxname);
}
printf("Created the file \"%s\".\n", glxname);
free(glxname);
}
else {
usage();
}
return result;
}
NAME
CMD_test -- check the integrity of a game.
FUNCTION
Check if a GAME is OK by running checkIntegrity() on it.
NAME
checkTime -- check if it is really time to run a turn.
SYNOPSIS
int checkTime(game *aGame)
FUNCTION
Does a sanity check to see if a turn really has to be run. On
some systems, after a reboot, crontab goes bezerk and executes a
whole bunch of entries in your crontab file for no good reason.
This will cause turns to be run prematurely.
This function checks if the current time is equal to the time a
game is supposed to be run. The GM has to put this time in a
game specific .galaxyngrc file, using the starttime key.
EXAMPLE
You want to make sure a game runs at 13:00. Add the entry
starttime 13:00
to the .galaxyngrc file. The a turn will then only run, if and
only if, it is started by between 13:00 and 13:09. Add starttime
13:10, and it will only run if started between 13:10 and 13:19.
RESULT
TRUE -- the game is allowed to run.
FALSE -- the game is not allowed to run.
SOURCE
int
checkTime(game *aGame)
{
int runGame;
assert(aGame != NULL);
runGame = FALSE;
if (aGame->starttime) {
char timeBuffer[255];
time_t ttp;
time(&ttp);
strftime(timeBuffer, 255, "%H:%M", localtime(&ttp));
if (strncmp(timeBuffer, aGame->starttime, 4) == 0) {
runGame = TRUE;
}
}
else {
runGame = TRUE;
}
return runGame;
}
NAME
galaxynghome -- path to all data files
SOURCE
char *galaxynghome = NULL;
NAME
lineBuffer -- global line buffer.
NOTES
2 is there to prevent buffer overflows.
SOURCE
char lineBuffer[2 * LINE_BUFFER_SIZE];
NAME
logFile --
SOURCE
FILE *logFile = NULL;
NAME
logLevel -- specifies the level of detail in log files.
SOURCE
int logLevel = LFULL;
NAME
main -- the start of it all.
RESULT
Reports any errors that occur back to the environment.
SOURCE
int
main(int argc, char **argv)
{
char *value;
int result;
/* Some initializations */
resetErnie(197162622);
nbrProducts = sizeof(productname) / sizeof(char *);
/* This should be a function */
if ((value = getenv("GALAXYNGHOME"))) {
galaxynghome = strdup(value);
}
else if ((value = getenv("HOME"))) {
sprintf(lineBuffer, "%s/Games", value);
galaxynghome = strdup(lineBuffer);
}
else {
galaxynghome = strdup("/please/set/your/HOME/or/GALAXYNGHOME/variable");
}
#ifdef WIN32
/* This should be a function */
if ((value = getenv("TEMP"))) {
tempdir = strdup(value);
}
else if ((value = getenv("TMP"))) {
tempdir = strdup(value);
}
else {
tempdir = strdup("c:\temp");
}
#else
tempdir = strdup("/tmp");
#endif
if (argc <= 1) {
usage();
}
else if (strstr(argv[1], "create")) {
result = CMD_create(argc, argv);
}
else if (strstr(argv[1], "dummymail0")) {
result = CMD_mail0(argc, argv, CMD_CHECK_DUMMY);
}
else if (strstr(argv[1], "mail0")) {
result = CMD_mail0(argc, argv, CMD_CHECK_REAL);
}
else if (strstr(argv[1], "filecheck")) {
result = CMD_checkFile(argc, argv, CMD_CHECK_DUMMY);
}
else if (strstr(argv[1], "dummycheck")) {
result = CMD_check(argc, argv, CMD_CHECK_DUMMY);
}
else if (strstr(argv[1], "check")) {
result = CMD_check(argc, argv, CMD_CHECK_REAL);
}
else if (strstr(argv[1], "dummyrun")) {
result = CMD_run(argc, argv, CMD_RUN_DUMMY);
}
else if (strstr(argv[1], "run")) {
result = CMD_run(argc, argv, CMD_RUN_REAL);
}
else if (strstr(argv[1], "selftest")) { /* experimental */
result = CMD_selftest();
}
else if (strstr(argv[1], "battletest")) { /* experimental */
result = CMD_battletest(argc, argv);
}
else if (strstr(argv[1], "test")) { /* experimental */
result = CMD_test(argc, argv);
}
else if (strstr(argv[1], "report")) {
result = CMD_report(argc, argv);
}
else if (strstr(argv[1], "relay")) {
result = CMD_relay(argc, argv);
}
else if (strstr(argv[1], "pscore")) { /* experimental */
result = CMD_dump(argc, argv, CMD_DUMP_PSCORE);
}
else if (strstr(argv[1], "score")) {
result = CMD_score(argc, argv);
}
else if (strstr(argv[1], "graph")) { /* experimental */
result = CMD_graph(argc, argv);
}
else if (strstr(argv[1], "template")) {
result = CMD_template(argc, argv);
}
else if (strstr(argv[1], "map")) {
result = CMD_dump(argc, argv, CMD_DUMP_MAP);
}
else if (strstr(argv[1], "hall")) {
result = CMD_dump(argc, argv, CMD_DUMP_HALL);
}
else if (strstr(argv[1], "lastorders")) {
result = CMD_dump(argc, argv, CMD_DUMP_LASTORDERS);
}
else if (strstr(argv[1], "players")) {
result = CMD_dump(argc, argv, CMD_DUMP_PLAYERS);
}
else if (strstr(argv[1], "toall")) {
result = CMD_dump(argc, argv, CMD_DUMP_MAILHEADER);
}
else {
usage();
}
return result;
}
NAME
options -- options available to players.
FUNCTION
Associative array to look-up option flag by option names.
SOURCE
struct option options[] =
{
{"Anonymous", F_ANONYMOUS},
{"AutoUnload", F_AUTOUNLOAD},
{"ProdTable", F_PRODTABLE},
{"SortGroups", F_SORTGROUPS},
{"GroupForeCast", F_GROUPFORECAST},
{"PlanetForeCast", F_PLANETFORECAST},
{"ShipTypeForecast", F_SHIPTYPEFORECAST},
{"RoutesForecast", F_ROUTESFORECAST},
{"Compress", F_COMPRESS},
{"Gplus", F_GPLUS},
{"MachineReport", F_MACHINEREPORT}, /* CB 1998 - Experimental */
{"BattleProtocol", F_BATTLEPROTOCOL},
{"XMLReport", F_XMLREPORT}, /* KDW 1999 - experimental */
{NULL, 0}
};
NAME
productname -- things a planet can produce.
SOURCE
char *productname[] =
{
"CAP", "MAT", 0, "Drive", "Weapons", "Shields", "Cargo",
};
NAME
relayMessage --
NAME
tempdir -- path to the directory used to store temporary files.
SOURCE
char *tempdir = NULL;
NAME
usage -- print usage info.