Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

rogue clone, again(groan!), this time in small pieces, part 3 of 3.

1 view
Skip to first unread message

Tim Stoehr

unread,
Mar 16, 1986, 3:35:50 PM3/16/86
to
#!/bin/sh-----cut here-----cut here-----cut here-----cut here-----
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# play.c # random.c # room.c # score.c # special_hit.c # throw.c # use.c # zap.c
echo shar: extracting play.c
cat - << \SHAR_EOF > play.c
#include <curses.h>
#include "object.h"
#include "move.h"

short interrupted = 0;
extern short party_room, detect_monster;
extern char hit_message[];

play_level()
{
short ch;
int count = 0;

for (;;) {
interrupted = 0;
if (hit_message[0]) {
message(hit_message);
hit_message[0] = 0;
}
move(rogue.row, rogue.col);
refresh();
ch = getchar();
check_message();
CH:
switch(ch) {
case '.':
rest((count > 0) ? count : 1);
break;
case 'i':
inventory(&rogue.pack, IS_OBJECT);
break;
/*case 'p':
inventory(&level_objects, IS_OBJECT);
break;*/
case 'f':
fight(0);
break;
case 'F':
fight(1);
break;
case 'h':
case 'j':
case 'k':
case 'l':
case 'y':
case 'u':
case 'n':
case 'b':
single_move_rogue(ch, 1);
break;
case 'H':
case 'J':
case 'K':
case 'L':
case 'B':
case 'Y':
case 'U':
case 'N':
case '\010':
case '\012':
case '\013':
case '\014':
case '\031':
case '\025':
case '\016':
case '\002':
multiple_move_rogue(ch);
break;
case 'e':
eat();
break;
case 'q':
quaff();
break;
case 'r':
read_scroll();
break;
case 'm':
move_onto();
break;
case 'd':
drop();
break;
case '\020':
remessage();
break;
case '>':
if (check_down()) {
return;
}
break;
case '<':
if (check_up()) {
return;
}
break;
case 'I':
single_inventory();
break;
case '\022':
wrefresh(curscr);
break;
case 'T':
take_off();
break;
case 'W':
case 'P':
wear();
break;
case 'w':
wield();
break;
case 'c':
call_it();
break;
case 'z':
zapp();
break;
case 't':
throw();
break;
case '\032':
tstp();
break;
case '!':
shell();
break;
case 'v':
message("i_rogue: Version 1.0. (stoehr was here)", 0);
break;
case 'Q':
quit();
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
count = 0;
do {
count = (10 * count) + (ch - '0');
ch = getchar();
} while ((ch >= '0') && (ch <= '9'));
goto CH;
break;
case ' ':
break;
default:
message("unknown command");
break;
}
}
}
SHAR_EOF
echo shar: extracting random.c
cat - << \SHAR_EOF > random.c
#include "macros.h"

get_rand(x, y)
int x, y;
{
long r, random();
int s;

two_sort(x, y);

r = random();
r = (r % ((y-x)+1)) + x;
s = (int) r;
return(s);
}

rand_percent(percentage)
{
return(get_rand(1, 100) <= percentage);
}
SHAR_EOF
echo shar: extracting room.c
cat - << \SHAR_EOF > room.c
#include <curses.h>
#include "room.h"
#include "object.h"
#include "move.h"

short current_room;
room rooms[MAXROOMS];
extern short detect_monster;
extern short blind;

