NetBSD/games/larn/main.c

1338 lines
26 KiB
C

/* $NetBSD: main.c,v 1.27 2021/05/02 12:50:45 rillig Exp $ */
/* main.c */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: main.c,v 1.27 2021/05/02 12:50:45 rillig Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
#include "extern.h"
static void showstr(void);
static void t_setup(int);
static void t_endup(int);
static void showwear(void);
static void showwield(void);
static void showread(void);
static void showeat(void);
static void showquaff(void);
static void show1(int, const char *[]);
static void randmonst(void);
static void parse(void);
static void run(int);
static void wield(void);
static void ydhi(int);
static void ycwi(int);
static void wear(void);
static void dropobj(void);
static void readscr(void);
static void eatcookie(void);
static void quaff(void);
static int whatitem(const char *);
static char copyright[] = "\nLarn is copyrighted 1986 by Noah Morgan.\n";
int srcount = 0; /* line counter for showstr() */
int dropflag = 0; /* if 1 then don't lookforobject() next round */
int rmst = 80; /* random monster creation counter */
int userid; /* the players login user id number */
gid_t gid, egid; /* used for security */
u_char nowelcome = 0, nomove = 0; /* if (nomove) then don't
* count next iteration as a
* move */
static char viewflag = 0;
/*
* if viewflag then we have done a 99 stay here and don't showcell in the
* main loop
*/
u_char restorflag = 0; /* 1 means restore has been done */
static char cmdhelp[] = "\
Cmd line format: larn [-slicnh] [-o<optsfile>] [-##] [++]\n\
-s show the scoreboard\n\
-l show the logfile (wizard id only)\n\
-i show scoreboard with inventories of dead characters\n\
-c create new scoreboard (wizard id only)\n\
-n suppress welcome message on starting game\n\
-## specify level of difficulty (example: -5)\n\
-h print this help text\n\
++ restore game from checkpoint file\n\
-o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
";
#ifdef VT100
static char *termtypes[] = {"vt100", "vt101", "vt102", "vt103", "vt125",
"vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
"vt341"};
#endif /* VT100 */
/*
************
MAIN PROGRAM
************
*/
int
main(int argc, char **argv)
{
int i;
int hard;
const char *ptr = 0;
struct passwd *pwe;
i = 0;
egid = getegid();
gid = getgid();
setegid(gid); /* give up "games" if we have it */
/*
* first task is to identify the player
*/
#ifndef VT100
init_term(); /* setup the terminal (find out what type)
* for termcap */
#endif /* VT100 */
/* try to get login name */
if (((ptr = getlogin()) == 0) || (*ptr == 0)) {
/* can we get it from /etc/passwd? */
if ((pwe = getpwuid(getuid())) != NULL)
ptr = pwe->pw_name;
else if ((ptr = getenv("USER")) == 0)
if ((ptr = getenv("LOGNAME")) == 0) {
noone: write(2, "Can't find your logname. Who Are You?\n", 39);
exit(1);
}
}
if (ptr == 0)
goto noone;
if (strlen(ptr) == 0)
goto noone;
/*
* second task is to prepare the pathnames the player will need
*/
strcpy(loginname, ptr); /* save loginname of the user for logging
* purposes */
strcpy(logname, ptr); /* this will be overwritten with the players
* name */
if ((ptr = getenv("HOME")) == NULL)
ptr = ".";
strcpy(savefilename, ptr);
strcat(savefilename, "/Larn.sav"); /* save file name in home
* directory */
snprintf(optsfile, sizeof(optsfile), "%s/.larnopts", ptr);
/* the .larnopts filename */
/*
* now malloc the memory for the dungeon
*/
cell = (struct cel *) malloc(sizeof(struct cel) * (MAXLEVEL + MAXVLEVEL) * MAXX * MAXY);
if (cell == 0)
died(-285); /* malloc failure */
lpbuf = malloc((5 * BUFBIG) >> 2); /* output buffer */
inbuffer = malloc((5 * MAXIBUF) >> 2); /* output buffer */
if ((lpbuf == 0) || (inbuffer == 0))
died(-285); /* malloc() failure */
lcreat((char *) 0);
newgame(); /* set the initial clock */
hard = -1;
#ifdef VT100
/*
* check terminal type to avoid users who have not vt100 type terminals
*/
ttype = getenv("TERM");
for (j = 1, i = 0; i < sizeof(termtypes) / sizeof(char *); i++)
if (strcmp(ttype, termtypes[i]) == 0) {
j = 0;
break;
}
if (j) {
lprcat("Sorry, Larn needs a VT100 family terminal for all its features.\n");
lflush();
exit(1);
}
#endif /* VT100 */
/*
* now make scoreboard if it is not there (don't clear)
*/
if (access(scorefile, 0) == -1) /* not there */
makeboard();
/*
* now process the command line arguments
*/
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-')
switch (argv[i][1]) {
case 's':
showscores();
exit(0); /* show scoreboard */
case 'l': /* show log file */
diedlog();
exit(0);
case 'i':
showallscores();
exit(0); /* show all scoreboard */
case 'c': /* anyone with password can create
* scoreboard */
lprcat("Preparing to initialize the scoreboard.\n");
if (getpassword() != 0) { /* make new scoreboard */
makeboard();
lprc('\n');
showscores();
}
exit(0);
case 'n': /* no welcome msg */
nowelcome = 1;
argv[i][0] = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': /* for hardness */
sscanf(&argv[i][1], "%d", &hard);
break;
case 'h': /* print out command line arguments */
write(1, cmdhelp, sizeof(cmdhelp));
exit(0);
case 'o': /* specify a .larnopts filename */
strncpy(optsfile, argv[i] + 2, 127);
break;
default:
printf("Unknown option <%s>\n", argv[i]);
exit(1);
};
if (argv[i][0] == '+') {
clear();
restorflag = 1;
if (argv[i][1] == '+') {
hitflag = 1;
restoregame(ckpfile); /* restore checkpointed
* game */
}
i = argc;
}
}
readopts(); /* read the options file if there is one */
#ifdef UIDSCORE
userid = geteuid(); /* obtain the user's effective id number */
#else /* UIDSCORE */
userid = getplid(logname); /* obtain the players id number */
#endif /* UIDSCORE */
if (userid < 0) {
write(2, "Can't obtain playerid\n", 22);
exit(1);
}
#ifdef HIDEBYLINK
/*
* this section of code causes the program to look like something else to ps
*/
if (strcmp(psname, argv[0])) { /* if a different process name only */
if ((i = access(psname, 1)) < 0) { /* link not there */
if (link(argv[0], psname) >= 0) {
argv[0] = psname;
execv(psname, argv);
}
} else
unlink(psname);
}
for (i = 1; i < argc; i++) {
szero(argv[i]); /* zero the argument to avoid ps snooping */
}
#endif /* HIDEBYLINK */
if (access(savefilename, 0) == 0) { /* restore game if need to */
clear();
restorflag = 1;
hitflag = 1;
restoregame(savefilename); /* restore last game */
}
sigsetup(); /* trap all needed signals */
sethard(hard); /* set up the desired difficulty */
setupvt100(); /* setup the terminal special mode */
if (c[HP] == 0) { /* create new game */
makeplayer(); /* make the character that will play */
newcavelevel(0);/* make the dungeon */
predostuff = 1; /* tell signals that we are in the welcome
* screen */
if (nowelcome == 0)
welcome(); /* welcome the player to the game */
}
drawscreen(); /* show the initial dungeon */
predostuff = 2; /* tell the trap functions that they must do
* a showplayer() from here on */
#if 0
nice(1); /* games should be run niced */
#endif
yrepcount = hit2flag = 0;
while (1) {
if (dropflag == 0)
lookforobject(); /* see if there is an object
* here */
else
dropflag = 0; /* don't show it just dropped an item */
if (hitflag == 0) {
if (c[HASTEMONST])
movemonst();
movemonst();
} /* move the monsters */
if (viewflag == 0)
showcell(playerx, playery);
else
viewflag = 0; /* show stuff around player */
if (hit3flag)
flushall();
hitflag = hit3flag = 0;
nomove = 1;
bot_linex(); /* update bottom line */
while (nomove) {
if (hit3flag)
flushall();
nomove = 0;
parse();
} /* get commands and make moves */
regen(); /* regenerate hp and spells */
if (c[TIMESTOP] == 0)
if (--rmst <= 0) {
rmst = 120 - (level << 2);
fillmonst(makemonst(level));
}
}
}
/*
showstr()
show character's inventory
*/
static void
showstr(void)
{
int i, number;
for (number = 3, i = 0; i < 26; i++)
if (iven[i])
number++; /* count items in inventory */
t_setup(number);
qshowstr();
t_endup(number);
}
void
qshowstr(void)
{
int i, j, k, sigsav;
srcount = 0;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
if (c[GOLD]) {
lprintf(".) %ld gold pieces", (long) c[GOLD]);
srcount++;
}
for (k = 26; k >= 0; k--)
if (iven[k]) {
for (i = 22; i < 84; i++)
for (j = 0; j <= k; j++)
if (i == iven[j])
show3(j);
k = 0;
}
lprintf("\nElapsed time is %ld. You have %ld mobuls left", (long) ((gltime + 99) / 100 + 1), (long) ((TIMELIMIT - gltime) / 100));
more();
nosignal = sigsav;
}
/*
* subroutine to clear screen depending on # lines to display
*/
static void
t_setup(int count)
{
if (count < 20) { /* how do we clear the screen? */
cl_up(79, count);
cursor(1, 1);
} else {
resetscroll();
clear();
}
}
/*
* subroutine to restore normal display screen depending on t_setup()
*/
static void
t_endup(int count)
{
if (count < 18) /* how did we clear the screen? */
draws(0, MAXX, 0, (count > MAXY) ? MAXY : count);
else {
drawscreen();
setscroll();
}
}
/*
function to show the things player is wearing only
*/
static void
showwear(void)
{
int i, j, sigsav, count;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
srcount = 0;
for (count = 2, j = 0; j <= 26; j++) /* count number of items we
* will display */
if ((i = iven[j]) != 0)
switch (i) {
case OLEATHER:
case OPLATE:
case OCHAIN:
case ORING:
case OSTUDLEATHER:
case OSPLINT:
case OPLATEARMOR:
case OSSPLATE:
case OSHIELD:
count++;
};
t_setup(count);
for (i = 22; i < 84; i++)
for (j = 0; j <= 26; j++)
if (i == iven[j])
switch (i) {
case OLEATHER:
case OPLATE:
case OCHAIN:
case ORING:
case OSTUDLEATHER:
case OSPLINT:
case OPLATEARMOR:
case OSSPLATE:
case OSHIELD:
show3(j);
};
more();
nosignal = sigsav;
t_endup(count);
}
/*
function to show the things player can wield only
*/
static void
showwield(void)
{
int i, j, sigsav, count;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
srcount = 0;
for (count = 2, j = 0; j <= 26; j++) /* count how many items */
if ((i = iven[j]) != 0)
switch (i) {
case ODIAMOND:
case ORUBY:
case OEMERALD:
case OSAPPHIRE:
case OBOOK:
case OCHEST:
case OLARNEYE:
case ONOTHEFT:
case OSPIRITSCARAB:
case OCUBEofUNDEAD:
case OPOTION:
case OSCROLL:
break;
default:
count++;
};
t_setup(count);
for (i = 22; i < 84; i++)
for (j = 0; j <= 26; j++)
if (i == iven[j])
switch (i) {
case ODIAMOND:
case ORUBY:
case OEMERALD:
case OSAPPHIRE:
case OBOOK:
case OCHEST:
case OLARNEYE:
case ONOTHEFT:
case OSPIRITSCARAB:
case OCUBEofUNDEAD:
case OPOTION:
case OSCROLL:
break;
default:
show3(j);
};
more();
nosignal = sigsav;
t_endup(count);
}
/*
* function to show the things player can read only
*/
static void
showread(void)
{
int i, j, sigsav, count;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
srcount = 0;
for (count = 2, j = 0; j <= 26; j++)
switch (iven[j]) {
case OBOOK:
case OSCROLL:
count++;
};
t_setup(count);
for (i = 22; i < 84; i++)
for (j = 0; j <= 26; j++)
if (i == iven[j])
switch (i) {
case OBOOK:
case OSCROLL:
show3(j);
};
more();
nosignal = sigsav;
t_endup(count);
}
/*
* function to show the things player can eat only
*/
static void
showeat(void)
{
int i, j, sigsav, count;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
srcount = 0;
for (count = 2, j = 0; j <= 26; j++)
switch (iven[j]) {
case OCOOKIE:
count++;
};
t_setup(count);
for (i = 22; i < 84; i++)
for (j = 0; j <= 26; j++)
if (i == iven[j])
switch (i) {
case OCOOKIE:
show3(j);
};
more();
nosignal = sigsav;
t_endup(count);
}
/*
function to show the things player can quaff only
*/
static void
showquaff(void)
{
int i, j, sigsav, count;
sigsav = nosignal;
nosignal = 1; /* don't allow ^c etc */
srcount = 0;
for (count = 2, j = 0; j <= 26; j++)
switch (iven[j]) {
case OPOTION:
count++;
};
t_setup(count);
for (i = 22; i < 84; i++)
for (j = 0; j <= 26; j++)
if (i == iven[j])
switch (i) {
case OPOTION:
show3(j);
};
more();
nosignal = sigsav;
t_endup(count);
}
static void
show1(int idx, const char *str2[])
{
lprintf("\n%c) %s", idx + 'a', objectname[iven[idx]]);
if (str2 != 0 && str2[ivenarg[idx]][0] != 0)
lprintf(" of%s", str2[ivenarg[idx]]);
}
void
show3(int indx)
{
switch (iven[indx]) {
case OPOTION:
show1(indx, potionname);
break;
case OSCROLL:
show1(indx, scrollname);
break;
case OLARNEYE:
case OBOOK:
case OSPIRITSCARAB:
case ODIAMOND:
case ORUBY:
case OCUBEofUNDEAD:
case OEMERALD:
case OCHEST:
case OCOOKIE:
case OSAPPHIRE:
case ONOTHEFT:
show1(indx, NULL);
break;
default:
lprintf("\n%c) %s", indx + 'a', objectname[iven[indx]]);
if (ivenarg[indx] > 0)
lprintf(" + %ld", (long) ivenarg[indx]);
else if (ivenarg[indx] < 0)
lprintf(" %ld", (long) ivenarg[indx]);
break;
}
if (c[WIELD] == indx)
lprcat(" (weapon in hand)");
if ((c[WEAR] == indx) || (c[SHIELD] == indx))
lprcat(" (being worn)");
if (++srcount >= 22) {
srcount = 0;
more();
clear();
}
}
/*
subroutine to randomly create monsters if needed
*/
static void
randmonst(void)
{
if (c[TIMESTOP])
return; /* don't make monsters if time is stopped */
if (--rmst <= 0) {
rmst = 120 - (level << 2);
fillmonst(makemonst(level));
}
}
/*
parse()
get and execute a command
*/
static void
parse(void)
{
int i, j, k, flag;
while (1) {
k = yylex();
switch (k) { /* get the token from the input and switch on
* it */
case 'h':
moveplayer(4);
return; /* west */
case 'H':
run(4);
return; /* west */
case 'l':
moveplayer(2);
return; /* east */
case 'L':
run(2);
return; /* east */
case 'j':
moveplayer(1);
return; /* south */
case 'J':
run(1);
return; /* south */
case 'k':
moveplayer(3);
return; /* north */
case 'K':
run(3);
return; /* north */
case 'u':
moveplayer(5);
return; /* northeast */
case 'U':
run(5);
return; /* northeast */
case 'y':
moveplayer(6);
return; /* northwest */
case 'Y':
run(6);
return; /* northwest */
case 'n':
moveplayer(7);
return; /* southeast */
case 'N':
run(7);
return; /* southeast */
case 'b':
moveplayer(8);
return; /* southwest */
case 'B':
run(8);
return; /* southwest */
case '.':
if (yrepcount)
viewflag = 1;
return; /* stay here */
case 'w':
yrepcount = 0;
wield();
return; /* wield a weapon */
case 'W':
yrepcount = 0;
wear();
return; /* wear armor */
case 'r':
yrepcount = 0;
if (c[BLINDCOUNT]) {
cursors();
lprcat("\nYou can't read anything when you're blind!");
} else if (c[TIMESTOP] == 0)
readscr();
return; /* to read a scroll */
case 'q':
yrepcount = 0;
if (c[TIMESTOP] == 0)
quaff();
return; /* quaff a potion */
case 'd':
yrepcount = 0;
if (c[TIMESTOP] == 0)
dropobj();
return; /* to drop an object */
case 'c':
yrepcount = 0;
cast();
return; /* cast a spell */
case 'i':
yrepcount = 0;
nomove = 1;
showstr();
return; /* status */
case 'e':
yrepcount = 0;
if (c[TIMESTOP] == 0)
eatcookie();
return; /* to eat a fortune cookie */
case 'D':
yrepcount = 0;
seemagic(0);
nomove = 1;
return; /* list spells and scrolls */
case '?':
yrepcount = 0;
help();
nomove = 1;
return; /* give the help screen */
case 'S':
clear();
lprcat("Saving . . .");
lflush();
savegame(savefilename);
wizard = 1;
died(-257); /* save the game - doesn't return */
__unreachable();
case 'Z':
yrepcount = 0;
if (c[LEVEL] > 9) {
oteleport(1);
return;
}
cursors();
lprcat("\nAs yet, you don't have enough experience to use teleportation");
return; /* teleport yourself */
case '^': /* identify traps */
flag = yrepcount = 0;
cursors();
lprc('\n');
for (j = playery - 1; j < playery + 2; j++) {
if (j < 0)
j = 0;
if (j >= MAXY)
break;
for (i = playerx - 1; i < playerx + 2; i++) {
if (i < 0)
i = 0;
if (i >= MAXX)
break;
switch (item[i][j]) {
case OTRAPDOOR:
case ODARTRAP:
case OTRAPARROW:
case OTELEPORTER:
lprcat("\nIt's ");
lprcat(objectname[item[i][j]]);
flag++;
};
}
}
if (flag == 0)
lprcat("\nNo traps are visible");
return;
#if WIZID
case '_': /* this is the fudge player password for
* wizard mode */
yrepcount = 0;
cursors();
nomove = 1;
if (userid != wisid) {
lprcat("Sorry, you are not empowered to be a wizard.\n");
scbr(); /* system("stty -echo cbreak"); */
lflush();
return;
}
if (getpassword() == 0) {
scbr(); /* system("stty -echo cbreak"); */
return;
}
wizard = 1;
scbr(); /* system("stty -echo cbreak"); */
for (i = 0; i < 6; i++)
c[i] = 70;
iven[0] = iven[1] = 0;
take(OPROTRING, 50);
take(OLANCE, 25);
c[WIELD] = 1;
c[LANCEDEATH] = 1;
c[WEAR] = c[SHIELD] = -1;
raiseexperience(6000000L);
c[AWARENESS] += 25000;
{
int i, j;
for (i = 0; i < MAXY; i++)
for (j = 0; j < MAXX; j++)
know[j][i] = 1;
for (i = 0; i < SPNUM; i++)
spelknow[i] = 1;
for (i = 0; i < MAXSCROLL; i++)
scrollname[i] = scrollhide[i];
for (i = 0; i < MAXPOTION; i++)
potionname[i] = potionhide[i];
}
for (i = 0; i < MAXSCROLL; i++)
if (strlen(scrollname[i]) > 2) { /* no null items */
item[i][0] = OSCROLL;
iarg[i][0] = i;
}
for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--)
if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) { /* no null items */
item[i][0] = OPOTION;
iarg[i][0] = i - MAXX + MAXPOTION;
}
for (i = 1; i < MAXY; i++) {
item[0][i] = i;
iarg[0][i] = 0;
}
for (i = MAXY; i < MAXY + MAXX; i++) {
item[i - MAXY][MAXY - 1] = i;
iarg[i - MAXY][MAXY - 1] = 0;
}
for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) {
item[MAXX - 1][i - MAXX - MAXY] = i;
iarg[MAXX - 1][i - MAXX - MAXY] = 0;
}
c[GOLD] += 25000;
drawscreen();
return;
#endif
case 'T':
yrepcount = 0;
cursors();
if (c[SHIELD] != -1) {
c[SHIELD] = -1;
lprcat("\nYour shield is off");
bottomline();
} else if (c[WEAR] != -1) {
c[WEAR] = -1;
lprcat("\nYour armor is off");
bottomline();
} else
lprcat("\nYou aren't wearing anything");
return;
case 'g':
cursors();
lprintf("\nThe stuff you are carrying presently weighs %ld pounds", (long) packweight());
/* FALLTHROUGH */
case ' ':
yrepcount = 0;
nomove = 1;
return;
case 'v':
yrepcount = 0;
cursors();
lprintf("\nCaverns of Larn, Version %ld.%ld, Diff=%ld",
(long) VERSION, (long) SUBVERSION,
(long) c[HARDGAME]);
if (wizard)
lprcat(" Wizard");
nomove = 1;
if (cheat)
lprcat(" Cheater");
lprcat(copyright);
return;
case 'Q':
yrepcount = 0;
quit();
nomove = 1;
return; /* quit */
case 'L' - 64:
yrepcount = 0;
drawscreen();
nomove = 1;
return; /* look */
#if WIZID
#ifdef EXTRA
case 'A':
yrepcount = 0;
nomove = 1;
if (wizard) {
diag();
return;
} /* create diagnostic file */
return;
#endif
#endif
case 'P':
cursors();
if (outstanding_taxes > 0)
lprintf("\nYou presently owe %ld gp in taxes.",
(long) outstanding_taxes);
else
lprcat("\nYou do not owe any taxes.");
return;
};
}
}
void
parse2(void)
{
if (c[HASTEMONST])
movemonst();
movemonst(); /* move the monsters */
randmonst();
regen();
}
static void
run(int dir)
{
int i;
i = 1;
while (i) {
i = moveplayer(dir);
if (i > 0) {
if (c[HASTEMONST])
movemonst();
movemonst();
randmonst();
regen();
}
if (hitflag)
i = 0;
if (i != 0)
showcell(playerx, playery);
}
}
/*
function to wield a weapon
*/
static void
wield(void)
{
int i;
while (1) {
if ((i = whatitem("wield")) == '\33')
return;
if (i != '.') {
if (i == '*')
showwield();
else if (iven[i - 'a'] == 0) {
ydhi(i);
return;
} else if (iven[i - 'a'] == OPOTION) {
ycwi(i);
return;
} else if (iven[i - 'a'] == OSCROLL) {
ycwi(i);
return;
} else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) {
lprcat("\nBut one arm is busy with your shield!");
return;
} else {
c[WIELD] = i - 'a';
if (iven[i - 'a'] == OLANCE)
c[LANCEDEATH] = 1;
else
c[LANCEDEATH] = 0;
bottomline();
return;
}
}
}
}
/*
common routine to say you don't have an item
*/
static void
ydhi(int x)
{
cursors();
lprintf("\nYou don't have item %c!", x);
}
static void
ycwi(int x)
{
cursors();
lprintf("\nYou can't wield item %c!", x);
}
/*
function to wear armor
*/
static void
wear(void)
{
int i;
while (1) {
if ((i = whatitem("wear")) == '\33')
return;
if (i != '.') {
if (i == '*')
showwear();
else
switch (iven[i - 'a']) {
case 0:
ydhi(i);
return;
case OLEATHER:
case OCHAIN:
case OPLATE:
case OSTUDLEATHER:
case ORING:
case OSPLINT:
case OPLATEARMOR:
case OSSPLATE:
if (c[WEAR] != -1) {
lprcat("\nYou're already wearing some armor");
return;
}
c[WEAR] = i - 'a';
bottomline();
return;
case OSHIELD:
if (c[SHIELD] != -1) {
lprcat("\nYou are already wearing a shield");
return;
}
if (iven[c[WIELD]] == O2SWORD) {
lprcat("\nYour hands are busy with the two handed sword!");
return;
}
c[SHIELD] = i - 'a';
bottomline();
return;
default:
lprcat("\nYou can't wear that!");
};
}
}
}
/*
function to drop an object
*/
static void
dropobj(void)
{
int i;
unsigned char *p;
long amt;
p = &item[playerx][playery];
while (1) {
if ((i = whatitem("drop")) == '\33')
return;
if (i == '*')
showstr();
else {
if (i == '.') { /* drop some gold */
if (*p) {
lprcat("\nThere's something here already!");
return;
}
lprcat("\n\n");
cl_dn(1, 23);
lprcat("How much gold do you drop? ");
if ((amt = readnum((long) c[GOLD])) == 0)
return;
if (amt > c[GOLD]) {
lprcat("\nYou don't have that much!");
return;
}
if (amt <= 32767) {
*p = OGOLDPILE;
i = amt;
} else if (amt <= 327670L) {
*p = ODGOLD;
i = amt / 10;
amt = 10 * i;
} else if (amt <= 3276700L) {
*p = OMAXGOLD;
i = amt / 100;
amt = 100 * i;
} else if (amt <= 32767000L) {
*p = OKGOLD;
i = amt / 1000;
amt = 1000 * i;
} else {
*p = OKGOLD;
i = 32767;
amt = 32767000L;
}
c[GOLD] -= amt;
lprintf("You drop %ld gold pieces", (long)amt);
iarg[playerx][playery] = i;
bottomgold();
know[playerx][playery] = 0;
dropflag = 1;
return;
}
drop_object(i - 'a');
return;
}
}
}
/*
* readscr() Subroutine to read a scroll one is carrying
*/
static void
readscr(void)
{
int i;
while (1) {
if ((i = whatitem("read")) == '\33')
return;
if (i != '.') {
if (i == '*')
showread();
else {
if (iven[i - 'a'] == OSCROLL) {
read_scroll(ivenarg[i - 'a']);
iven[i - 'a'] = 0;
return;
}
if (iven[i - 'a'] == OBOOK) {
readbook(ivenarg[i - 'a']);
iven[i - 'a'] = 0;
return;
}
if (iven[i - 'a'] == 0) {
ydhi(i);
return;
}
lprcat("\nThere's nothing on it to read");
return;
}
}
}
}
/*
* subroutine to eat a cookie one is carrying
*/
static void
eatcookie(void)
{
const char *p;
int i;
while (1) {
if ((i = whatitem("eat")) == '\33')
return;
if (i != '.') {
if (i == '*')
showeat();
else {
if (iven[i - 'a'] == OCOOKIE) {
lprcat("\nThe cookie was delicious.");
iven[i - 'a'] = 0;
if (!c[BLINDCOUNT]) {
if ((p = fortune()) != NULL) {
lprcat(" Inside you find a scrap of paper that says:\n");
lprcat(p);
}
}
return;
}
if (iven[i - 'a'] == 0) {
ydhi(i);
return;
}
lprcat("\nYou can't eat that!");
return;
}
}
}
}
/*
* subroutine to quaff a potion one is carrying
*/
static void
quaff(void)
{
int i;
while (1) {
if ((i = whatitem("quaff")) == '\33')
return;
if (i != '.') {
if (i == '*')
showquaff();
else {
if (iven[i - 'a'] == OPOTION) {
quaffpotion(ivenarg[i - 'a']);
iven[i - 'a'] = 0;
return;
}
if (iven[i - 'a'] == 0) {
ydhi(i);
return;
}
lprcat("\nYou wouldn't want to quaff that, would you? ");
return;
}
}
}
}
/*
function to ask what player wants to do
*/
static int
whatitem(const char *str)
{
int i;
cursors();
lprintf("\nWhat do you want to %s [* for all] ? ", str);
i = 0;
while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.'))
i = ttgetch();
if (i == '\33')
lprcat(" aborted");
return (i);
}
/*
subroutine to get a number from the player
and allow * to mean return amt, else return the number entered
*/
unsigned long
readnum(long mx)
{
int i;
unsigned long amt = 0;
sncbr();
if ((i = ttgetch()) == '*')
amt = mx; /* allow him to say * for all gold */
else
while (i != '\n') {
if (i == '\033') {
scbr();
lprcat(" aborted");
return (0);
}
if ((i <= '9') && (i >= '0') && (amt < 99999999))
amt = amt * 10 + i - '0';
i = ttgetch();
}
scbr();
return (amt);
}
#ifdef HIDEBYLINK
/*
* routine to zero every byte in a string
*/
void
szero(str)
char *str;
{
while (*str)
*str++ = 0;
}
#endif /* HIDEBYLINK */