omega-rpg/command3.c

1122 lines
30 KiB
C

/* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
/* command3.c */
/* This file contains some more top level command functions
called from command1.c */
#ifndef MSDOS_SUPPORTED_ANTIQUE
#include <pwd.h>
#include <unistd.h>
#endif
#include "glob.h"
/* look at some spot */
void examine(void)
{
pol ol;
int x=Player.x,y=Player.y,drewmenu=FALSE;
clearmsg();
/* WDT HACK: I'm not sure I buy that one shouldn't be able to examine
* when one is blind. However, the 'right' way to do it is certainly
* too difficult (I would expect to be able to examine only the items
* I actually recall). So, for now I'll use David Given's compromise.
* 12/30/98
*/
if (Player.status[BLINDED] > 0)
{
mprint("You're blind - you can't examine things.");
return;
}
setgamestatus(SKIP_MONSTERS);
mprint("Examine --");
setspot(&x,&y);
if (inbounds(x,y)) {
clearmsg();
if (Current_Environment == E_COUNTRYSIDE) {
if (! c_statusp(x, y, SEEN))
print3("How should I know what that is?");
else {
mprint("That terrain is:");
mprint(countryid(Country[x][y].current_terrain_type));
}
}
else if (! view_los_p(Player.x,Player.y,x,y))
print3("I refuse to examine something I can't see.");
else {
clearmsg();
if (Level->site[x][y].creature != NULL)
mprint(mstatus_string(Level->site[x][y].creature));
else if ((Player.x == x) && (Player.y ==y))
describe_player();
if (loc_statusp(x,y,SECRET))
print2("An age-worn stone wall.");
else
switch (Level->site[x][y].locchar) {
case SPACE: print2("An infinite void."); break;
case PORTCULLIS: print2("A heavy steel portcullis"); break;
case ABYSS: print2("An entrance to the infinite abyss"); break;
case FLOOR:
if (Current_Dungeon == Current_Environment)
print2("A dirty stone floor.");
else print2("The ground.");
break;
case WALL:
if (Level->site[x][y].aux == 0)
print2("A totally impervious wall.");
else if (Level->site[x][y].aux < 10)
print2("A pitted concrete wall.");
else if (Level->site[x][y].aux < 30)
print2("An age-worn sandstone wall.");
else if (Level->site[x][y].aux < 50)
print2("A smooth basalt wall.");
else if (Level->site[x][y].aux < 70)
print2("A solid granite wall.");
else if (Level->site[x][y].aux < 90)
print2("A wall of steel.");
else if (Level->site[x][y].aux < 210) {
if (Current_Environment == E_CITY)
print2("A thick wall of Rampart bluestone");
else print2("A magically reinforced wall.");
}
else print2("An almost totally impervious wall.");
break;
case RUBBLE:print2("A dangerous-looking pile of rubble."); break;
case SAFE:print2("A steel safe inset into the floor."); break;
case CLOSED_DOOR:print2("A solid oaken door, now closed."); break;
case OPEN_DOOR:print2("A solid oaken door, now open."); break;
case STATUE:print2("A strange-looking statue."); break;
case STAIRS_UP:print2("A stairway leading up."); break;
case STAIRS_DOWN:print2("A stairway leading down...."); break;
case TRAP:print2(trapid(Level->site[x][y].p_locf)); break;
case HEDGE:
if (Level->site[x][y].p_locf == L_EARTH_STATION)
print2("A weird fibrillation of oozing tendrils.");
else print2("A brambly, thorny hedge.");
break;
case LAVA:print2("A bubbling pool of lava."); break;
case LIFT:print2("A strange glowing disk."); break;
case ALTAR:print2("An (un?)holy altar."); break;
case CHAIR:print2("A chair."); break;
case WHIRLWIND:print2("A strange cyclonic electrical storm."); break;
case WATER:
if (Level->site[x][y].p_locf == L_WATER)
print2("A deep pool of water.");
else if (Level->site[x][y].p_locf == L_CHAOS)
print2("A pool of primal chaos.");
else if (Level->site[x][y].p_locf == L_WATER_STATION)
print2("A bubbling pool of acid.");
else print2("An eerie pool of water.");
break;
case FIRE:print2("A curtain of fire."); break;
default:print2("Wow, I haven't the faintest idea!"); break;
}
if ((ol = Level->site[x][y].things) != NULL && !loc_statusp(x,y,SECRET)) {
if (ol->next == NULL)
print3(itemid(ol->thing));
else {
drewmenu = TRUE;
menuclear();
menuprint("Things on floor:\n");
while (ol != NULL) {
menuprint("\n");
menuprint(itemid(ol->thing));
ol = ol->next;
}
showmenu();
}
}
morewait();
sign_print(x,y,TRUE);
}
}
if (drewmenu) xredraw();
}
void help(void)
{
char c;
char filestr[80];
FILE *in, *out;
int n;
clearmsg();
print1("Please enter the letter indicating what topic you want help on.");
menuclear();
menuprint("a: Overview\n");
menuprint("b: Characters\n");
menuprint("c: Inventories\n");
menuprint("d: Movement\n");
menuprint("e: Combat\n");
menuprint("f: Bugs\n");
menuprint("g: Magic\n");
menuprint("h: The Countryside\n");
menuprint("i: The Screen Display\n");
menuprint("j: Saving and Restoring\n");
menuprint("k: Options Settings\n");
menuprint("l: Dungeon/City/Other Command List\n");
menuprint("m: Countryside Command List\n");
#if !defined(MSDOS) && !defined(AMIGA)
menuprint("n: Everything\n");
#endif
menuprint("ESCAPE: Forget the whole thing.");
showmenu();
do
c = (char) mcigetc();
#if defined(MSDOS) || defined(AMIGA)
while ((c < 'a' || c > 'm') && c != ESCAPE);
if (c != ESCAPE) {
sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
displayfile(filestr);
}
#else
while ((c < 'a' || c > 'n') && c != ESCAPE);
if (c == 'n') {
if (cinema_confirm("I'm about to copy all help files into 'omega.doc'.")=='y') {
change_to_user_perms();
out = checkfopen("omega.doc", "w");
print2("Copying");
for (n = 1; n <= 13; n++)
{
nprint2(".");
sprintf(Str1, "%shelp%d.txt", Omegalib, n);
in = checkfopen(Str1, "r");
while (fgets(Str1, STRING_LEN, in))
fputs(Str1, out);
fclose(in);
}
fclose(out);
change_to_game_perms();
nprint2(" Done.");
}
}
else if (c != ESCAPE) {
sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
print1("Display help file, or Copy help file to file in wd. [dc] ");
do
c = (char) mcigetc();
while ((c != 'd') && (c != 'c')&& (c!=ESCAPE));
if (c == 'd')
displayfile(filestr);
else if (c == 'c') copyfile(filestr);
}
#endif
xredraw();
}
extern const char * LAST_OMEGA_BUILD_TIME;
void version(void)
{
setgamestatus(SKIP_MONSTERS);
print3(VERSIONSTRING);
nprint3(":");
nprint3(" build date: ");
nprint3((char *)LAST_OMEGA_BUILD_TIME);
}
void fire(void)
{
int index,x1,y1,x2,y2;
pob obj;
struct monster *m;
clearmsg();
print1("Fire/Throw --");
index = getitem(NULL_ITEM);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else if (index == CASHVALUE) print3("Can't fire money at something!");
else if (cursed(Player.possessions[index]) &&
Player.possessions[index]->used)
print3("You can't seem to get rid of it!");
/* load a crossbow */
else if ((Player.possessions[O_WEAPON_HAND] != NULL) &&
(Player.possessions[O_WEAPON_HAND]->id == OB_CROSSBOW) &&
(Player.possessions[O_WEAPON_HAND]->aux != LOADED) &&
(Player.possessions[index]->id == OB_BOLT)) {
/* WDT: how much time? */
mprint("You crank back the crossbow and load a bolt.");
Player.possessions[O_WEAPON_HAND]->aux = LOADED;
}
else {
if (Player.possessions[index]->used) {
Player.possessions[index]->used = FALSE;
item_use(Player.possessions[index]);
}
obj = Player.possessions[index];
x1 = x2 = Player.x;
y1 = y2 = Player.y;
setspot(&x2,&y2);
if ((x2 == Player.x) && (y2 == Player.y))
mprint("You practice juggling for a moment or two.");
else {
do_object_los(obj->objchar,&x1,&y1,x2,y2);
if ((m=Level->site[x1][y1].creature) != NULL) {
if (obj->dmg == 0) {
if (m->treasure > 0) { /* the monster can have treasure/objects */
mprint("Your gift is caught!");
givemonster(m,split_item(1,obj));
conform_lost_objects(1,obj);
}
else {
mprint("Your thrown offering is ignored.");
setgamestatus(SUPPRESS_PRINTING);
p_drop_at(x1,y1,1,obj);
resetgamestatus(SUPPRESS_PRINTING);
conform_lost_objects(1,obj);
}
}
else if (obj->aux == I_SCYTHE) {
mprint("It isn't very aerodynamic... you miss.");
setgamestatus(SUPPRESS_PRINTING);
p_drop_at(x1,y1,1,obj);
resetgamestatus(SUPPRESS_PRINTING);
conform_lost_objects(1,obj);
}
else if (hitp(Player.hit,m->ac)) {/* ok already, hit the damn thing */
weapon_use(2*statmod(Player.str),obj,m);
if ((obj->id == OB_ARROW || obj->id == OB_BOLT) &&
!random_range(4))
dispose_lost_objects(1,obj);
else {
setgamestatus(SUPPRESS_PRINTING);
p_drop_at(x1,y1,1,obj);
resetgamestatus(SUPPRESS_PRINTING);
conform_lost_objects(1,obj);
}
}
else {
mprint("You miss it.");
setgamestatus(SUPPRESS_PRINTING);
p_drop_at(x1,y1,1,obj);
resetgamestatus(SUPPRESS_PRINTING);
conform_lost_objects(1,obj);
}
}
else {
setgamestatus(SUPPRESS_PRINTING);
p_drop_at(x1,y1,1,obj);
resetgamestatus(SUPPRESS_PRINTING);
conform_lost_objects(1,obj);
plotspot(x1,y1,TRUE);
}
}
}
}
/* WDT: This function is used in interrupt handling, so it has the potential
* to mess up the display. Perhaps I should have a Curses window just for it,
* so that I could clean up nicely if the user answers 'no' to its question.
*/
void quit(void)
{
clearmsg();
change_to_game_perms();
mprint("Quit: Are you sure? [yn] ");
if (ynq()=='y') {
if (Player.rank[ADEPT] == 0) display_quit();
else display_bigwin();
#ifdef SAVE_LEVELS
kill_all_levels();
#endif
endgraf();
printf("Bye!\n");
exit(0);
}
else resetgamestatus(SKIP_MONSTERS);
}
/* rest in 10 second segments so if woken up by monster won't
die automatically.... */
void nap(void)
{
static int naptime;
if (gamestatusp(FAST_MOVE)) {
if (naptime-- < 1) {
clearmsg();
mprint("Yawn. You wake up.");
resetgamestatus(FAST_MOVE);
drawvision(Player.x,Player.y);
}
}
else {
clearmsg();
naptime = (int) parsenum("Rest for how long? (in minutes) ");
if (naptime > 600) {
print3("You can only sleep up to 10 hours (600 minutes)");
naptime = 3600;
}
else naptime *= 6;
if (naptime > 1) {
clearmsg();
setgamestatus(FAST_MOVE);
mprint("Resting.... ");
}
}
}
void charid(void)
{
char id;
int countryside=FALSE;
char cstr[80];
clearmsg();
mprint("Character to identify: ");
id = mgetc();
if (Current_Environment == E_COUNTRYSIDE) {
countryside = TRUE;
strcpy(cstr,countryid(id));
if (strcmp(cstr,"I have no idea.")==0)
countryside = FALSE;
else mprint(cstr);
}
if (! countryside) {
if ((id >= 'a' && id <= 'z') || (id >= 'A' && id <= 'Z') || id == '@')
mprint("A monster or NPC -- examine (x) to find out exactly.");
else switch(id) {
case (SPACE&0xff):
mprint(" : An airless void (if seen) or unknown region (if unseen)");
break;
case (WALL&0xff):
mprint(" : An (impenetrable?) wall");
break;
case (OPEN_DOOR&0xff):
mprint(" : An open door");
break;
case (CLOSED_DOOR&0xff):
mprint(" : A closed (possibly locked) door");
break;
case (LAVA&0xff):
mprint(" : A pool of lava");
break;
case (HEDGE&0xff):
mprint(" : A dense hedge");
break;
case (WATER&0xff):
mprint(" : A deep body of water");
break;
case (FIRE&0xff):
mprint(" : A curtain of fire");
break;
case (TRAP&0xff):
mprint(" : An uncovered trap");
break;
case (STAIRS_UP&0xff):
mprint(" : A stairway leading up");
break;
case (STAIRS_DOWN&0xff):
mprint(" : A stairway leading down");
break;
case (FLOOR&0xff):
mprint(" : The dungeon floor");
break;
case (PORTCULLIS&0xff):
mprint(" : A heavy steel portcullis");
break;
case (ABYSS&0xff):
mprint(" : An entrance to the infinite abyss");
break;
case (PLAYER&0xff):
mprint(" : You, the player");
break;
case (CORPSE&0xff):
mprint(" : The remains of some creature");
break;
case (THING&0xff):
mprint(" : Some random miscellaneous object");
break;
case (SAFE&0xff):
mprint(" : A steel safe inset into the floor");
break;
case (RUBBLE&0xff):
mprint(" : A dangerous-looking pile of rubble");
break;
case (STATUE&0xff):
mprint(" : A statue");
break;
case (ALTAR&0xff):
mprint(" : A (un?)holy altar");
break;
case (CASH&0xff):
mprint(" : Bills, specie, gems: cash");
break;
case (PILE&0xff):
mprint(" : A pile of objects");
break;
case (FOOD&0xff):
mprint(" : Something edible");
break;
case (WEAPON&0xff):
mprint(" : Some kind of weapon");
break;
case (MISSILEWEAPON&0xff):
mprint(" : Some kind of missile weapon");
break;
case (SCROLL&0xff):
mprint(" : Something readable");
break;
case (POTION&0xff):
mprint(" : Something drinkable");
break;
case (ARMOR&0xff):
mprint(" : A suit of armor");
break;
case (SHIELD&0xff):
mprint(" : A shield");
break;
case (CLOAK&0xff):
mprint(" : A cloak");
break;
case (BOOTS&0xff):
mprint(" : A pair of boots");
break;
case (STICK&0xff):
mprint(" : A stick");
break;
case (RING&0xff):
mprint(" : A ring");
break;
case (ARTIFACT&0xff):
mprint(" : An artifact");
break;
case (CHAIR&0xff):
mprint(" : A chair");
break;
case (WHIRLWIND&0xff):
mprint(" : A whirlwind");
break;
default:
mprint("That character is unused.");
break;
}
}
}
void wizard(void)
{
char *lname;
#ifndef MSDOS_SUPPORTED_ANTIQUE
struct passwd *dastuff;
#endif
setgamestatus(SKIP_MONSTERS);
if (gamestatusp(CHEATED)) mprint("You're already in wizard mode!");
else {
clearmsg();
if (cinema_confirm("You just asked to enter wizard mode.")=='y') {
lname = getlogin();
#ifndef MSDOS_SUPPORTED_ANTIQUE
if (!lname || strlen(lname) == 0)
{
dastuff = getpwuid(getuid());
lname = dastuff->pw_name;
}
#endif
if (strcmp(lname,WIZARD)==0) {
setgamestatus(CHEATED);
mprint("Wizard mode set.");
}
else {
mprint("There is a shrieking sound, as of reality being distorted.");
strcpy(Str1,WIZARD);
strcat(Str1,", the Wizard of Omega appears before you....");
if (Str1[0] >= 'a' && Str1[0] <= 'z')
Str1[0] += 'A'-'a'; /* capitalise 1st letter */
mprint(Str1);
mprint("'Do not meddle in the affairs of Wizards --");
if (random_range(2)) mprint("it makes them soggy and hard to light.'");
else mprint("for they are subtle, and swift to anger!'");
}
}
}
}
/* Jump, that is */
void vault(void)
{
int x=Player.x,y=Player.y,jumper=0;
clearmsg();
if (Player.possessions[O_BOOTS] != NULL)
if (Player.possessions[O_BOOTS]->usef == I_BOOTS_JUMPING)
jumper = 2;
if (Player.status[IMMOBILE] > 0) {
resetgamestatus(FAST_MOVE);
print3("You are unable to move");
}
else {
setgamestatus(SKIP_MONSTERS);
mprint("Jump where?");
setspot(&x,&y);
if (! los_p(Player.x,Player.y,x,y))
print3("The way is obstructed.");
else if (Player.itemweight > Player.maxweight)
print3("You are too burdened to jump anywhere.");
else if (distance(x,y,Player.x,Player.y) >
max(2,statmod(Player.agi)+2)+jumper)
print3("The jump is too far for you.");
else if (Level->site[x][y].creature != NULL)
print3("You can't jump on another creature.");
else if (! p_moveable(x,y))
print3("You can't jump there.");
else {
resetgamestatus(SKIP_MONSTERS);
Player.x = x;
Player.y = y;
if ((! jumper) && (random_range(30) > Player.agi)) {
mprint("Oops -- took a tumble.");
setgamestatus(SKIP_PLAYER);
p_damage((Player.itemweight/250),UNSTOPPABLE,"clumsiness");
}
p_movefunction(Level->site[Player.x][Player.y].p_locf);
if (Current_Environment != E_COUNTRYSIDE)
if ((Level->site[Player.x][Player.y].things != NULL) &&
(optionp(PICKUP)))
pickup();
}
}
}
/* Sets sequence of combat maneuvers. */
void tacoptions(void)
{
int actionsleft,done,place;
char defatt, *attstr, *defstr; /* for the default setting */
int draw_again = 1;
setgamestatus(SKIP_MONSTERS);
done = FALSE;
actionsleft = maneuvers();
place = 0;
do {
if (draw_again) {
menuclear();
menuprint("Enter a combat maneuvers sequence.\n");
menuprint("? for help, ! for default, backspace to start again,\n");
menuprint(" RETURN to save sequence\n");
showmenu();
draw_again = 0;
}
clearmsg();
mprint("Maneuvers Left:");
mnumprint(actionsleft);
switch(mgetc()) {
case '?':
combat_help();
draw_again = 1;
break;
case 'a': case 'A':
if (actionsleft < 1) print3("No more maneuvers!");
else {
if (Player.possessions[O_WEAPON_HAND] == NULL) {
Player.meleestr[place] = 'C';
menuprint("\nPunch:");
}
else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
Player.meleestr[place] = 'T';
menuprint("\nThrust:");
}
else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
Player.meleestr[place] = 'C';
menuprint("\nStrike:");
}
else {
menuprint("\nCut:");
Player.meleestr[place] = 'C';
}
place++;
Player.meleestr[place]=getlocation();
place++;
actionsleft--;
}
break;
case 'b': case 'B':
if (actionsleft<1) print3("No more maneuvers!");
else {
Player.meleestr[place] = 'B';
if (Player.possessions[O_WEAPON_HAND] == NULL)
menuprint("\nDodge (from):");
else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING)
menuprint("\nParry:");
else menuprint("\nBlock:");
place++;
Player.meleestr[place]= getlocation();
place++;
actionsleft--;
}
break;
case 'l': case 'L':
if (actionsleft<2) print3("Not enough maneuvers to lunge!");
else {
if (Player.possessions[O_WEAPON_HAND] != NULL) {
if (Player.possessions[O_WEAPON_HAND]->type != MISSILE) {
menuprint("\nLunge:");
Player.meleestr[place] = 'L';
place++;
Player.meleestr[place]=getlocation();
place++;
actionsleft -= 2;
}
else {
print3("Can't lunge with a missile weapon!");
morewait();
}
}
else {
print3("Can't lunge without a weapon!");
morewait();
}
}
break;
case 'r': case 'R':
if (actionsleft<2) print3("Not enough maneuvers to riposte!");
else {
if (Player.possessions[O_WEAPON_HAND] != NULL) {
if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
Player.meleestr[place++] = 'R';
menuprint("\nRiposte:");
Player.meleestr[place++]=getlocation();
actionsleft -= 2;
}
else {
print3("Can't riposte without a thrusting weapon!");
morewait();
}
}
else {
print3("Can't riposte without a thrusting weapon!");
morewait();
}
}
break;
case BACKSPACE:
case DELETE:
place = 0;
actionsleft=maneuvers();
draw_again = 1;
break;
case '!':
if (Player.possessions[O_WEAPON_HAND] == NULL) {
defatt = 'C';
attstr = "Punch";
}
else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
defatt = 'T';
attstr = "Thrust";
}
else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
defatt = 'C';
attstr = "Strike";
}
else {
defatt = 'C';
attstr = "Cut";
}
if (Player.possessions[O_WEAPON_HAND] == NULL)
defstr = "Dodge";
else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING)
defstr = "Parry";
else defstr = "Block";
menuclear();
menuprint("Enter a combat maneuvers sequence.\n");
menuprint("? for help, ! for default, backspace to start again,\n");
menuprint(" RETURN to save sequence\n\n");
for(place=0;place<maneuvers();place++)
if (place&1) { /* every 2nd time around */
Player.meleestr[place*2] = 'B';
Player.meleestr[(place*2)+1] = 'C';
menuprint(defstr);
menuprint(" Center.\n");
}
else {
Player.meleestr[place*2] = defatt;
Player.meleestr[(place*2)+1] = 'C';
menuprint(attstr);
menuprint(" Center.\n");
}
actionsleft = 0;
showmenu();
Player.meleestr[place*2]='\0';
break;
case RETURN:
case LINEFEED:
case ESCAPE:
done = TRUE;
break;
}
/* if (actionsleft < 1) morewait(); */ /* FIXED 12/30/98 */
} while (! done);
xredraw();
Player.meleestr[place] = 0;
}
/* Do the Artful Dodger trick */
void pickpocket(void)
{
int dx,dy,index=0;
struct monster *m;
clearmsg();
mprint("Pickpocketing --");
index = getdir();
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
dx = Dirs[0][index];
dy = Dirs[1][index];
if ((! inbounds(Player.x+dx, Player.y+dy)) ||
(Level->site[Player.x+dx][Player.y+dy].creature == NULL)) {
print3("There's nothing there to steal from!!!");
setgamestatus(SKIP_MONSTERS);
}
else {
m = Level->site[Player.x+dx][Player.y+dy].creature;
if (m->id == GUARD) {
mprint("Trying to steal from a guardsman, eh?");
mprint("Not a clever idea.");
if (Player.cash > 0) {
mprint("As a punitive fine, the guard takes all your money.");
{
pob o = detach_money(Player.cash);
m_pickup(m,o);
}
dataprint();
}
else {
mprint("The guardsman places you under arrest.");
morewait();
send_to_jail();
}
}
else if (m->possessions == NULL) {
mprint("You couldn't find anything worth taking!");
mprint("But you managed to annoy it...");
m_status_set(m,HOSTILE);
}
else
{
/* DAG -- code and idea contributed by Ross Presser <ross_presser@imtek.com> */
int i,j,k;
i = Player.dex*5+Player.rank[THIEVES]*20+random_range(100);
j = random_range(100)+m->level*20;
k = random_range(j);
if (i>j) {
mprint("You successfully complete your crime!");
mprint("You stole:");
mprint(itemid(m->possessions->thing));
Player.alignment--;
gain_experience(m->level*m->level);
gain_item(m->possessions->thing);
m->possessions = m->possessions->next;
}
else if (i<k) {
mprint("No luck ... yet.");
}
else {
mprint("You were unsucessful at your crime.");
mprint("Even worse, you managed to annoy it...");
m_status_set(m,HOSTILE);
}
}
}
}
}
void rename_player(void)
{
setgamestatus(SKIP_MONSTERS);
clearmsg();
mprint("Rename Character: ");
strcpy(Str1,msgscanstring());
if (strlen(Str1) == 0)
mprint(Player.name);
else {
if (Str1[0] >= 'a' && Str1[0] <= 'z')
Str1[0] += 'A' - 'a';
strcpy(Player.name, Str1);
}
sprintf(Str1, "Henceforth, you shall be known as %s", Player.name);
print2(Str1);
}
void abortshadowform(void)
{
setgamestatus(SKIP_MONSTERS);
if (Player.status[SHADOWFORM] && (Player.status[SHADOWFORM]<1000)) {
mprint("You abort your spell of Shadow Form.");
Player.immunity[NORMAL_DAMAGE]--;
Player.immunity[ACID]--;
Player.immunity[THEFT]--;
Player.immunity[INFECTION]--;
mprint("You feel less shadowy now.");
Player.status[SHADOWFORM] = 0;
}
}
void tunnel(void)
{
int dir,ox,oy,aux;
clearmsg();
mprint("Tunnel -- ");
dir = getdir();
if (dir == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
ox = Player.x + Dirs[0][dir];
oy = Player.y + Dirs[1][dir];
if (loc_statusp(ox,oy,SECRET))
mprint("You have no success as yet.");
else if (Level->site[ox][oy].locchar != WALL) {
print3("You can't tunnel through that!");
setgamestatus(SKIP_MONSTERS);
}
else {
aux = Level->site[ox][oy].aux;
if (random_range(20)==1){
if (Player.possessions[O_WEAPON_HAND] == NULL) {
mprint("Ouch! broke a fingernail...");
p_damage(Player.str / 6,UNSTOPPABLE,"a broken fingernail");
}
else if ((Player.possessions[O_WEAPON_HAND]->type == THRUSTING) ||
((Player.possessions[O_WEAPON_HAND]->type != STRIKING) &&
(Player.possessions[O_WEAPON_HAND]->fragility <
random_range(20)))) {
mprint("Clang! Uh oh...");
(void) damage_item(Player.possessions[O_WEAPON_HAND]);
}
else mprint("Your digging implement shows no sign of breaking.");
}
if (Player.possessions[O_WEAPON_HAND] == NULL) {
if ((aux > 0) && ((Player.str/3)+random_range(100) > aux)) {
mprint("You carve a tunnel through the stone!");
tunnelcheck();
Level->site[ox][oy].locchar = RUBBLE;
Level->site[ox][oy].p_locf = L_RUBBLE;
lset(ox, oy, CHANGED);
}
else mprint("No joy.");
}
else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
if ((aux > 0) &&
(Player.possessions[O_WEAPON_HAND]->dmg*2+random_range(100) >
aux)) {
mprint("You carve a tunnel through the stone!");
tunnelcheck();
Level->site[ox][oy].locchar = RUBBLE;
Level->site[ox][oy].p_locf = L_RUBBLE;
lset(ox, oy, CHANGED);
}
else mprint("No luck.");
}
else if ((aux > 0) &&
(Player.possessions[O_WEAPON_HAND]->dmg+random_range(100)
> aux)) {
mprint("You carve a tunnel through the stone!");
tunnelcheck();
Level->site[ox][oy].locchar = RUBBLE;
Level->site[ox][oy].p_locf = L_RUBBLE;
lset(ox, oy, CHANGED);
}
else mprint("You have no success as yet.");
}
}
}
void hunt(Symbol terrain)
{
int fertility=0;
switch(terrain) {
case SWAMP:
mprint("You hesitate to hunt for food in the marshy wasteland.");
break;
case VOLCANO:
case CASTLE:
case TEMPLE:
case CAVES:
case STARPEAK:
case MAGIC_ISLE:
case DRAGONLAIR:
mprint("There is nothing alive here (or so it seems)");
break;
case VILLAGE:
case CITY:
mprint("You can find no food here; perhaps if you went inside....");
break;
case ROAD:
mprint("You feel it would be a better idea to hunt off the road.");
break;
case CHAOS_SEA:
mprint("Food in the Sea of Chaos? Go on!");
break;
case DESERT:
mprint("You wander off into the trackless desert in search of food...");
Time += 100;
hourly_check();
fertility = 10;
break;
case PALACE:
case JUNGLE:
mprint("You search the lush and verdant jungle for game....");
Time += 100;
hourly_check();
fertility = 80;
break;
case PLAINS:
mprint("You set off through the tall grass; the game is afoot.");
Time += 100;
hourly_check();
fertility = 50;
break;
case TUNDRA:
mprint("You blaze a trail through the frozen wasteland....");
Time += 100;
hourly_check();
fertility = 30;
break;
case FOREST:
mprint("You try to follow the many tracks through the forest loam....");
Time += 100;
hourly_check();
fertility = 70;
break;
case MOUNTAINS: case PASS:
mprint("You search the cliff walls looking for something to eat....");
Time += 100;
hourly_check();
fertility = 30;
break;
case RIVER:
mprint("The halcyon river is your hopeful food source...");
Time += 100;
hourly_check();
fertility = 80;
break;
}
if (((Date % 360 < 60) || (Date % 360 > 300)) &&
(terrain != DESERT) &&
(terrain != JUNGLE)) {
mprint("The cold weather impedes your hunt....");
fertility = fertility / 2;
}
if (fertility > random_range(100)) {
mprint("You have an encounter...");
change_environment(E_TACTICAL_MAP);
}
else mprint("Your hunt is fruitless.");
}
void dismount_steed(void)
{
pml ml;
if (! gamestatusp(MOUNTED))
print3("You're on foot already!");
else if (Current_Environment == E_COUNTRYSIDE) {
if (cinema_confirm("If you leave your steed here he will wander away!")=='y')
resetgamestatus(MOUNTED);
}
else {
resetgamestatus(MOUNTED);;
ml = ((pml) checkmalloc(sizeof(mltype)));
ml->m = ((pmt) checkmalloc(sizeof(montype)));
*(ml->m) = Monsters[HORSE];
ml->m->x = Player.x;
ml->m->y = Player.y;
ml->m->status = MOBILE+SWIMMING;
ml->next = Level->mlist;
Level->site[Player.x][Player.y].creature = ml->m;
Level->mlist = ml;
}
calc_melee();
}
void city_move(void)
{
int site,x=Player.x,y=Player.y,toggle=FALSE;
clearmsg();
if (Current_Environment != E_CITY) {
print3("This command only works in the city!");
setgamestatus(SKIP_MONSTERS);
}
else if (Player.status[IMMOBILE] > 0)
print3("You can't even move!");
else if (hostilemonstersnear()) {
setgamestatus(SKIP_MONSTERS);
print3("You can't move this way with hostile monsters around!");
}
else if (Level->site[Player.x][Player.y].aux == NOCITYMOVE)
print3("You can't use the 'M' command from this location.");
else {
print1("Move to which establishment [? for help, ESCAPE to quit]");
site = parsecitysite();
if (site != ABORT) {
mprint("You're on your way...");
morewait();
while ((x != CitySiteList[site][1]) || (y != CitySiteList[site][2])) {
toggle = ! toggle;
if (toggle) {
Time++;
if (Time % 10 == 0) tenminute_check();
else minute_status_check();
}
x += sign(CitySiteList[site][1] - x);
y += sign(CitySiteList[site][2] - y);
screencheck(x,y);
omshowcursor(x,y);
}
Player.x = x;
Player.y = y;
screencheck(Player.x,Player.y);
mprint("Made it!");
drawvision(Player.x, Player.y);
morewait();
p_movefunction(Level->site[x][y].p_locf);
}
}
}
void frobgamestatus(void)
{
char response;
long num;
mprint("Set or Reset or Forget it [s,r,ESCAPE]:");
do response = (char) mcigetc();
while ((response != 'r') && (response != 's') && (response != ESCAPE));
if (response != ESCAPE) {
num = (int) parsenum("Enter log2 of flag:");
if (num > -1) {
num = pow2(num);
if (num == CHEATED) {
mprint("Can't alter Wizard flag.");
return;
}
if (response == 's') setgamestatus(num);
else resetgamestatus(num);
mprint("Done....");
}
}
}