light_up_room()
{
short i, j;

if (blind) return;
for (i = rooms[current_room].top_row;
i <= rooms[current_room].bottom_row; i++) {
for (j = rooms[current_room].left_col;
j <= rooms[current_room].right_col; j++) {
mvaddch(i, j, get_room_char(screen[i][j], i, j));
}
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
}

light_passage(row, col)
{
short i, j, i_end, j_end;

if (blind) return;

i_end = (row < (LINES-2)) ? 1 : 0;
j_end = (col < (COLS-1)) ? 1 : 0;

for (i = ((row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
for (j = ((col > 0) ? -1 : 0); j <= j_end; j++) {
if (is_passable(row+i, col+j)) {
mvaddch(row+i, col+j,
get_room_char(screen[row+i][col+j],
row+i, col+j));
}
}
}
}

darken_room(rn)
short rn;
{
short i, j;

if (blind) return;

for (i = rooms[rn].top_row + 1;
i < rooms[rn].bottom_row; i++) {
for (j = rooms[rn].left_col + 1;
j < rooms[rn].right_col; j++) {
if (!is_object(i, j) &&
!(detect_monster && (screen[i][j] & MONSTER))) {
if (!hiding_xeroc(i, j)) {
mvaddch(i, j, ' ');
}
}
}
}
}

get_room_char(mask, row, col)
register short mask;
register short row, col;
{
if (mask & MONSTER) {
return(get_monster_char_row_col(row, col));
}
if (mask & SCROLL) {
return('?');
}
if (mask & POTION) {
return('!');
}
if (mask & FOOD) {
return(':');
}
if (mask & WAND) {
return('/');
}
if (mask & ARMOR) {
return(']');
}
if (mask & WEAPON) {
return(')');
}
if (mask & GOLD) {
return('*');
}
if (mask & TUNNEL) {
return('#');
}
if (mask & HORWALL) {
return('-');
}
if (mask & VERTWALL) {
return('|');
}
if (mask & AMULET) {
return(',');
}
if (mask & FLOOR) {
return('.');
}
if (mask & DOOR) {
return('+');
}
if (mask & STAIRS) {
return('%');
}
return(' ');
}

get_rand_row_col(row, col, mask)
short *row, *col;
unsigned short mask;
{
short rn;
AGAIN:
do {
*row = get_rand(MIN_ROW, SROWS-2);
*col = get_rand(0, SCOLS-1);
rn = get_room_number(*row, *col);
} while (!(screen[*row][*col] & mask) || (rn == NO_ROOM));
if (screen[*row][*col] & (~mask)) goto AGAIN;
}

get_rand_room()
{
short i;

do {
i = get_rand(0, MAXROOMS-1);
} while (!rooms[i].is_room);

return(i);
}

fill_room_with_objects(rn)
{
short i;
object *obj, *get_rand_object();
short n, N, row, col;

N = ((rooms[rn].bottom_row - rooms[rn].top_row) - 1) *
((rooms[rn].right_col - rooms[rn].left_col) - 1);
n = get_rand(5, 10);
if (n > N) n = N - 2;

for (i = 0; i < n; i++) {
do {
row = get_rand(rooms[rn].top_row+1,
rooms[rn].bottom_row-1);
col = get_rand(rooms[rn].left_col+1,
rooms[rn].right_col-1);
} while (screen[row][col] != FLOOR);

obj = get_rand_object();
put_object_at(obj, row, col);
}
return(n);
}

get_room_number(row, col)
{
short i;

for (i = 0; i < MAXROOMS; i++) {
if ((row >= rooms[i].top_row)&&(row <= rooms[i].bottom_row) &&
(col >= rooms[i].left_col)&&(col <= rooms[i].right_col)) {
return(i);
}
}
return(NO_ROOM);
}

shell()
{
char *getenv(), *rindex();
char *sh;
int status;

move(LINES-1, 0);
refresh();
stop_window();
putchar('\n');

if (!(sh = getenv("SHELL"))) {
sh = "/bin/sh";
}

if (!fork()) {
if (setreuid(-1, getuid()) < 0) exit(1);
execl(sh, rindex(sh, '/') + 1, 0);
exit(0);
}
wait(&status);
start_window();
wrefresh(curscr);
}
SHAR_EOF
echo shar: extracting score.c
cat - << \SHAR_EOF > score.c
#include <signal.h>
#include <curses.h>
#include "object.h"
#include "monster.h"
#include "room.h"
#include <sys/file.h>

extern char *player_name;
extern char *monster_names[];
extern short has_amulet, max_level;

killed_by(monster, other)
object *monster;
short other;
{
char buf[80];
short i;

signal(SIGINT, SIG_IGN);

if (other != QUIT) {
rogue.gold = ((rogue.gold * 9) / 10);
}

if (other) {
switch(other) {
case HYPOTHERMIA:
strcpy(buf, "died of hypothermia");
break;
case STARVATION:
strcpy(buf, "died of starvation");
break;
case QUIT:
strcpy(buf, "quit");
break;
}
} else {
strcpy(buf, "Killed by ");
if (is_vowel(monster_names[monster->ichar - 'A'])) {
strcat(buf, "an ");
} else {
strcat(buf, "a ");
}
strcat(buf, monster_names[monster->ichar - 'A']);
}
strcat(buf, " with ");
sprintf(buf+strlen(buf), "%d gold", rogue.gold);
message(buf, 0);
message("");
score(monster, other);
}

win()
{
rogue.armor = 0; /* disarm and relax */
rogue.weapon = 0;

clear();
mvaddstr(10, 11, "@ @ @@@ @ @ @ @ @ @@@ @ @ @");
mvaddstr(11, 11, " @ @ @ @ @ @ @ @ @ @ @ @@ @ @");
mvaddstr(12, 11, " @ @ @ @ @ @ @ @ @ @ @ @ @ @");
mvaddstr(13, 11, " @ @ @ @ @ @ @ @ @ @ @ @@");
mvaddstr(14, 11, " @ @@@ @@@ @@ @@ @@@ @ @ @");
mvaddstr(17, 11, "Congratulations, you have been admitted to the");
mvaddstr(18, 11, "Fighter's Guild. You return home, sell all your");
mvaddstr(19, 11, "treasures at great profit and retire into comfort.");
message("");
message("");
id_all();
sell_pack();
score((object *) 0, WIN);
}

quit()
{
message("really quit?", 1);
if (getchar() != 'y') {
check_message();
return;
}
check_message();

killed_by(0, QUIT);
}

score(monster, other)
object *monster;
{
int fd;

while (access(SCOREFILE, W_OK) || access(SCOREFILE, R_OK)) {
umask(0);
if ((fd = creat(SCOREFILE, 0666)) < 0) {
message("cannot find/read/write score file");
message(SCOREFILE);
message("I'll wait, you go off and try to fix it");
message("hit space when finished fixing the problem");
wait_for_ack(0);
} else {
close(fd);
}
}
put_scores(monster, other);
}

put_scores(monster, other)
object *monster;
{
short i, j, n, rank = 10, x, dont_insert = 0;
char scores[10][82];
int fd, s;

fd = open(SCOREFILE, O_RDWR, 0);

for (i = 0; i < 10; i++) {
L: if (((n = read(fd, scores[i], 80)) < 80) && (n != 0)) {
message("error in score file format");
message("");
clean_up("sorry, score file is out of order");
} else if (n == 0) {
break;
}
if (!ncmp(scores[i]+16, player_name)) {
x = 7;
while (scores[i][x] == ' ') x++;
s = get_number(scores[i] + x);
if (s <= rogue.gold) {
goto L;
} else {
dont_insert = 1;
}
}
}
if (dont_insert) goto DI;

for (j = 0; j < i; j++) {
if (rank > 9) {

x = 7;
while (scores[j][x] == ' ') x++;
s = get_number(scores[j] + x);

if (s <= rogue.gold) {
rank = j;
}
}
}
if (i == 0) {
rank = 0;
} else if ((i < 10) && (rank > 9)) {
rank = i;
}
if (rank <= 9) {
insert_score(scores, rank, i, monster, other);

if (i < 10) {
i++;
}
}
lseek(fd, 0, 0);
DI:
clear();
mvaddstr(3, 30, "Top Ten Rogueists");
mvaddstr(8, 0, "Rank\tScore\tName");

signal(SIGQUIT, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);

for (j = 0; j < i; j++) {
if (j == rank) {
standout();
}
if (j == 9) {
scores[j][0] = '1';
scores[j][1] = '0';
} else {
scores[j][0] = ' ';
scores[j][1] = j + '1';
}
mvaddstr(j+10, 0, scores[j]);
if (rank < 10) {
write(fd, scores[j], 80);
}
if (j == rank) {
standend();
}
}
refresh();
close(fd);
clean_up("");
}

insert_score(scores, rank, n, monster, other)
char scores[][82];
short rank, n;
object *monster;
{
short i, k;
char buf[82];

for (i = (n - 1); i >= rank; i--) {
if (i < 9) {
strcpy(scores[i+1], scores[i]);
}
}
sprintf(buf, "%2d %5d %s: ", rank+1, rogue.gold, player_name);

if (other) {
switch(other) {
case HYPOTHERMIA:
strcat(buf, "died of hypothermia");
break;
case STARVATION:
strcat(buf, "died of starvation");
break;
case QUIT:
strcat(buf, "quit");
break;
case WIN:
strcat(buf, "a total winner");
break;
}
} else {
strcat(buf, "killed by ");
if (is_vowel(monster_names[monster->ichar - 'A'])) {
strcat(buf, "an ");
} else {
strcat(buf, "a ");
}
strcat(buf, monster_names[monster->ichar - 'A']);
}
sprintf(buf+strlen(buf), " on level %d ", max_level);
if ((other != WIN) && has_amulet) {
strcat(buf, "with amulet");
}
for (i = strlen(buf); i < 79; i++) {
buf[i] = ' ';
}
buf[79] = 0;
strcpy(scores[rank], buf);
}

is_vowel(ch)
short ch;
{
return( (ch == 'a') ||
(ch == 'e') ||
(ch == 'i') ||
(ch == 'o') ||
(ch == 'u') );
}

sell_pack()
{
object *obj;
short row = 2, val;
char buf[80];

obj = rogue.pack.next_object;

clear();

while (obj) {
mvaddstr(1, 0, "Value Item");
if (obj->what_is == FOOD) {
goto NEXT;
}
obj->identified = 1;
val = get_value(obj);
rogue.gold += val;

if (row < SROWS) {
sprintf(buf, "%5d ", val);
get_description(obj, buf+11);
mvaddstr(row++, 0, buf);
}
NEXT: obj = obj->next_object;
}
refresh();
message("");
}

get_value(obj)
object *obj;
{
short wc;
int val;

wc = obj->which_kind;

switch(obj->what_is) {
case WEAPON:
val = id_weapons[wc].value;
if ((wc == ARROW) || (wc == SHURIKEN)) {
val *= obj->quantity;
}
val += (obj->damage_enchantment * 85);
val += (obj->to_hit_enchantment * 85);
break;
case ARMOR:
val = id_armors[wc].value;
val += (obj->damage_enchantment * 75);
if (obj->is_protected) {
val += 200;
}
break;
case WAND:
val = id_wands[wc].value * obj->class;
break;
case SCROLL:
val = id_scrolls[wc].value * obj->quantity;
break;
case POTION:
val = id_potions[wc].value * obj->quantity;
break;
case AMULET:
val = 5000;
break;
}
if (val <= 0) {
val = 10;
}
return(val);
}

id_all()
{
short i;

for (i = 0; i < SCROLLS; i++) {
id_scrolls[i].id_status = IDENTIFIED;
}
for (i = 0; i < WEAPONS; i++) {
id_weapons[i].id_status = IDENTIFIED;
}
for (i = 0; i < ARMORS; i++) {
id_armors[i].id_status = IDENTIFIED;
}
for (i = 0; i < WANDS; i++) {
id_wands[i].id_status = IDENTIFIED;
}
for (i = 0; i < POTIONS; i++) {
id_potions[i].id_status = IDENTIFIED;
}
}

ncmp(s1, s2)
char *s1, *s2;
{
short i = 0;
int r;

while(s1[i] != ':') i++;
s1[i] = 0;
r = strcmp(s1, s2);
s1[i] = ':';
return(r);
}
SHAR_EOF
echo shar: extracting special_hit.c
cat - << \SHAR_EOF > special_hit.c
#include <curses.h>
#include "object.h"
#include "move.h"
#include "monster.h"

short being_held;

extern short current_level, max_level, has_amulet, detect_monster;
extern int level_points[];

special_hit(monster)
object *monster;
{
switch(monster->ichar) {
case 'A':
rust(monster);
break;
case 'F':
being_held = 1;
break;
case 'I':
freeze(monster);
break;
case 'L':
steal_gold(monster);
break;
case 'N':
steal_item(monster);
break;
case 'R':
sting(monster);
break;
case 'V':
drain_life();
break;
case 'W':
drain_level();
break;
}
}

rust(monster)
object *monster;
{
if (!rogue.armor || (get_armor_class(rogue.armor) <= 1) ||
(rogue.armor->which_kind == LEATHER)) {
return;
}
if (rogue.armor->is_protected) {
if (!monster->identified) {
message("the rust vanishes instantly", 0);
monster->identified = 1;
}
} else {
rogue.armor->damage_enchantment--;
message("your armor weakens", 0);
print_stats();
}
}

freeze(monster)
object *monster;
{
short freeze_percent = 99;
short i, n;

if (rand_percent(12)) return;

freeze_percent -= (rogue.strength_current+(rogue.strength_current/2));
freeze_percent -= rogue.exp * 4;
freeze_percent -= (get_armor_class(rogue.armor) * 5);
freeze_percent -= (rogue.hp_max / 3);

if (freeze_percent > 10) {
monster->identified = 1;
message("you are frozen", 1);

n = get_rand(5, 9);
for (i = 0; i < n; i++) {
move_monsters();
}
if (rand_percent(freeze_percent)) {
for (i = 0; i < 50; i++) {
move_monsters();
}
killed_by((object *)0, HYPOTHERMIA);
}
message("you can move again", 1);
monster->identified = 0;
}
}

steal_gold(monster)
object *monster;
{
int amount;

if (rand_percent(15)) return;

if (rogue.gold > 50) {
amount = rogue.gold > 1000 ? get_rand(8, 15) : get_rand(2, 5);
amount = rogue.gold / amount;
} else {
amount = rogue.gold/2;
}
amount += (get_rand(0, 2) - 1) * (rogue.exp + current_level);
if ((amount <= 0) && (rogue.gold > 0)) {
amount = rogue.gold;
}

if (amount > 0) {
rogue.gold -= amount;
message("your purse feels lighter", 0);
print_stats();
}
disappear(monster);
}

steal_item(monster)
object *monster;
{
object *obj;
short i, n, has_something = 0;
char description[80];

if (rand_percent(15)) return;

obj = rogue.pack.next_object;

if (!obj) {
goto DSPR;
}
while (obj) {
if ((obj != rogue.armor) && (obj != rogue.weapon)) {
has_something = 1;
break;
}
obj = obj->next_object;
}
if (!has_something) goto DSPR;

n = get_rand(0, MAX_PACK_COUNT);
obj = rogue.pack.next_object;

for (i = 0; i <= n; i++) {
obj = obj->next_object;
while (!obj || (obj == rogue.weapon) || (obj == rogue.armor)) {
if (!obj) {
obj = rogue.pack.next_object;
} else {
obj = obj->next_object;
}
}
}
strcpy(description, "she stole ");
get_description(obj, description+10);
message(description, 0);

if (obj->what_is == AMULET) {
has_amulet = 0;
}
vanish(obj, 0);
DSPR: disappear(monster);
}

disappear(monster)
object *monster;
{
short row, col;

row = monster->row;
col = monster->col;

remove_mask(row, col, MONSTER);
if (can_see(row, col)) {
mvaddch(row, col, get_room_char(screen[row][col], row, col));
}
remove_from_pack(monster, &level_monsters);
free(monster);
}

cough_up(monster)
object *monster;
{
object *obj, *get_an_object(),*get_rand_object();
short row, col, i, j, n;

if (current_level < max_level) {
return;
}

switch(monster->ichar) {
case 'L':
obj = get_an_object();
obj->what_is = GOLD;
obj->quantity = get_rand(9, 599);
break;
default:
if (rand_percent(monster->which_kind)) {
obj = get_rand_object();
break;
}
return;
}
row = monster->row;
col = monster->col;

for (n = 0; n <= 5; n++) {
for (i = -n; i <= n; i++) {
if (try_to_cough(row+n, col+i, obj)) {
return;
}
if (try_to_cough(row-n, col+i, obj)) {
return;
}
}
for (i = -n; i <= n; i++) {
if (try_to_cough(row+i, col-n, obj)) {
return;
}
if (try_to_cough(row+i, col+n, obj)) {
return;
}
}
}
free(obj);
}

try_to_cough(row, col, obj)
short row, col;
object *obj;
{
if ((row<MIN_ROW)||(row>(LINES-2))||(col<0)||(col>(COLS-1))) {
return(0);
}
if ((!(screen[row][col] & IS_OBJECT)) &&
(screen[row][col] & (TUNNEL|FLOOR|DOOR)) &&
!(screen[row][col] & MONSTER)) {
put_object_at(obj, row, col);
mvaddch(row, col, get_room_char(screen[row][col], row, col));
refresh();
return(1);
}
return(0);
}

orc_gold(monster)
object *monster;
{
short i, j, row, col, rn, s;

if (monster->identified) {
return(0);
}
if ((rn = get_room_number(monster->row, monster->col)) < 0) {
return(0);
}
for (i = rooms[rn].top_row+1;
i < rooms[rn].bottom_row; i++) {
for (j = rooms[rn].left_col+1;
j < rooms[rn].right_col; j++) {
if ((screen[i][j] & GOLD) &&
!(screen[i][j] & MONSTER)) {
monster->m_flags |= CAN_GO;
s = monster_can_go(monster, i, j);
monster->m_flags &= (~CAN_GO);
if (s) {
move_monster_to(monster, i, j);
monster->m_flags |= IS_ASLEEP;
monster->m_flags &= (~WAKENS);
monster->identified = 1;
return(1);
}
monster->identified = 1;
monster->m_flags |= CAN_GO;
mv_monster(monster, i, j);
monster->m_flags &= (~CAN_GO);
monster->identified = 0;
return(1);
}
}
}
return(0);
}

check_orc(monster)
object *monster;
{
if (monster->ichar == 'O') {
monster->identified = 1;
}
}

check_xeroc(monster)
object *monster;
{
char *monster_name();
char msg[80];

if ((monster->ichar == 'X') && monster->identified) {
wake_up(monster);
monster->identified = 0;
mvaddch(monster->row, monster->col,
get_room_char(screen[monster->row][monster->col],
monster->row, monster->col));
check_message();
sprintf(msg, "wait, that's a %s!", monster_name(monster));
message(msg, 1);
return(1);
}
return(0);
}

hiding_xeroc(row, col)
register short row, col;
{
object *object_at(), *monster;

if ((current_level < XEROC1) || (current_level > XEROC2) ||
!(screen[row][col] & MONSTER)) {
return(0);
}
monster = object_at(&level_monsters, row, col);

if ((monster->ichar == 'X') && monster->identified) {
return(1);
}
return(0);
}

sting(monster)
object *monster;
{
short ac, sting_chance = 35;
char msg[80], *monster_name();

if (rogue.strength_current < 5) return;

ac = get_armor_class(rogue.armor);

sting_chance += (6 * (6 - ac));

if (rogue.exp > 8) {
sting_chance -= (6 * (rogue.exp - 8));
}

if (sting_chance > 100) {
sting_chance = 100;
} else if (sting_chance <= 0) {
sting_chance = 1;
}
if (rand_percent(sting_chance)) {
sprintf(msg, "the %s's bite has weakened you",
monster_name(monster));
message(msg, 0);
rogue.strength_current--;
print_stats();
}
}

drain_level()
{
if (!rand_percent(20) || (rogue.exp <= 7)) {
return;
}
rogue.exp_points = level_points[rogue.exp-2] - get_rand(10, 50);
rogue.exp -= 2;
add_exp(1);
}

drain_life()
{
if (!rand_percent(25) || (rogue.hp_max<=30) || (rogue.hp_current<10)) {
return;
}
message("you feel weaker", 0);
rogue.hp_max--;
rogue.hp_current--;
if (rand_percent(50)) {
if (rogue.strength_current >= 5) {
rogue.strength_current--;
if (rand_percent(50)) {
rogue.strength_max--;
}
}
}
print_stats();
}

m_confuse(monster)
object *monster;
{
char msg[80];
char *monster_name();

if (monster->identified) {
return(0);
}
if (!can_see(monster->row, monster->col)) {
return(0);
}
if (rand_percent(45)) {
monster->identified = 1;
return(0);
}
if (rand_percent(55)) {
monster->identified = 1;
sprintf(msg, "the gaze of the %s has confused you",
monster_name(monster));
message(msg, 1);
confuse();
return(1);
}
return(0);
}

flame_broil(monster)
object *monster;
{
short row, col;

if (!can_see(monster->row, monster->col)) {
return(0);
}
if (rand_percent(50)) {
return(0);
}
if (!rogue_is_around(monster->row, monster->col)) {

row = monster->row; col = monster->col;
get_closer(&row, &col, rogue.row, rogue.col);
standout();
do {
mvaddch(row, col, '*');
refresh();
get_closer(&row, &col, rogue.row, rogue.col);
} while ((row != rogue.row) || (col != rogue.col));
standend();
row = monster->row; col = monster->col;
get_closer(&row, &col, rogue.row, rogue.col);
do {
mvaddch(row, col, get_room_char(screen[row][col],
row, col));
refresh();
get_closer(&row, &col, rogue.row, rogue.col);
} while ((row != rogue.row) || (col != rogue.col));
}
monster_hit(monster, "flame");
return(1);
}

get_closer(row, col, trow, tcol)
short *row, *col;
short trow, tcol;
{
if (*row < trow) {
(*row)++;
} else if (*row > trow) {
(*row)--;
}
if (*col < tcol) {
(*col)++;
} else if (*col > tcol) {
(*col)--;
}
}
SHAR_EOF
echo shar: extracting throw.c
cat - << \SHAR_EOF > throw.c
#include <curses.h>
#include "object.h"
#include "move.h"
#include "monster.h"

extern short current_room;
extern char *CURSE_MESSAGE;
extern char hit_message[];

throw()
{
short wch;
short first_miss = 1, f = 1;
object *weapon, *get_letter_object();
short dir, row, col;
object *monster, *get_thrown_at_monster();

while (!is_direction(dir = getchar())) {
putchar(7);
fflush(stdout);
if (first_miss) {
message("direction? ", 0);
first_miss = 0;
}
}
if (dir == CANCEL) {
check_message();
return;
}
if ((wch = get_pack_letter("throw what?", WEAPON)) == CANCEL) {
check_message();
return;
}
check_message();

if (!(weapon = get_letter_object(wch))) {
message("no such item.", 0);
return;
}
if (weapon->what_is != WEAPON) {
wch = get_rand(0, 2);

switch(wch) {
case 0:
message("if you don't want it, drop it!", 0);
break;
case 1:
message("throwing that would do noone any good", 0);
break;
case 2:
message("why would you want to throw that?", 0);
break;
}
return;
}
if ((weapon == rogue.weapon) && (weapon->is_cursed)) {
message(CURSE_MESSAGE, 0);
return;
}
row = rogue.row; col = rogue.col;
monster = get_thrown_at_monster(dir, &row, &col);
mvaddch(rogue.row, rogue.col, rogue.fchar);
refresh();

if (can_see(row, col) && ((row != rogue.row) || (col != rogue.col))) {
mvaddch(row, col, get_room_char(screen[row][col], row, col));
}
if (monster) {
wake_up(monster);
check_orc(monster);

if (!throw_at_monster(monster, weapon)) {
f = flop_weapon(weapon, row, col);
}
} else {
f = flop_weapon(weapon, row, col);
}
vanish(weapon, 1);
}

throw_at_monster(monster, weapon)
object *monster, *weapon;
{
short damage, hit_chance;
char *name_of();
short t;

hit_chance = get_hit_chance(weapon);
t = weapon->quantity;
weapon->quantity = 1;
sprintf(hit_message, "the %s", name_of(weapon));
weapon->quantity = t;

if (!rand_percent(hit_chance)) {
strcat(hit_message, "misses ");
return(0);
}
strcat(hit_message, "hit ");
damage = get_weapon_damage(weapon);
if (((weapon->which_kind == ARROW) && (rogue.weapon &&
(rogue.weapon->which_kind == BOW))) ||
((weapon->which_kind == SHURIKEN) && (rogue.weapon == weapon))) {
damage += get_weapon_damage(rogue.weapon);
damage = ((damage * 2) / 3);
}
monster_damage(monster, damage);
return(1);
}

object *get_thrown_at_monster(dir, row, col)
short dir;
short *row, *col;
{
object *object_at();
short orow, ocol;
short i;

orow = *row; ocol = *col;

for (i = 0; i < 24; i++) {
get_dir_rc(dir, row, col);
if ((screen[*row][*col] == BLANK) ||
(screen[*row][*col] & (HORWALL | VERTWALL))) {
*row = orow;
*col = ocol;
return(0);
}
if ((i != 0) && can_see(orow, ocol)) {
mvaddch(orow, ocol, get_room_char(screen[orow][ocol],
orow, ocol));
}
if (can_see(*row, *col)) {
if (!(screen[*row][*col] & MONSTER)) {
mvaddch(*row, *col, ')');
}
refresh();
}
orow = *row; ocol = *col;
if (screen[*row][*col] & MONSTER) {
if (!hiding_xeroc(*row, *col)) {
return(object_at(&level_monsters, *row, *col));
}
}
if (screen[*row][*col] & TUNNEL) {
i += 2;
}
}
return(0);
}

flop_weapon(weapon, row, col)
object *weapon;
short row, col;
{
object *new_weapon, *get_an_object();
short i, j, r, c, found = 0, inc1, inc2;
char msg[80];

inc1 = get_rand(0, 1) ? 1 : -1;
inc2 = get_rand(0, 1) ? 1 : -1;

r = row;
c = col;

if ((screen[r][c] & ~(FLOOR | TUNNEL | DOOR)) ||
((row == rogue.row) && (col == rogue.col))) {
for (i = inc1; i != (2 * -inc1); i -= inc1) {
for (j = inc2; j != (2 * -inc2); j -= inc2) {
r = row + i;
c = col + j;

if ((r > (LINES-2)) || (r < MIN_ROW) ||
(c > (COLS-1)) || (c < 0)) {
continue;
}
if (!screen[r][c]) continue;
if ((screen[r][c] & ~(FLOOR|TUNNEL|DOOR))
|| ((r == rogue.row) && (c == rogue.col))) {
continue;
}
found = 1;
goto FOUND;
}
}
} else {
found = 1;
}
FOUND: if (found) {
new_weapon = get_an_object();
*new_weapon = *weapon;
new_weapon->quantity = 1;
new_weapon->row = r;
new_weapon->col = c;
add_mask(r, c, WEAPON);
add_to_pack(new_weapon, &level_objects, 0);
if (can_see(r, c)) {
mvaddch(r, c, get_room_char(screen[r][c], r, c));
}
} else {
short t;

t = weapon->quantity;
weapon->quantity = 1;
sprintf(msg, "the %svanishes as it hits the ground",
name_of(weapon));
weapon->quantity = t;
message(msg, 0);
}
return(found);
}
SHAR_EOF
echo shar: extracting use.c
cat - << \SHAR_EOF > use.c
#include <curses.h>
#include "object.h"
#include "move.h"
#include "monster.h"
#include "room.h"

short halluc = 0;
short blind = 0;
short confused = 0;
short detect_monster = 0;

extern short being_held;

char *strange_feeling = "you have a strange feeling for a moment, then it passes";

extern char *hunger_str;
extern short current_room;
extern int level_points[];

quaff()
{
short ch, i;
object *obj, *get_letter_object();
char msg[SCOLS];

ch = get_pack_letter("quaff what? ", POTION);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("no such item.", 0);
return;
}
if (obj->what_is != POTION) {
message("you can't drink that", 0);
return;
}
switch(obj->which_kind) {
case INCREASE_STRENGTH:
message("you feel stronger now, what bulging muscles!",
0);
rogue.strength_current++;
if (rogue.strength_current > rogue.strength_max) {
rogue.strength_max = rogue.strength_current;
}
break;
case RESTORE_STRENGTH:
rogue.strength_current = rogue.strength_max;
message("this tastes great, you feel warm all over", 0);
break;
case HEALING:
message("you begin to feel better", 0);
potion_heal(0);
break;
case EXTRA_HEALING:
message("you begin to feel much better", 0);
potion_heal(1);
break;
case POISON:
rogue.strength_current -= get_rand(1, 3);
if (rogue.strength_current < 0) {
rogue.strength_current = 0;
}
message("you feel very sick now", 0);
if (halluc) {
unhallucinate();
}
break;
case RAISE_LEVEL:
add_exp((level_points[rogue.exp-1]-rogue.exp_points)+1);
break;
case BLINDNESS:
go_blind();
break;
case HALLUCINATION:
message("oh wow, everything seems so cosmic", 0);
halluc += get_rand(500, 800);
break;
case DETECT_MONSTER:
if (level_monsters.next_object) {
show_monsters();
} else {
message(strange_feeling, 0);
}
detect_monster = 1;
break;
case DETECT_OBJECTS:
if (level_objects.next_object) {
if (!blind) {
show_objects();
}
} else {
message(strange_feeling, 0);
}
break;
case CONFUSION:
message((halluc ? "what a trippy feeling" :
"you feel confused"), 0);
confuse();
break;
}
print_stats();
if (id_potions[obj->which_kind].id_status != CALLED) {
id_potions[obj->which_kind].id_status = IDENTIFIED;
}
vanish(obj, 1);
}

read_scroll()
{
short ch;
object *obj, *get_letter_object();
char msg[SCOLS];
char *get_ench_color();

ch = get_pack_letter("read what? ", SCROLL);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("no such item.", 0);
return;
}
if (obj->what_is != SCROLL) {
message("you can't read that", 0);
return;
}
switch(obj->which_kind) {
case SCARE_MONSTER:
message("you hear a maniacal laughter in the distance",
0);
break;
case HOLD_MONSTER:
hold_monster();
break;
case ENCHANT_WEAPON:
if (rogue.weapon) {
sprintf(msg, "your %sglows %sfor a moment",
id_weapons[rogue.weapon->which_kind].title,
get_ench_color());
message(msg, 0);
if (get_rand(0, 1) == 1) {
rogue.weapon->to_hit_enchantment++;
} else {
rogue.weapon->damage_enchantment++;
}
rogue.weapon->is_cursed = 0;
} else {
message("your hands tingle", 0);
}
break;
case ENCHANT_ARMOR:
if (rogue.armor) {
sprintf(msg, "your armor glows %sfor a moment",
get_ench_color());
message(msg, 0);
rogue.armor->damage_enchantment++;
rogue.armor->is_cursed = 0;
print_stats();
} else {
message("your skin crawls", 0);
}
break;
case IDENTIFY:
message("this is a scroll of identify", 0);
message("what would you like to identify?", 0);
obj->identified = 1;
id_scrolls[obj->which_kind].id_status = IDENTIFIED;
identify();
break;
case TELEPORT:
teleport();
break;
case SLEEP:
sleep_scroll();
break;
case PROTECT_ARMOR:
if (rogue.armor) {
message( "your armor is covered by a shimmering gold shield", 0);
rogue.armor->is_protected = 1;
} else {
message("your acne seems to have disappeared",
0);
}
break;
case REMOVE_CURSE:
message(
"you feel as though someone is watching over you", 0);
if (rogue.armor) {
rogue.armor->is_cursed = 0;
}
if (rogue.weapon) {
rogue.weapon->is_cursed = 0;
}
break;
case CREATE_MONSTER:
create_monster();
break;
case AGGRAVATE_MONSTER:
aggravate();
break;
}
if (id_scrolls[obj->which_kind].id_status != CALLED) {
id_scrolls[obj->which_kind].id_status = IDENTIFIED;
}
vanish(obj, 1);
}

vanish(obj, rm)
object *obj;
short rm;
{
if (obj->quantity > 1) {
obj->quantity--;
} else {
remove_from_pack(obj, &rogue.pack);
make_avail_ichar(obj->ichar);
free(obj);
}
if (rm) {
register_move();
}
}

potion_heal(extra)
{
float ratio;
short add;

ratio = ((float)rogue.hp_current) / rogue.hp_max;

if (ratio >= 0.90) {
rogue.hp_max += (extra + 1);
rogue.hp_current = rogue.hp_max;
} else {
if (ratio < 30.00) {
ratio = 30.00;
}
if (extra) {
ratio += ratio;
}
add = (short)(ratio*((float)rogue.hp_max-rogue.hp_current));
rogue.hp_current += add;
if (rogue.hp_current > rogue.hp_max) {
rogue.hp_current = rogue.hp_max;
}
}
if (blind) {
unblind();
}
if (confused && extra) {
unconfuse();
}
if (confused) {
confused = ((confused - 9) / 2);
if (confused <= 0) {
unconfuse();
}
}
if (halluc && extra) {
unhallucinate();
} else if (halluc) {
halluc = (halluc/2) + 1;
}
}

identify()
{
short ch;
object *obj, *get_letter_object();
struct identify *id_table, *get_id_table();
char description[SCOLS];
AGAIN:
ch = get_pack_letter("identify what? ", IS_OBJECT);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("no such item, try again", 0);
message("", 0);
check_message();
goto AGAIN;
}
obj->identified = 1;
if (obj->what_is & (SCROLL | POTION | WEAPON | ARMOR | WAND)) {
id_table = get_id_table(obj);
id_table[obj->which_kind].id_status = IDENTIFIED;
}
get_description(obj, description);
message(description, 0);
}

