omega-rpg/command2.c

1220 lines
31 KiB
C

/* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
/* command2.c */
/* This file contains toplevel commands called from command1.c */
#ifndef MSDOS_SUPPORTED_ANTIQUE
#include <unistd.h>
#include <ctype.h>
#endif
#include "glob.h"
/* no op a turn.... */
void rest(void)
{
if (random_range(20) == 1) {
switch(random_range(10)) {
case 0: print3(" Time passes slowly.... "); break;
case 1: print3(" Tick. Tock. Tick. Tock. "); break;
case 2: print3(" Ho Hum. "); break;
case 3: print3(" Beauty Sleep. Well, in your case, Ugly Sleep. "); break;
case 4: print3(" And with Strange Aeons, even Death may die. "); break;
case 5: print3(" La Di Da. "); break;
case 6: print3(" Time keeps on tickin' tickin' -- into the future.... ");
break;
case 7: print3(" Boooring! "); break;
case 8: print3(" You think I like watching you sleep? "); break;
case 9: print3(" You sure have an early bedtime! "); break;
}
morewait();
}
}
/* read a scroll, book, tome, etc. */
void peruse(void)
{
int index;
struct object *obj;
clearmsg();
if (Player.status[BLINDED] > 0)
print3("You're blind -- you can't read!!!");
else if (Player.status[AFRAID] > 0)
print3("You are too afraid to stop to read a scroll!");
else {
index = getitem_prompt("Read -- ", SCROLL);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
obj = Player.possessions[index];
if (obj->objchar != SCROLL) {
print3("There's nothing written on ");
nprint3(itemid(obj));
}
else {
nprint1("You carefully unfurl the scroll....");
morewait();
item_use(obj);
dispose_lost_objects(1,obj);
}
}
}
}
void quaff(void)
{
int index;
struct object *obj;
clearmsg();
index = getitem_prompt("Quaff -- ", POTION);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
obj = Player.possessions[index];
if (obj->objchar != POTION) {
print3("You can't drink ");
nprint3(itemid(obj));
}
else {
print1("You drink it down.... ");
item_use(obj);
morewait();
dispose_lost_objects(1,obj);
}
}
}
void activate(void)
{
int index = ABORT;
char response;
clearmsg();
print1("Activate -- item [i] or artifact [a] or quit [ESCAPE]?");
do response = (char) mcigetc();
while ((response != 'i') && (response != 'a') && (response != ESCAPE));
if (response != ESCAPE) {
if (response == 'i')
index = getitem_prompt("Activate -- ", THING);
else if (response == 'a')
index = getitem_prompt("Activate -- ", ARTIFACT);
if (index != ABORT) {
clearmsg();
print1("You activate it.... ");
morewait();
item_use(Player.possessions[index]);
}
else setgamestatus(SKIP_MONSTERS);
}
else setgamestatus(SKIP_MONSTERS);
}
void eat (void)
{
int index;
struct object *obj;
clearmsg();
index = getitem_prompt("Eat -- ", FOOD);
if (index == ABORT)
{
setgamestatus(SKIP_MONSTERS);
}
else
{
obj = Player.possessions[index];
if ((obj->objchar != FOOD) && (obj->objchar != CORPSE))
{
print3("You can't eat ");
nprint3(itemid(obj));
}
else
{
if (obj->usef == I_FOOD) Player.food = max(0, Player.food+obj->aux);
item_use(obj);
dispose_lost_objects(1,obj);
if (Current_Dungeon == E_COUNTRYSIDE)
{
Time += 100;
hourly_check();
}
}
}
foodcheck();
}
/* search all adjacent spots for secrecy */
void search(int *searchval)
{
int i;
if (Player.status[AFRAID] > 0)
print3("You are too terror-stricken to stop to search for anything.");
else {
if (!gamestatusp(FAST_MOVE)) {
setgamestatus(FAST_MOVE);
*searchval = Searchnum;
}
for (i=0;i<9;i++)
searchat(Player.x+Dirs[0][i],Player.y+Dirs[1][i]);
drawvision(Player.x,Player.y);
}
}
/* pick up a thing where the player is */
void pickup(void)
{
if (Level->site[Player.x][Player.y].things == NULL)
print3("There's nothing there!");
else if (Player.status[SHADOWFORM])
print3("You can't really interact with the real world in your shadowy state.");
else
pickup_at(Player.x,Player.y);
}
#ifndef MSDOS_SUPPORTED_ANTIQUE
/* floor inventory */
void floor_inv(void)
{
pol ol = Level->site[Player.x][Player.y].things;
setgamestatus(SKIP_MONSTERS);
menuclear();
while (ol != NULL) {
if (ol->thing == NULL) print3("***Error; null thing on things list***");
else {
menuprint(itemid(ol->thing));
menuprint("\n");
}
ol = ol->next;
}
showmenu();
morewait();
xredraw();
}
#endif
void drop(void)
{
int index,n;
clearmsg();
index = getitem_prompt("Drop -- ", CASH);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
if (index == CASHVALUE) drop_money();
else if ((! Player.possessions[index]->used) ||
(! cursed(Player.possessions[index]))) {
if (Player.possessions[index]->number == 1) {
p_drop_at(Player.x,Player.y,1,Player.possessions[index]);
conform_lost_objects(1,Player.possessions[index]);
}
else {
n = getnumber(Player.possessions[index]->number);
p_drop_at(Player.x,Player.y,n,Player.possessions[index]);
conform_lost_objects(n,Player.possessions[index]);
}
}
else {
print3("You can't seem to get rid of: ");
nprint3(itemid(Player.possessions[index]));
}
}
calc_melee();
}
/* talk to the animals -- learn their languages.... */
void talk(void)
{
int dx,dy,index=0;
char response;
struct monster *m;
clearmsg();
print1("Talk --");
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 talk to!!!");
setgamestatus(SKIP_MONSTERS);
}
else {
m = Level->site[Player.x+dx][Player.y+dy].creature;
menuclear();
strcpy(Str1," Talk to ");
strcat(Str1,m->monstring);
strcat(Str1,":");
menuprint(Str1);
menuprint("\na: Greet.");
menuprint("\nb: Threaten.");
menuprint("\nc: Surrender.");
menuprint("\nESCAPE: Clam up.");
showmenu();
do response = menugetc();
while ((response != 'a') &&
(response != 'b') &&
(response != 'c') &&
(response != ESCAPE));
switch(response) {
case 'a': monster_talk(m); break;
case 'b': threaten(m); break;
case 'c': surrender(m); break;
default: setgamestatus(SKIP_MONSTERS); break;
}
}
}
xredraw();
}
/* try to deactivate a trap */
void disarm(void)
{
int x,y,index=0;
pob o;
clearmsg();
print1("Disarm -- ");
index = getdir();
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
x = Dirs[0][index]+Player.x;
y = Dirs[1][index]+Player.y;
if (! inbounds(x,y))
print3("Whoa, off the map...");
else if (Level->site[x][y].locchar != TRAP)
print3("You can't see a trap there!");
else {
if (random_range(50+difficulty()*5) <
Player.dex*2+Player.level*3+Player.rank[THIEVES]*10) {
print1("You disarmed the trap!");
if (random_range(100) < Player.dex+Player.rank[THIEVES]*10) {
o = ((pob) checkmalloc(sizeof(objtype)));
switch(Level->site[x][y].p_locf) {
case L_TRAP_DART:
*o=Objects[OB_TRAP_DART];
break;
case L_TRAP_DISINTEGRATE:
*o=Objects[OB_TRAP_DISINTEGRATE];
break;
case L_TRAP_SLEEP_GAS:
*o=Objects[OB_TRAP_SLEEP];
break;
case L_TRAP_TELEPORT:
*o=Objects[OB_TRAP_TELEPORT];
break;
case L_TRAP_ABYSS:
*o=Objects[OB_TRAP_ABYSS];
break;
case L_TRAP_FIRE:
*o=Objects[OB_TRAP_FIRE];
break;
case L_TRAP_SNARE:
*o=Objects[OB_TRAP_SNARE];
break;
case L_TRAP_ACID:
*o=Objects[OB_TRAP_ACID];
break;
case L_TRAP_MANADRAIN:
*o=Objects[OB_TRAP_MANADRAIN];
break;
default:
/* DAG can't use free_obj() as object not initialized */
free(o);
o = NULL;
break;
}
if (o != NULL) {
print2("You manage to retrieve the trap components!");
morewait();
Objects[o->id].known = 1;
o->known = 1;
gain_item(o);
gain_experience(25);
}
}
Level->site[x][y].p_locf = L_NO_OP;
Level->site[x][y].locchar = FLOOR;
lset(x, y, CHANGED);
gain_experience(5);
}
else if (random_range(10+difficulty()*2) > Player.dex) {
print1("You accidentally set off the trap!");
Player.x = x; Player.y = y;
p_movefunction(Level->site[x][y].p_locf);
}
else print1("You failed to disarm the trap.");
}
}
}
/* is it more blessed to give, or receive? */
void give(void)
{
int index;
int dx,dy,dindex=0;
struct monster *m;
pob obj;
clearmsg();
print1("Give to monster --");
dindex = getdir();
if (dindex == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
dx = Dirs[0][dindex];
dy = Dirs[1][dindex];
if (! inbounds(Player.x+dx, Player.y+dy))
print3("Whoa, off the map...");
else if (Level->site[Player.x+dx][Player.y+dy].creature == NULL) {
print3("There's nothing there to give something to!!!");
setgamestatus(SKIP_MONSTERS);
}
else {
m = Level->site[Player.x+dx][Player.y+dy].creature;
clearmsg();
index = getitem_prompt("Give what? ", CASH);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else if (index == CASHVALUE) give_money(m);
else if (! cursed(Player.possessions[index])) {
obj = copy_obj( Player.possessions[index] );
obj->used = FALSE;
conform_lost_objects(1,Player.possessions[index]);
obj->number = 1;
print2("Given: ");
nprint2(itemid(obj));
morewait();
/* WDT bug fix: I moved the print above the givemonster
* call. If that turns out looking ugly, I should change it to
* a sprintf or strcat. At any rate, it was wrong before because
* it was accessing an object which had already been freed as part
* of givemonster. */
givemonster(m,obj);
calc_melee();
}
else {
print3("You can't even give away: ");
nprint3(itemid(Player.possessions[index]));
}
}
}
}
/* zap a wand, of course */
void zapwand(void)
{
int index;
struct object *obj;
clearmsg();
if (Player.status[AFRAID] > 0)
print3("You are so terror-stricken you can't hold a wand straight!");
else {
index = getitem_prompt("Zap -- ", STICK);
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
obj = Player.possessions[index];
if (obj->objchar != STICK) {
print3("You can't zap: ");
nprint3(itemid(obj));
}
else
if (obj->charge < 1)
print3("Fizz.... Pflpt. Out of charges. ");
else {
obj->charge--;
item_use(obj);
}
}
}
}
/* cast a spell */
void magic(void)
{
int index,drain;
clearmsg();
if (Player.status[AFRAID] > 0)
print3("You are too afraid to concentrate on a spell!");
else {
index = getspell();
xredraw();
if (index == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
drain = Spells[index].powerdrain;
if (Lunarity == 1) drain = drain / 2;
else if (Lunarity == -1) drain = drain *2;
if (drain > Player.mana)
if (Lunarity == -1 && Player.mana >= drain/2)
print3("The contrary moon has made that spell too draining! ");
else
print3("You lack the power for that spell! ");
else {
Player.mana -= drain;
cast_spell(index);
}
}
}
dataprint();
}
/* go upstairs ('<' command) */
void upstairs(void)
{
if (Level->site[Player.x][Player.y].locchar != STAIRS_UP)
print3("Not here!");
else if (Level->site[Player.x][Player.y].p_locf == L_ESCALATOR)
p_movefunction(Level->site[Player.x][Player.y].p_locf);
else {
if (gamestatusp(MOUNTED))
print2("You manage to get your horse upstairs.");
print1("You ascend a level.");
if (Level->depth <= 1) {
if (Level->environment == E_SEWERS)
change_environment(E_CITY);
else change_environment(E_COUNTRYSIDE);
}
else change_level(Level->depth,Level->depth-1,FALSE);
roomcheck();
}
setgamestatus(SKIP_MONSTERS);
}
/* go downstairs ('>' command) */
void downstairs(void)
{
if (Level->site[Player.x][Player.y].locchar != STAIRS_DOWN)
print3("Not here!");
else if (Level->site[Player.x][Player.y].p_locf == L_ENTER_CIRCLE ||
Level->site[Player.x][Player.y].p_locf == L_ENTER_COURT)
p_movefunction(Level->site[Player.x][Player.y].p_locf);
else {
if (gamestatusp(MOUNTED))
print2("You manage to get your horse downstairs.");
if (Current_Environment == Current_Dungeon) {
print1("You descend a level.");
change_level(Level->depth,Level->depth+1,FALSE);
roomcheck();
}
else if ((Current_Environment == E_CITY) ||
(Last_Environment == E_CITY))
change_environment(E_SEWERS);
else if (Current_Environment != Current_Dungeon)
print3("This stairway is deviant. You can't use it.");
}
setgamestatus(SKIP_MONSTERS);
}
/* set various player options */
/* have to redefine in odefs for next full recompile */
void setoptions(void)
{
int slot = 1,to,done = FALSE;
int response;
clearmsg();
menuclear();
display_options();
move_slot(1,1,NUMOPTIONS);
clearmsg();
print1("Currently selected option is preceded by highlit >>");
print2("Move selected option with '>' and '<', ESCAPE to quit.");
do {
response = mcigetc();
switch(response) {
case 'j':
case '>':
#ifdef KEY_DOWN
case KEY_DOWN:
#endif
to = slot + 1;
#ifndef COMPRESS_SAVE_FILES
if (to == 8) /* COMPRESS_OPTION */
to = 9;
#endif
slot = move_slot(slot,to,NUMOPTIONS+1);
break;
case 'k':
case '<':
#ifdef KEY_UP
case KEY_UP:
#endif
to = slot - 1;
#ifndef COMPRESS_SAVE_FILES
if (to == 8) /* COMPRESS_OPTION */
to = 7;
#endif
if (to > 0)
slot = move_slot(slot,to,NUMOPTIONS+1);
break;
#ifdef KEY_HOME
case KEY_HOME:
slot = move_slot(slot,1,NUMOPTIONS+1);
break;
#endif
#ifdef KEY_LL
case KEY_LL:
slot = move_slot(slot,NUMOPTIONS,NUMOPTIONS+1);
break;
#endif
case 't':
if (slot <= NUMTFOPTIONS)
optionset(pow2(slot-1));
else if (slot == VERBOSITY_LEVEL)
Verbosity = TERSE;
else print3("'T' is meaningless for this option.");
break;
case 'f':
if (slot <= NUMTFOPTIONS)
optionreset(pow2(slot-1));
else print3("'F' is meaningless for this option.");
break;
case 'm':
if (slot == VERBOSITY_LEVEL)
Verbosity = MEDIUM;
else print3("'M' is meaningless for this option.");
break;
case 'v':
if (slot == VERBOSITY_LEVEL)
Verbosity = VERBOSE;
else print3("'V' is meaningless for this option.");
break;
case '1':case '2':case '3':case '4':case '5':
case '6':case '7':case '8':case'9':
if (slot == SEARCH_DURATION)
Searchnum = response - '0';
else print3("A number is meaningless for this option.");
break;
case ESCAPE:
done = TRUE;
break;
default: print3("That response is meaningless for this option."); break;
}
display_option_slot(slot);
move_slot(slot,slot,NUMOPTIONS+1);
} while (! done);
if (optionp(SHOW_COLOUR))
colour_on();
else
colour_off();
#if !defined(MSDOS_SUPPORTED_ANTIQUE) && !defined(AMIGA)
xredraw();
#endif
}
/* name an item */
void callitem(void)
{
int index;
pob obj;
clearmsg();
setgamestatus(SKIP_MONSTERS);
index = getitem_prompt("Call -- ", NULL_ITEM);
if (index == CASHVALUE) print3("Can't rename cash!");
else if (index != ABORT) {
obj = Player.possessions[index];
if (obj->known)
print3("That item is already identified!");
else {
print1("Call it:");
obj->objstr = salloc(msgscanstring());
clearmsg();
print2("Also call all similar items by that name? [yn] ");
if (ynq2() == 'y') {
Objects[obj->id].objstr = obj->objstr;
}
}
}
}
/* open a door */
void opendoor(void)
{
int dir;
int ox,oy;
clearmsg();
print1("Open --");
dir = getdir();
if (dir == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
ox = Player.x + Dirs[0][dir];
oy = Player.y + Dirs[1][dir];
if (Level->site[ox][oy].locchar == OPEN_DOOR) {
print3("That door is already open!");
setgamestatus(SKIP_MONSTERS);
}
else if (Level->site[ox][oy].locchar == PORTCULLIS) {
print1("You try to lift the massive steel portcullis....");
if (random_range(100) < Player.str) {
print2("Incredible. You bust a gut and lift the portcullis.");
Level->site[ox][oy].locchar = FLOOR;
lset(ox, oy, CHANGED);
}
else {
print2("Argh. You ruptured yourself.");
p_damage(Player.str,UNSTOPPABLE,"a portcullis");
}
}
else if ((Level->site[ox][oy].locchar != CLOSED_DOOR) ||
loc_statusp(ox,oy,SECRET)) {
print3("You can't open that!");
setgamestatus(SKIP_MONSTERS);
}
else if (Level->site[ox][oy].aux == LOCKED)
print3("That door seems to be locked.");
else {
Level->site[ox][oy].locchar = OPEN_DOOR;
lset(ox, oy, CHANGED);
}
}
}
/* Try to destroy some location */
void bash_location(void)
{
int dir;
int ox,oy;
clearmsg();
print1("Bashing --");
dir = getdir();
if (dir == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
ox = Player.x + Dirs[0][dir];
oy = Player.y + Dirs[1][dir];
if ((Current_Environment == E_CITY) &&
(ox == 0) &&
(oy == 0)) {
print1("Back Door WIZARD Mode!");
print2("You will invalidate your score if you proceed.");
morewait();
if (cinema_confirm("You are about to enable WIZARD Mode.")=='y') {
print2("You feel like a cheater.");
setgamestatus(CHEATED);
}
else print2("A sudden tension goes out of the air....");
}
else {
if (Level->site[ox][oy].locchar == WALL) {
print1("You hurl yourself at the wall!");
p_damage(Player.str,NORMAL_DAMAGE,"a suicidal urge");
}
else if (Level->site[ox][oy].locchar == OPEN_DOOR) {
print1("You hurl yourself through the open door!");
print2("Yaaaaah! ... thud.");
morewait();
Player.x = ox;
Player.y = oy;
p_damage(3,UNSTOPPABLE,"silliness");
p_movefunction(Level->site[Player.x][Player.y].p_locf);
setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
}
else if (Level->site[ox][oy].locchar == CLOSED_DOOR) {
if (loc_statusp(ox,oy,SECRET)) {
print1("You found a secret door!");
lreset(ox,oy,SECRET);
lset(ox, oy, CHANGED);
}
if (Level->site[ox][oy].aux == LOCKED) {
if (random_range(50+difficulty()*10) < Player.str) {
Player.x = ox;
Player.y = oy;
print2("You blast the door off its hinges!");
Level->site[ox][oy].locchar = FLOOR;
lset(ox, oy, CHANGED);
p_movefunction(Level->site[Player.x][Player.y].p_locf);
setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
}
else {
print1("Crash! The door holds.");
if (random_range(30) > Player.str)
p_damage(max(1,statmod(Player.str)),UNSTOPPABLE,"a door");
}
}
else {
Player.x = ox;
Player.y = oy;
print2("You bash open the door!");
if (random_range(30) > Player.str)
p_damage(1,UNSTOPPABLE,"a door");
Level->site[ox][oy].locchar = OPEN_DOOR;
lset(ox, oy, CHANGED);
p_movefunction(Level->site[Player.x][Player.y].p_locf);
setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
}
}
else if (Level->site[ox][oy].locchar == STATUE) {
statue_random(ox,oy);
}
else if (Level->site[ox][oy].locchar == PORTCULLIS) {
print1("Really, you don't have a prayer.");
if (random_range(1000) < Player.str) {
print2("The portcullis flies backwards into a thousand fragments.");
print3("Wow. What a stud.");
gain_experience(100);
Level->site[ox][oy].locchar = FLOOR;
Level->site[ox][oy].p_locf = L_NO_OP;
lset(ox, oy, CHANGED);
}
else {
print2("You only hurt yourself on the 3'' thick steel bars.");
p_damage(Player.str,UNSTOPPABLE,"a portcullis");
}
}
else if (Level->site[ox][oy].locchar == ALTAR) {
if ((Player.patron > 0)&&(Level->site[ox][oy].aux == Player.patron)) {
print1("You have a vision! An awesome angel hovers over the altar.");
print2("The angel says: 'You twit, don't bash your own altar!'");
print3("The angel slaps you upside the head for your presumption.");
p_damage(Player.hp-1,UNSTOPPABLE,"an annoyed angel");
}
else if (Level->site[ox][oy].aux == 0) {
print1("The feeble powers of the minor godling are not enough to");
print2("protect his altar! The altar crumbles away to dust.");
print3("You feel almost unbearably smug.");
Level->site[ox][oy].locchar = RUBBLE;
Level->site[ox][oy].p_locf = L_RUBBLE;
lset(ox, oy, CHANGED);
gain_experience(5);
}
else {
print1("You have successfully annoyed a major deity. Good job.");
print2("Zzzzap! A bolt of godsfire strikes!");
if (Player.rank[PRIESTHOOD] > 0)
print3("Your own deity's aegis defends you from the bolt!");
p_damage(max(0,random_range(100)-Player.rank[PRIESTHOOD]*20),
UNSTOPPABLE,
"a bolt of godsfire");
if (Player.rank[PRIESTHOOD]*20+Player.pow+Player.level >
random_range(200)) {
morewait();
print1("The altar crumbles...");
Level->site[ox][oy].locchar = RUBBLE;
Level->site[ox][oy].p_locf = L_RUBBLE;
lset(ox, oy, CHANGED);
morewait();
if (Player.rank[PRIESTHOOD]) {
print2("You sense your deity's pleasure with you.");
morewait();
print3("You are surrounded by a golden glow.");
cleanse(1);
heal(10);
}
gain_experience(500);
}
}
}
else {
print3("You restrain yourself from total silliness.");
setgamestatus(SKIP_MONSTERS);
}
}
}
}
/* attempt destroy an item */
void bash_item(void)
{
int item;
pob obj;
clearmsg();
item = getitem_prompt("Destroy an item -- ", NULL_ITEM);
if (item == ABORT)
setgamestatus(SKIP_MONSTERS);
else if (item == CASHVALUE)
{
print3("You can't destroy cash!");
setgamestatus(SKIP_MONSTERS);
}
else
{
obj = Player.possessions[item];
if (Player.str+random_range(20) > obj->fragility+random_range(20)) {
/* damage_item() can free object, but need these after... */
int oid;
unsigned char olevel;
olevel = obj->level;
oid = obj->id;
if ( damage_item(obj) )
{
if ( OB_POTION_CHAOS == oid )
{
Player.alignment += random_range(10);
if ( Player.alignment < 0 )
{
print2("You feel a sense of inner constraint!");
gain_experience(olevel * olevel * 5);
}
else
print2("You feel wonderfully lawful!");
/* In either case, chaotic or lawful, destroying a PoCh is
* lawful. */
Player.alignment += random_range(10);
}
else if ( OB_SCROLL_LAW == oid )
{
Player.alignment -= random_range(10);
if ( Player.alignment < 0 )
{
print2("You feel deliciously chaotic!");
gain_experience(olevel * olevel * 5);
}
else
print2("You feel a sense of inner turmoil!");
Player.alignment -= random_range(10);
}
else if (Player.alignment < 0)
{
print2("That was fun....");
gain_experience(olevel * olevel * 5);
}
}
}
else {
if (obj->objchar == WEAPON) {
print2("The weapon turned in your hand -- you hit yourself!");
p_damage(random_range(obj->dmg+abs(obj->plus)),
NORMAL_DAMAGE,
"a failure at vandalism");
}
else if (obj->objchar == ARTIFACT) {
print2("Uh Oh -- Now you've gotten it angry....");
p_damage(obj->level*10,
UNSTOPPABLE,
"an enraged artifact");
}
else {
print2("Ouch! Damn thing refuses to break...");
p_damage(1,UNSTOPPABLE,"a failure at vandalism");
}
}
}
}
/* guess what this does */
/* if force is true, exiting due to some problem - don't bomb out */
void save(int compress, int force)
{
char fname[100];
int pos, ok = TRUE;
clearmsg();
if (gamestatusp(ARENA_MODE)) {
if (force) {
resetgamestatus(ARENA_MODE);
change_environment(E_CITY);
}
else {
print3("Can't save the game in the arena!");
setgamestatus(SKIP_MONSTERS);
ok = FALSE;
}
}
else if (Current_Environment == E_ABYSS) {
if (force)
change_environment(E_COUNTRYSIDE);
else {
print3("Can't save the game in the Adept's Challenge!");
setgamestatus(SKIP_MONSTERS);
ok = FALSE;
}
}
else if (Current_Environment == E_TACTICAL_MAP) {
if (force)
change_environment(E_COUNTRYSIDE);
else {
/* WDT MARK! I understand this, but it's wrong. */
print3("Can't save the game in the tactical map!");
setgamestatus(SKIP_MONSTERS);
ok = FALSE;
}
}
if (!force && ok) {
ok = (cinema_confirm("You're about to save and exit.") == 'y');
}
if (force || ok) {
sprintf(Str1, "Enter savefile name [default %s]: ", SaveFileName );
print1(Str1);
strcpy(fname,msgscanstring());
if (fname[0] == '\0') {
/* no file name entered, use default. DAG */
strcpy( fname, SaveFileName );
}
#ifdef MSDOS
for (pos = 0; fname[pos] && isalnum(fname[pos]); pos++)
;
#else
for (pos = 0; fname[pos] && isprint(fname[pos]) && !isspace(fname[pos]);
pos++)
;
#endif
if (fname[pos]) {
sprintf(Str1, "Illegal character '%c' in filename - Save aborted.", fname[pos]);
print1(Str1);
ok = FALSE;
}
#ifdef MSDOS
if (strlen(fname) > FNAME_MAX_LEN)
{
/* WDT -- copied from SYSV block below. */
sprintf(Str1, "Save name longer than %d characters - Save aborted.",
FNAME_MAX_LEN);
print1(Str1);
ok = FALSE;
}
#else
# ifdef SYSV
if (strlen(fname) > FNAME_MAX_LEN - EXT_LENGTH - 1)
{
sprintf(Str1, "Save name longer than %d characters - Save aborted.",
FNAME_MAX_LEN - EXT_LENGTH - 1);
print1(Str1);
ok = FALSE;
}
# endif
#endif
if (ok) {
if (save_game(compress,fname)) {
endgraf();
printf("Bye!\n");
exit(0);
}
else
print1("Internal error -- unable to save.");
}
}
if (force) {
morewait();
clearmsg();
print1("The game is quitting - you will lose your character.");
print2("Try to save again? ");
if (ynq2() == 'y')
save(compress, force);
}
setgamestatus(SKIP_MONSTERS); /* if we get here, we failed to save */
}
/* close a door */
void closedoor(void)
{
int dir;
int ox,oy;
clearmsg();
print1("Close --");
dir = getdir();
if (dir == ABORT)
setgamestatus(SKIP_MONSTERS);
else {
ox = Player.x + Dirs[0][dir];
oy = Player.y + Dirs[1][dir];
if (Level->site[ox][oy].locchar == CLOSED_DOOR) {
print3("That door is already closed!");
setgamestatus(SKIP_MONSTERS);
}
else if (Level->site[ox][oy].locchar != OPEN_DOOR) {
print3("You can't close that!");
setgamestatus(SKIP_MONSTERS);
}
else Level->site[ox][oy].locchar = CLOSED_DOOR;
lset(ox, oy, CHANGED);
}
}
/* handle a h,j,k,l, etc. */
void moveplayer(int dx, int dy)
{
if (p_moveable(Player.x+dx,Player.y+dy)) {
if (Player.status[IMMOBILE] > 0) {
resetgamestatus(FAST_MOVE);
print3("You are unable to move");
}
else if ((Player.maxweight < Player.itemweight) &&
random_range(2) &&
(! Player.status[LEVITATING])) {
if (gamestatusp(MOUNTED)) {
print1("Your horse refuses to carry you and your pack another step!");
print2("Your steed bucks wildly and throws you off!");
p_damage(10,UNSTOPPABLE,"a cruelly abused horse");
resetgamestatus(MOUNTED);
summon(-1,HORSE);
}
else {
p_damage(1,UNSTOPPABLE,"a rupture");
print3("The weight of your pack drags you down. You can't move.");
}
}
else {
Player.x += dx;
Player.y += dy;
p_movefunction(Level->site[Player.x][Player.y].p_locf);
/* causes moves to take effectively 30 seconds in town without
monsters being sped up compared to player */
if ((Current_Environment == E_CITY) ||
(Current_Environment == E_VILLAGE)) {
twiddle = ! twiddle;
if (twiddle) {
Time++;
if (Time % 10 == 0) tenminute_check();
else minute_status_check();
}
}
/* this test protects against player entering countryside and still
having effects from being on the Level, a kluge, but hey,... */
if (Current_Environment != E_COUNTRYSIDE) {
if (gamestatusp(FAST_MOVE))
if ((Level->site[Player.x][Player.y].things != NULL) ||
(optionp(RUNSTOP) &&
loc_statusp(Player.x,Player.y,STOPS)))
resetgamestatus(FAST_MOVE);
if ((Level->site[Player.x][Player.y].things != NULL) &&
(optionp(PICKUP)))
pickup();
}
}
}
else if (gamestatusp(FAST_MOVE)) {
drawvision(Player.x,Player.y);
resetgamestatus(FAST_MOVE);
}
}
/* handle a h,j,k,l, etc. */
void movepincountry(int dx, int dy)
{
int i,takestime = TRUE;
if ((Player.maxweight < Player.itemweight) &&
random_range(2) &&
(! Player.status[LEVITATING])) {
if (gamestatusp(MOUNTED)) {
print1("Your horse refuses to carry you and your pack another step!");
print2("Your steed bucks wildly and throws you off!");
p_damage(10,UNSTOPPABLE,"a cruelly abused horse");
resetgamestatus(MOUNTED);
morewait();
print1("With a shrill neigh of defiance, your former steed gallops");
print2("off into the middle distance....");
if (Player.packptr != 0) {
morewait();
print1("You remember (too late) that the contents of your pack");
print2("were kept in your steed's saddlebags!");
for(i=0;i<MAXPACK;i++) {
if (Player.pack[i] != NULL)
free_obj( Player.pack[i], TRUE );
Player.pack[i] = NULL;
}
Player.packptr = 0;
calc_melee();
}
}
else {
p_damage(1,UNSTOPPABLE,"a rupture");
print3("The weight of your pack drags you down. You can't move.");
}
}
else {
if (gamestatusp(LOST)) {
print3("Being lost, you strike out randomly....");
morewait();
dx = random_range(3)-1;
dy = random_range(3)-1;
}
if (p_country_moveable(Player.x+dx,Player.y+dy)) {
if (Player.status[IMMOBILE] > 0)
print3("You are unable to move");
else {
Player.x += dx;
Player.y += dy;
if ((! gamestatusp(MOUNTED))&&(Player.possessions[O_BOOTS] != NULL)) {
if (Player.possessions[O_BOOTS]->usef == I_BOOTS_7LEAGUE) {
takestime = FALSE;
if (Player.possessions[O_BOOTS]->blessing < 0) {
print1("Whooah! -- Your boots launch you into the sky....");
print2("You come down in a strange location....");
setPlayerXY( random_range(COUNTRY_WIDTH), random_range(COUNTRY_LENGTH));
morewait();
clearmsg();
print1("Your boots disintegrate with a malicious giggle...");
dispose_lost_objects(1,Player.possessions[O_BOOTS]);
}
else if (Player.possessions[O_BOOTS]->known != 2) {
print1("Wow! Your boots take you 7 leagues in a single stride!");
Player.possessions[O_BOOTS]->known = 2;
}
}
}
if (gamestatusp(LOST) && (Precipitation < 1) &&
c_statusp(Player.x, Player.y, SEEN)) {
print3("Ah! Now you know where you are!");
morewait();
resetgamestatus(LOST);
}
else if (gamestatusp(LOST)) {
print3("You're still lost.");
morewait();
}
if (Precipitation > 0) Precipitation--;
c_set(Player.x, Player.y, SEEN);
terrain_check(takestime);
}
}
}
}