* Phantasia 3.3.2 -- Interterminal fantasy game
* This game is distributed for free as is. It is not guaranteed to work
* in every conceivable environment. It is not even guaranteed to work
* This game is distributed without notice of copyright, therefore it
* may be used in any manner the recipient sees fit. However, the
* author assumes no responsibility for maintaining or revising this
* game, in its original form, or any derivitives thereof.
* The author shall not be responsible for any loss, cost, or damage,
* including consequential damage, caused by reliance on this material.
* The author makes no warranties, express or implied, including warranties
* of merchantability or fitness for a particular purpose or use.
* AT&T is in no way connected with this game.
* The program allocates as much file space as it needs to store characters,
* so the possibility exists for the character file to grow without bound.
* The file is purged upon normal entry to try to avoid that problem.
* A similar problem exists for energy voids. To alleviate the problem here,
* the void file is cleared with every new king, and a limit is placed
* on the size of the energy void file.
* Put one line of text into the file 'motd' for announcements, etc.
* If ENEMY is #defined, a list of restricted login names is checked
* in the file 'enemy'. These names are listed, one per line, with
* The scoreboard file is updated when someone dies, and keeps track
* of the highest character to date for that login.
* Being purged from the character file does not cause the scoreboard
* All source files are set up for 'vi' with shiftwidth=4, tabstop=8.
* main.c Main routines for Phantasia
/***************************************************************************
/ FUNCTION: initialize state, and call main process
/ AUTHOR: E. A. Estes, 12/4/85
/ int argc - argument count
/ char **argv - argument vector
/ MODULES CALLED: monstlist(), checkenemy(), ok_to_play(), activelist(),
/ throneroom(), checkbattle(), readmessage(), changestats(), writerecord(),
/ tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampered(),
/ fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(),
/ signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(),
/ strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain(),
/ playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initialstate(),
/ scorelist(), titlelist()
/ GLOBAL INPUTS: *Login, Throne, Wizard, Player, *stdscr, Changed, Databuf[],
/ Fileloc, Helpfile[], Stattable[]
/ GLOBAL OUTPUTS: Wizard, Player, Changed, Fileloc, Timeout, *Statptr
/ Process arguments, initialize program, and loop forever processing
/***************************************************************************/
bool noheader
= FALSE
; /* set if don't want header */
bool headeronly
= FALSE
; /* set if only want header */
bool examine
= FALSE
; /* set if examine a character */
long seconds
; /* for time of day */
double dtemp
; /* for temporary calculations */
initialstate(); /* init globals */
checkenemy(); /* check if denied access */
while (--argc
&& (*++argv
)[0] == '-')
case 'a': /* all users */
case 'p': /* purge old players */
case 'S': /* set 'Wizard' */
Wizard
= (getuid() == UID
);
case 'b': /* scoreboard */
system(strcat(Databuf
, Helpfile
));
if (!isatty(0)) /* don't let non-tty's play */
playinit(); /* set up to catch signals, init curses */
purgeoldplayers(); /* clean up old characters */
mvaddstr(23, 27, "Sorry, you can't play now.\n");
/* get the player structure filled */
mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? ");
switch (getanswer("NYQ", FALSE
))
Fileloc
= recallplayer();
Fileloc
= rollnewplayer();
if (Player
.p_level
> 5.0)
/* low level players have long timeout */
/* update some important player statistics */
strcpy(Player
.p_login
, Login
);
Player
.p_lastused
= localtime(&seconds
)->tm_yday
;
Player
.p_status
= S_PLAYING
;
writerecord(&Player
, Fileloc
);
Statptr
= &Stattable
[Player
.p_type
]; /* initialize pointer */
sigset(SIGINT
, interrupt
);
signal(SIGINT
, interrupt
);
signal(SIGINT
, interrupt
);
signal(SIGINT
, interrupt
);
altercoordinates(Player
.p_x
, Player
.p_y
, A_FORCED
); /* set some flags */
/* loop forever, processing input */
mvaddstr(6, 0, "Whoops! Can't play now.\n");
adjuststats(); /* cleanup stats */
if (Throne
&& Player
.p_crowns
== 0 && Player
.p_specialtype
!= SC_KING
)
/* not allowed on throne -- move */
mvaddstr(5,0,"You're not allowed in the Lord's Chamber without a crown.\n");
altercoordinates(0.0, 0.0, A_NEAR
);
checktampered(); /* check for energy voids, etc. */
if (Player
.p_status
!= S_CLOAKED
&& (dtemp
= fabs(Player
.p_x
)) == fabs(Player
.p_y
)
dtemp
= sqrt(dtemp
/ 100.0);
if (floor(dtemp
) == dtemp
)
/* |x| / 100 == n*n; at a trading post */
checkbattle(); /* check for player to player battle */
neatstuff(); /* gurus, medics, etc. */
if (Player
.p_status
== S_CLOAKED
)
/* costs 3 mana per turn to be cloaked */
/* ran out of mana, uncloak */
Player
.p_status
= S_PLAYING
;
if (Player
.p_status
!= S_PLAYING
&& Player
.p_status
!= S_CLOAKED
)
/* change status back to S_PLAYING */
Player
.p_status
= S_PLAYING
;
/* update file only if important stuff has changed */
writerecord(&Player
, Fileloc
);
readmessage(); /* read message, if any */
displaystats(); /* print statistics */
/* maybe make king, print prompt, etc. */
addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit ");
if (Player
.p_level
>= MEL_CLOAK
&& Player
.p_magiclvl
>= ML_CLOAK
)
if (Player
.p_level
>= MEL_TELEPORT
&& Player
.p_magiclvl
>= ML_TELEPORT
)
if (Player
.p_specialtype
>= SC_COUNCIL
|| Wizard
)
procmain(); /* process input */
/************************************************************************
/ FUNCTION NAME: initialstate()
/ FUNCTION: initialize some important global variable
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: time(), fopen(), srandom(), error(), getuid(), getlogin(),
/ GLOBAL INPUTS: Peoplefile[], Voidfile[], Messfile[], Monstfile[]
/ GLOBAL OUTPUTS: *Energyvoidfp, Echo, Marsh, *Login, Users, Beyond,
/ Throne, Wizard, Changed, Okcount, Timeout, Windows, *Monstfp, *Messagefp,
/ Set global flags, and open files which remain open.
/************************************************************************/
if ((Login
= getlogin()) == NULL
)
Login
= getpwuid(getuid())->pw_name
;
if ((Playersfp
= fopen(Peoplefile
, "r+")) == NULL
)
if ((Monstfp
= fopen(Monstfile
, "r+")) == NULL
)
if ((Messagefp
= fopen(Messfile
, "r")) == NULL
)
if ((Energyvoidfp
= fopen(Voidfile
, "r+")) == NULL
)
srandom((unsigned) time((long *) NULL
)); /* prime random numbers */
/************************************************************************
/ FUNCTION NAME: rollnewplayer()
/ FUNCTION: roll up a new character
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(),
/ wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw(),
/ getanswer(), getstring()
/ GLOBAL INPUTS: Other, Wizard, Player, *stdscr, Databuf[]
/ Prompt player, and roll up new character.
/************************************************************************/
int chartype
; /* character type */
initplayer(&Player
); /* initialize player structure */
mvaddstr(4, 21, "Which type of character do you want:");
mvaddstr(8, 4, "1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento ");
chartype
= getanswer("1234567", FALSE
);
chartype
= getanswer("123456", FALSE
);
genchar(chartype
); /* roll up a character */
"Strength : %2.0f Quickness: %2.0f Mana : %2.0f\n",
Player
.p_strength
, Player
.p_quickness
, Player
.p_mana
);
"Energy Level: %2.0f Brains : %2.0f Magic Level: %2.0f\n",
Player
.p_energy
, Player
.p_brains
, Player
.p_magiclvl
);
if (Player
.p_type
== C_EXPER
|| Player
.p_type
== C_SUPER
)
mvaddstr(14, 14, "Type '1' to keep >");
ch
= getanswer(" ", TRUE
);
if (Player
.p_type
== C_EXPER
|| Player
.p_type
== C_SUPER
)
/* get coordinates for experimento */
mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? ");
getstring(Databuf
, SZ_DATABUF
);
sscanf(Databuf
, "%lf %lf", &Player
.p_x
, &Player
.p_y
);
if (fabs(Player
.p_x
) > D_EXPER
|| fabs(Player
.p_y
) > D_EXPER
)
mvaddstr(17, 0, "Invalid coordinates. Try again.\n");
/* name the new character */
"Give your character a name [up to %d characters] ? ", SZ_NAME
- 1);
getstring(Player
.p_name
, SZ_NAME
);
truncstring(Player
.p_name
); /* remove trailing blanks */
if (Player
.p_name
[0] == '\0')
mvaddstr(19, 0, "Invalid name.");
else if (findname(Player
.p_name
, &Other
) >= 0L)
/* cannot have duplicate names */
mvaddstr(19, 0, "Name already in use.");
addstr(" Pick another.\n");
/* get a password for character */
mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? ");
getstring(Player
.p_password
, SZ_PASSWORD
);
mvaddstr(21, 0, "One more time to verify ? ");
getstring(Databuf
, SZ_PASSWORD
);
while (strcmp(Player
.p_password
, Databuf
) != 0);
/************************************************************************
/ FUNCTION NAME: procmain()
/ FUNCTION: process input from player
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: dotampered(), changestats(), inputoption(), allstatslist(),
/ fopen(), wmove(), drandom(), sscanf(), fclose(), altercoordinates(),
/ waddstr(), fprintf(), distance(), userlist(), leavegame(), encounter(),
/ getstring(), wclrtobot()
/ GLOBAL INPUTS: Circle, Illcmd[], Throne, Wizard, Player, *stdscr,
/ Databuf[], Illmove[], Messfile[]
/ GLOBAL OUTPUTS: Player, Changed
/ Process main menu options.
/************************************************************************/
double x
; /* desired new x coordinate */
double y
; /* desired new y coordinate */
double temp
; /* for temporary calculations */
FILE *fp
; /* for opening files */
register int loop
; /* a loop counter */
bool hasmoved
= FALSE
; /* set if player has moved */
mvaddstr(4, 0, "\n\n"); /* clear status area */
clrtobot(); /* clear data on bottom area of screen */
if (Player
.p_specialtype
== SC_VALAR
&& (ch
== '1' || ch
== '7'))
case 'K': /* move up/north */
y
= Player
.p_y
+ MAXMOVE();
case 'J': /* move down/south */
y
= Player
.p_y
- MAXMOVE();
case 'L': /* move right/east */
x
= Player
.p_x
+ MAXMOVE();
case 'H': /* move left/west */
x
= Player
.p_x
- MAXMOVE();
Player
.p_energy
+= (Player
.p_maxenergy
+ Player
.p_shield
) / 15.0
+ Player
.p_level
/ 3.0 + 2.0;
MIN(Player
.p_energy
, Player
.p_maxenergy
+ Player
.p_shield
);
if (Player
.p_status
!= S_CLOAKED
)
/* cannot find mana if cloaked */
Player
.p_mana
+= (Circle
+ Player
.p_level
) / 4.0;
if (drandom() < 0.2 && Player
.p_status
== S_PLAYING
&& !Throne
)
case 'X': /* change/examine a character */
for (loop
= 3; loop
; --loop
)
mvaddstr(4, 0, "X Y Coordinates ? ");
getstring(Databuf
, SZ_DATABUF
);
if (sscanf(Databuf
, "%lf %lf", &x
, &y
) != 2)
mvaddstr(5, 0, "Try again\n");
else if (distance(Player
.p_x
, x
, Player
.p_y
, y
) > MAXMOVE())
mvaddstr(4, 0, "Message ? ");
getstring(Databuf
, SZ_DATABUF
);
/* we open the file for writing to erase any data which is already there */
fp
= fopen(Messfile
, "w");
fprintf(fp
, "%s: %s", Player
.p_name
, Databuf
);
if (Player
.p_level
< MEL_CLOAK
|| Player
.p_magiclvl
< ML_CLOAK
)
else if (Player
.p_status
== S_CLOAKED
)
Player
.p_status
= S_PLAYING
;
else if (Player
.p_mana
< MM_CLOAK
)
mvaddstr(5, 0, "No mana left.\n");
Player
.p_mana
-= MM_CLOAK
;
Player
.p_status
= S_CLOAKED
;
* conditions for teleport
* - 20 per (level plus magic level)
* - OR council of the wise or valar or ex-valar
* - OR transport from throne
* transports from throne cost no mana
if (Player
.p_level
< MEL_TELEPORT
|| Player
.p_magiclvl
< ML_TELEPORT
)
for (loop
= 3; loop
; --loop
)
mvaddstr(4, 0, "X Y Coordinates ? ");
getstring(Databuf
, SZ_DATABUF
);
if (sscanf(Databuf
, "%lf %lf", &x
, &y
) == 2)
temp
= distance(Player
.p_x
, x
, Player
.p_y
, y
);
/* can transport anywhere from throne */
&& Player
.p_specialtype
<= SC_COUNCIL
/* council, valar can transport anywhere */
&& temp
> (Player
.p_level
+ Player
.p_magiclvl
) * 20.0)
/* can only move 20 per exp. level + mag. level */
temp
= (temp
/ 75.0 + 1.0) * 20.0; /* mana used */
if (!Throne
&& temp
> Player
.p_mana
)
mvaddstr(5, 0, "Not enough power for that distance.\n");
/* no monsters while on throne */
mvaddstr(5, 0, "No monsters in the chamber!\n");
else if (Player
.p_specialtype
!= SC_VALAR
)
/* the valar cannot call monsters */
if (Wizard
|| Player
.p_specialtype
== SC_KING
&& Throne
)
/* kings must be on throne to decree */
case '8': /* intervention */
if (Wizard
|| Player
.p_specialtype
>= SC_COUNCIL
)
/* player has moved -- alter coordinates, and do random monster */
altercoordinates(x
, y
, A_SPECIFIC
);
if (drandom() < 0.2 && Player
.p_status
== S_PLAYING
&& !Throne
)
/************************************************************************
/ FUNCTION NAME: checkenemy()
/ FUNCTION: check login name against enemy list
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: fopen(), fgets(), strcmp(), fclose(), printf(), cleanup()
/ GLOBAL INPUTS: *Login, Databuf[], Enemyfile[]
/ The enemy file has a list of login names which are denied
/ We scan this list and exit if the current login name is
/************************************************************************/
FILE *fp
; /* to open enemy file */
/* check hit list of restricted accounts */
if ((fp
= fopen(Enemyfile
, "r")) != NULL
)
while (fgets(Databuf
, SZ_DATABUF
, fp
) != NULL
)
if (strcmp(Login
, Databuf
) == 0)
printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", Login
);
printf ("Mail comments to %s.\n", WIZARD
);
/************************************************************************
/ FUNCTION NAME: titlelist()
/ FUNCTION: print title page
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: fread(), fseek(), fopen(), fgets(), wmove(), strcpy(),
/ fclose(), strlen(), waddstr(), sprintf(), wrefresh()
/ GLOBAL INPUTS: Lines, Other, *stdscr, Databuf[], Lastdead[], Motdfile[],
/ Print important information about game, players, etc.
/************************************************************************/
register FILE *fp
; /* used for opening various files */
bool councilfound
= FALSE
; /* set if we find a member of the council */
bool kingfound
= FALSE
; /* set if we find a king */
double hiexp
, nxtexp
; /* used for finding the two highest players */
double hilvl
, nxtlvl
; /* used for finding the two highest players */
char hiname
[21], nxtname
[21];/* used for finding the two highest players */
mvaddstr(0, 14, "W e l c o m e t o P h a n t a s i a (vers. 3.3.2)!");
/* print message of the day */
if ((fp
= fopen(Motdfile
, "r")) != NULL
&& fgets(Databuf
, SZ_DATABUF
, fp
) != NULL
)
mvaddstr(2, 40 - strlen(Databuf
) / 2, Databuf
);
while (fread((char *) &Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
if (Other
.p_specialtype
== SC_KING
&& Other
.p_status
!= S_NOTUSED
)
sprintf(Databuf
, "The present ruler is %s Level:%.0f",
Other
.p_name
, Other
.p_level
);
mvaddstr(4, 40 - strlen(Databuf
) / 2, Databuf
);
mvaddstr(4, 24, "There is no ruler at this time.");
while (fread((char *) &Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
if (Other
.p_specialtype
== SC_VALAR
&& Other
.p_status
!= S_NOTUSED
)
sprintf(Databuf
, "The Valar is %s Login: %s", Other
.p_name
, Other
.p_login
);
mvaddstr(6, 40 - strlen(Databuf
) / 2 , Databuf
);
/* search for council of the wise */
while (fread((char *) &Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
if (Other
.p_specialtype
== SC_COUNCIL
&& Other
.p_status
!= S_NOTUSED
)
/* found a member of the council */
mvaddstr(8, 30, "Council of the Wise:");
/* This assumes a finite (<=5) number of C.O.W.: */
sprintf(Databuf
, "%s Login: %s", Other
.p_name
, Other
.p_login
);
mvaddstr(Lines
++, 40 - strlen(Databuf
) / 2, Databuf
);
/* search for the two highest players */
nxtname
[0] = hiname
[0] = '\0';
while (fread((char *) &Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
if (Other
.p_experience
> hiexp
&& Other
.p_specialtype
<= SC_KING
&& Other
.p_status
!= S_NOTUSED
)
/* highest found so far */
hiexp
= Other
.p_experience
;
strcpy(hiname
, Other
.p_name
);
else if (Other
.p_experience
> nxtexp
&& Other
.p_specialtype
<= SC_KING
&& Other
.p_status
!= S_NOTUSED
)
/* next highest found so far */
nxtexp
= Other
.p_experience
;
strcpy(nxtname
, Other
.p_name
);
mvaddstr(15, 28, "Highest characters are:");
sprintf(Databuf
, "%s Level:%.0f and %s Level:%.0f",
hiname
, hilvl
, nxtname
, nxtlvl
);
mvaddstr(17, 40 - strlen(Databuf
) / 2, Databuf
);
if ((fp
= fopen(Lastdead
,"r")) != NULL
&& fgets(Databuf
, SZ_DATABUF
, fp
) != NULL
)
mvaddstr(19, 25, "The last character to die was:");
mvaddstr(20, 40 - strlen(Databuf
) / 2,Databuf
);
/************************************************************************
/ FUNCTION NAME: recallplayer()
/ FUNCTION: find a character on file
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: writerecord(), truncstring(), more(), death(), wmove(),
/ wclear(), strcmp(), printw(), cleanup(), waddstr(), findname(), mvprintw(),
/ getanswer(), getstring()
/ GLOBAL INPUTS: Player, *stdscr, Databuf[]
/ GLOBAL OUTPUTS: Echo, Player
/ Search for a character of a certain name, and check password.
/************************************************************************/
long loc
= 0L; /* location in player file */
register int loop
; /* loop counter */
mvprintw(10, 0, "What was your character's name ? ");
getstring(Databuf
, SZ_NAME
);
if ((loc
= findname(Databuf
, &Player
)) >= 0L)
for (loop
= 0; loop
< 2; ++loop
)
/* prompt for password */
mvaddstr(11, 0, "Password ? ");
getstring(Databuf
, SZ_PASSWORD
);
if (strcmp(Databuf
, Player
.p_password
) == 0)
if (Player
.p_status
!= S_OFF
)
/* player did not exit normally last time */
addstr("Your character did not exit normally last time.\n");
addstr("If you think you have good cause to have your character saved,\n");
printw("you may quit and mail your reason to '%s'.\n", WIZARD
);
addstr("Otherwise, continuing spells certain death.\n");
addstr("Do you want to quit ? ");
ch
= getanswer("YN", FALSE
);
Player
.p_status
= S_HUNGUP
;
writerecord(&Player
, loc
);
mvaddstr(12, 0, "No good.\n");
mvaddstr(11, 0, "Not found.\n");
/************************************************************************
/ FUNCTION NAME: neatstuff()
/ FUNCTION: do random stuff
/ AUTHOR: E. A. Estes, 3/3/86
/ MODULES CALLED: collecttaxes(), floor(), wmove(), drandom(), infloat(),
/ waddstr(), mvprintw(), getanswer()
/ GLOBAL INPUTS: Player, *stdscr, *Statptr
/ Handle gurus, medics, etc.
/************************************************************************/
double temp
; /* for temporary calculations */
switch ((int) ROLL(0.0, 100.0))
if (Player
.p_poison
> 0.0)
mvaddstr(4, 0, "You've found a medic! How much will you offer to be cured ? ");
if (temp
< 0.0 || temp
> Player
.p_gold
)
/* negative gold, or more than available */
mvaddstr(6, 0, "He was not amused, and made you worse.\n");
else if (drandom() / 2.0 > (temp
+ 1.0) / MAX(Player
.p_gold
, 1))
/* medic wants 1/2 of available gold */
mvaddstr(5, 0, "Sorry, he wasn't interested.\n");
mvaddstr(5, 0, "He accepted.");
Player
.p_poison
= MAX(0.0, Player
.p_poison
- 1.0);
mvaddstr(4, 0, "You've been caught raping and pillaging!\n");
Player
.p_experience
+= 4000.0;
mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp
);
ch
= getanswer("NY", FALSE
);
mvaddstr(4, 0, "You've found a Holy Orb!\n");
if (Player
.p_poison
< 1.0)
mvaddstr(4, 0, "You've been hit with a plague!\n");
mvaddstr(4, 0, "You've found some holy water.\n");
mvaddstr(4, 0, "You've met a Guru. . .");
if (drandom() * Player
.p_sin
> 1.0)
addstr("You disgusted him with your sins!\n");
else if (Player
.p_poison
> 0.0)
addstr("He looked kindly upon you, and cured you.\n");
addstr("He rewarded you for your virtue.\n");
mvaddstr(4, 0, "You've found an amulet.\n");
mvaddstr(4, 0, "You've regained your sight!\n");
Player
.p_blindness
= FALSE
;
default: /* deal with poison */
if (Player
.p_poison
> 0.0)
temp
= Player
.p_poison
* Statptr
->c_weakness
* Player
.p_maxenergy
/ 600.0;
if (Player
.p_energy
> Player
.p_maxenergy
/ 10.0
&& temp
+ 5.0 < Player
.p_energy
)
/************************************************************************
/ FUNCTION NAME: genchar()
/ FUNCTION: generate a random character
/ AUTHOR: E. A. Estes, 12/4/85
/ int type - ASCII value of character type to generate
/ MODULES CALLED: floor(), drandom()
/ GLOBAL INPUTS: Wizard, Player, Stattable[]
/ Use the lookup table for rolling stats.
/************************************************************************/
register int subscript
; /* used for subscripting into Stattable */
register struct charstats
*statptr
;/* for pointing into Stattable */
if (subscript
< C_MAGIC
|| subscript
> C_EXPER
)
if (subscript
!= C_SUPER
|| !Wizard
)
statptr
= &Stattable
[subscript
];
ROLL(statptr
->c_quickness
.base
, statptr
->c_quickness
.interval
);
ROLL(statptr
->c_strength
.base
, statptr
->c_strength
.interval
);
ROLL(statptr
->c_mana
.base
, statptr
->c_mana
.interval
);
ROLL(statptr
->c_energy
.base
, statptr
->c_energy
.interval
);
ROLL(statptr
->c_brains
.base
, statptr
->c_brains
.interval
);
ROLL(statptr
->c_magiclvl
.base
, statptr
->c_magiclvl
.interval
);
Player
.p_type
= subscript
;
if (Player
.p_type
== C_HALFLING
)
/* give halfling some experience */
Player
.p_experience
= ROLL(600.0, 200.0);
/************************************************************************
/ FUNCTION NAME: playinit()
/ FUNCTION: initialize for playing game
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: signal(), wclear(), noecho(), crmode(), initscr(),
/ GLOBAL INPUTS: *stdscr, ill_sig()
/ GLOBAL OUTPUTS: Windows
/ Catch a bunch of signals, and turn on curses stuff.
/************************************************************************/
/* catch/ingnore signals */
sigset(SIGTRAP
, ill_sig
);
sigset(SIGSEGV
, ill_sig
);
sigset(SIGPIPE
, ill_sig
);
signal(SIGQUIT
, ill_sig
);
signal(SIGALRM
, SIG_IGN
);
signal(SIGTERM
, SIG_IGN
);
signal(SIGTSTP
, SIG_IGN
);
signal(SIGTTIN
, SIG_IGN
);
signal(SIGTTOU
, SIG_IGN
);
signal(SIGTRAP
, ill_sig
);
signal(SIGSEGV
, ill_sig
);
signal(SIGPIPE
, ill_sig
);
signal(SIGQUIT
, SIG_IGN
);
signal(SIGTERM
, SIG_IGN
);
signal(SIGALRM
, SIG_IGN
);
signal(SIGTRAP
, ill_sig
);
signal(SIGSEGV
, ill_sig
);
signal(SIGPIPE
, ill_sig
);
signal(SIGQUIT
, SIG_IGN
);
signal(SIGTERM
, SIG_IGN
);
signal(SIGALRM
, SIG_IGN
);
signal(SIGTRAP
, ill_sig
);
signal(SIGSEGV
, ill_sig
);
signal(SIGPIPE
, ill_sig
);
initscr(); /* turn on curses */
noecho(); /* do not echo input */
crmode(); /* do not process erase, kill */
Windows
= TRUE
; /* mark the state */
/************************************************************************
/ FUNCTION NAME: cleanup()
/ FUNCTION: close some files, and maybe exit
/ AUTHOR: E. A. Estes, 12/4/85
/ bool doexit - exit flag
/ MODULES CALLED: exit(), wmove(), fclose(), endwin(), nocrmode(), wrefresh()
/ GLOBAL INPUTS: *Energyvoidfp, LINES, *stdscr, Windows, *Monstfp,
/ Close all open files. If we are "in curses" terminate curses.
/ If 'doexit' is set, exit, otherwise return.
/************************************************************************/
#include <utmp.h> /* used for counting users on system */
/************************************************************************
/ FUNCTION NAME: ok_to_play()
/ FUNCTION: indicate whether playing is allowed
/ AUTHOR: E. A. Estes, 12/4/85
/ FALSE if playing is not allowed
/ TRUE if playing is allowed
/ MODULES CALLED: time(), fread(), fopen(), fclose(), localtime()
/ GLOBAL INPUTS: Wizard, Okcount
/ GLOBAL OUTPUTS: Okcount
/ This function is provided to allow one to restrict access to the game.
/ Tailor this routine as appropriate.
/ Return FALSE if playing is not allowed at this time.
/************************************************************************/
register struct tm
*tp
; /* to get time of day */
register int numusers
= 0; /* number of users on system */
FILE *fp
; /* to open files */
long now
; /* present time */
struct utmp ubuf
; /* to read 'utmp' file */
/* wizard can always play */
/* only check every 5 times */
if (((tp
->tm_hour
> 8 && tp
->tm_hour
< 12) /* 8-noon */
|| (tp
->tm_hour
> 12 && tp
->tm_hour
< 16)) /* 1-4 pm */
&& (tp
->tm_wday
!= 0 && tp
->tm_wday
!= 6)) /* not a weekend */
if ((fp
= fopen("/etc/utmp", "r")) != NULL
)
while (fread((char *) &ubuf
, sizeof(ubuf
), 1, fp
) == 1)
if (ubuf
.ut_type
== USER_PROCESS
)
if (ubuf
.ut_name
[0] != '\0')
if (numusers
> N_MAXUSERS
)