eat()
{
short ch;
short moves;
object *obj, *get_letter_object();
char msg[SCOLS];

ch = get_pack_letter("eat what? ", FOOD);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("no such item.", 0);
return;
}
if (obj->what_is != FOOD) {
message("you can't eat that", 0);
return;
}
moves = get_rand(800, 1000);

if (moves >= 900) {
message("yum, that tasted good", 0);
} else {
message("yuk, that food tasted awful", 0);
add_exp(3);
}
rogue.moves_left /= 2;
rogue.moves_left += moves;
hunger_str = "";
print_stats();

vanish(obj, 1);
}

hold_monster()
{
short i, j;
short mcount = 0;
object *monster, *object_at();
short row, col;

for (i = -2; i <= 2; i++) {
for (j = -2; j <= 2; j++) {
row = rogue.row + i;
col = rogue.col + j;
if ((row < MIN_ROW) || (row > (LINES-2)) || (col < 0) ||
(col > (COLS-1))) {
continue;
}
if (screen[row][col] & MONSTER) {
monster = object_at(&level_monsters, row, col);
monster->m_flags |= IS_ASLEEP;
monster->m_flags &= (~WAKENS);
mcount++;
}
}
}
if (mcount == 0) {
message("you feel a strange sense of loss", 0);
} else if (mcount == 1) {
message("the monster freezes", 0);
} else {
message("the monsters around you freeze", 0);
}
}

teleport()
{
if (current_room >= 0) {
darken_room(current_room);
} else {
mvaddch(rogue.row, rogue.col,
get_room_char(screen[rogue.row][rogue.col], rogue.row,
rogue.col));
}
put_player();
light_up_room();
being_held = 0;
}

hallucinate()
{
object *obj;
short ch;

if (blind) return;

obj = level_objects.next_object;

while (obj) {
ch = mvinch(obj->row, obj->col);
if (((ch < 'A') || (ch > 'Z')) &&
((obj->row != rogue.row) || (obj->col != rogue.col)))
if ((ch != ' ')&&(ch != '.')&&(ch != '#')&&(ch != '+')) {
addch(get_rand_obj_char());
}
obj = obj->next_object;
}
obj = level_monsters.next_object;

while (obj) {
ch = mvinch(obj->row, obj->col);
if ((ch >= 'A') && (ch <= 'Z')) {
addch(get_rand('A', 'Z'));
}
obj = obj->next_object;
}
}

unhallucinate()
{
halluc = 0;
if (current_room == PASSAGE) {
light_passage(rogue.row, rogue.col);
} else {
light_up_room();
}
message("everything looks SO boring now", 0);
}

unblind()
{
blind = 0;
message("the veil of darkness lifts", 0);
if (current_room == PASSAGE) {
light_passage(rogue.row, rogue.col);
} else {
light_up_room();
}
blind = 0;
if (detect_monster) {
show_monsters();
}
if (halluc) {
hallucinate();
}
}

sleep_scroll()
{
short i;

message("you fall asleep", 0);
sleep(1);
i = get_rand(4, 10);

while (i--) {
move_monsters();
}
sleep(1);
message("you can move again", 0);
}

go_blind()
{
short i, j;

if (!blind) {
message("a cloak of darkness falls around you", 0);
}
blind += get_rand(500, 800);

if (current_room >= 0) {
for (i = rooms[current_room].top_row + 1;
i < rooms[current_room].bottom_row; i++) {
for (j = rooms[current_room].left_col + 1;
j < rooms[current_room].right_col; j++) {
mvaddch(i, j, ' ');
}
}
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
refresh();
}

char *get_ench_color()
{
if (halluc) {
return(id_potions[get_rand(0, POTIONS-1)].title);
}
return("blue ");
}

confuse()
{
confused = get_rand(12, 22);
}

unconfuse()
{
char msg[80];

confused = 0;
sprintf(msg, "you feel less %s now", (halluc ? "trippy" : "confused"));
message(msg, 0);
}
SHAR_EOF
echo shar: extracting zap.c
cat - << \SHAR_EOF > zap.c
#include <curses.h>
#include "object.h"
#include "move.h"
#include "monster.h"

extern short current_room, being_held, current_level;

zapp()
{
short wch;
short first_miss = 1;
object *wand, *get_letter_object();
short dir, row, col;
object *monster, *get_zapped_monster();

while (!is_direction(dir = getchar())) {
putchar(7);
fflush(stdout);
if (first_miss) {
message("direction? ", 0);
first_miss = 0;
}
}
if (dir == CANCEL) {
check_message();
return;
}
if ((wch = get_pack_letter("zap with what?", WAND)) == CANCEL) {
check_message();
return;
}
check_message();

if (!(wand = get_letter_object(wch))) {
message("no such item.", 0);
return;
}
if (wand->what_is != WAND) {
message("you can't zap with that", 0);
return;
}
if (wand->class <= 0) {
message("nothing happens", 0);
goto RM;
} else {
wand->class--;
}
row = rogue.row; col = rogue.col;
monster = get_zapped_monster(dir, &row, &col);
if (monster != 0) {
wake_up(monster);
zap_monster(monster, wand->which_kind);
}
RM: register_move();
}

object *get_zapped_monster(dir, row, col)
short dir;
short *row, *col;
{
object *object_at();
short orow, ocol;
short i;

for (;;) {
orow = *row; ocol = *col;
get_dir_rc(dir, row, col);
if (((*row == orow) && (*col == ocol)) ||
(screen[*row][*col] & (HORWALL | VERTWALL)) ||
(screen[*row][*col] == BLANK)) {
return(0);
}
if (screen[*row][*col] & MONSTER) {
if (!hiding_xeroc(*row, *col)) {
return(object_at(&level_monsters, *row, *col));
}
}
}
}

zap_monster(monster, kind)
object *monster;
short kind;
{
short row, col;
struct object *nm;

row = monster->row;
col = monster->col;
nm = monster->next_object;

switch(kind) {
case SLOW_MONSTER:
if (monster->m_flags & HASTED) {
monster->m_flags &= (~HASTED);
} else {
monster->quiver = 0;
monster->m_flags |= SLOWED;
}
break;
case HASTE_MONSTER:
if (monster->m_flags & SLOWED) {
monster->m_flags &= (~SLOWED);
} else {
monster->m_flags |= HASTED;
}
break;
case TELEPORT_AWAY:
teleport_away(monster);
break;
case KILL_MONSTER:
rogue.exp_points -= monster->kill_exp;
monster_damage(monster, monster->quantity);
break;
case INVISIBILITY:
monster->m_flags |= IS_INVIS;
mvaddch(row, col, get_monster_char(monster));
break;
case POLYMORPH:
if (monster->ichar == 'F') {
being_held = 0;
}
MA: *monster = monster_tab[get_rand(0, MONSTERS-1)];
if ((monster->ichar == 'X') && ((current_level < XEROC1) ||
(current_level > XEROC2))) {
goto MA;
}
monster->what_is = MONSTER;
monster->row = row; monster->col = col;
monster->next_object = nm;
wake_up(monster);
if (can_see(row, col)) {
mvaddch(row, col, get_monster_char(monster));
}
break;
case PUT_TO_SLEEP:
monster->m_flags |= IS_ASLEEP;
monster->m_flags &= (~WAKENS);
break;
case DO_NOTHING:
message("nothing happens", 0);
break;
}
}

teleport_away(monster)
object *monster;
{
short row, col;

if (monster->ichar == 'F') {
being_held = 0;
}
get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT));
remove_mask(monster->row, monster->col, MONSTER);
mvaddch(monster->row, monster->col,
get_room_char(screen[monster->row][monster->col], monster->row,
monster->col));

monster->row = row; monster->col = col;
add_mask(row, col, MONSTER);

if (can_see(row, col)) {
mvaddch(row, col, get_monster_char(monster));
}
}
SHAR_EOF

0 new messages