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

Rogue clone, again(groan!), in small pieces. Part 2 of 3.

1 view
Skip to first unread message

Tim Stoehr

unread,
Mar 16, 1986, 3:34:20 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:
# monster.c # move.c # object.c # pack.c
echo shar: extracting monster.c
cat - << \SHAR_EOF > monster.c
#include <curses.h>
#include "monster.h"
#include "object.h"
#include "room.h"
#include "move.h"

extern short current_level;
extern short current_room, party_room;
extern short detect_monster;
extern short blind, halluc;

char *monster_names[] = {
"aquatar",
"bat",
"centaur",
"dragon",
"emu",
"venus fly-trap",
"griffin",
"hobgoblin",
"ice monster",
"jabberwock",
"kestrel",
"leprechaun",
"medusa",
"nymph",
"orc",
"phantom",
"quasit",
"rattlesnake",
"snake",
"troll",
"black unicorn",
"vampire",
"wraith",
"xeroc",
"yeti",
"zombie"
};

object monster_tab[MONSTERS] = {
{(IS_ASLEEP|WAKENS|WANDERS),"0d0",25,'A',20,9,18,100,0,0},
{(IS_ASLEEP|WANDERS|FLITS),"1d3",10,'B',2,1,8,60,0,0},
{(IS_ASLEEP|WANDERS),"3d3/2d5",30,'C',15,7,16,85,0,10},
{(IS_ASLEEP|WAKENS),"4d5/3d9",128,'D',5000,21,126,100,0,90},
{(IS_ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0},
{(0),"0d0",32,'F',91,12,126,80,0,0},
{(IS_ASLEEP|WAKENS|WANDERS|FLIES),"5d4/4d5",92,'G',2000,20,126,85,0,10},
{(IS_ASLEEP|WAKENS|WANDERS),"1d3/1d3",17,'H',3,1,10,67,0,0},
{(IS_ASLEEP),"0d0",15,'I',5,2,11,68,0,0},
{(IS_ASLEEP|WANDERS),"3d10/3d4",125,'J',3000,21,126,100,0,0},
{(IS_ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0},
{(IS_ASLEEP),"0d0",25,'L',18,6,16,75,0,0},
{(IS_ASLEEP|WAKENS|WANDERS),"4d4/3d7",92,'M',250,18,126,85,0,25},
{(IS_ASLEEP),"0d0",25,'N',37,10,19,75,0,100},
{(IS_ASLEEP|WANDERS|WAKENS),"1d6",25,'O',5,4,13,70,0,10},
{(IS_ASLEEP|IS_INVIS|WANDERS|FLITS),"5d4",76,'P',120,15,23,80,0,50},
{(IS_ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20},
{(IS_ASLEEP|WAKENS|WANDERS),"2d5",19,'R',10,3,12,70,0,0},
{(IS_ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0},
{(IS_ASLEEP|WAKENS|WANDERS),"4d6",64,'T',125,13,22,75,0,33},
{(IS_ASLEEP|WAKENS|WANDERS),"4d9",88,'U',200,17,26,85,0,33},
{(IS_ASLEEP|WAKENS|WANDERS),"1d14",40,'V',350,19,126,85,0,18},
{(IS_ASLEEP|WANDERS),"2d7",42,'W',55,14,23,75,0,0},
{(IS_ASLEEP),"4d6",42,'X',110,XEROC1,XEROC2,75,0,0},
{(IS_ASLEEP|WANDERS),"3d6",33,'Y',50,11,20,80,0,20},
{(IS_ASLEEP|WAKENS|WANDERS),"1d7",20,'Z',8,5,14,69,0,0}
};

object level_monsters;

put_monsters()
{
short i;
short n;
object *monster, *get_rand_monster();

n = get_rand(3, 7);

for (i = 0; i < n; i++) {
monster = get_rand_monster();
if ((monster->m_flags & WANDERS) && rand_percent(50)) {
wake_up(monster);
}
put_monster_rand_location(monster);
add_to_pack(monster, &level_monsters, 0);
}
}

object *get_rand_monster()
{
object *monster, *get_an_object();
short mn;

monster = get_an_object();

for (;;) {
mn = get_rand(0, MAXMONSTER-1);
if ((current_level >= monster_tab[mn].is_protected) &&
(current_level <= monster_tab[mn].is_cursed)) {
break;
}
}
*monster = monster_tab[mn];
monster->what_is = MONSTER;
if (monster->ichar == 'X') {
monster->identified = get_rand_obj_char();
}
if (current_level > (AMULET_LEVEL + 2)) {
monster->m_flags |= HASTED;
}
monster->trow = -1;
return(monster);
}

move_monsters()
{
object *monster;
short flew;

monster = level_monsters.next_object;

while (monster) {
if (monster->m_flags & HASTED) {
mv_monster(monster, rogue.row, rogue.col);
} else if (monster->m_flags & SLOWED) {
monster->quiver = !monster->quiver;
if (monster->quiver) {
goto NM;
}
}
flew = 0;
if ((monster->m_flags & FLIES) &&
!monster_can_go(monster, rogue.row, rogue.col)) {
flew = 1;
mv_monster(monster, rogue.row, rogue.col);
}
if (!flew || !monster_can_go(monster, rogue.row, rogue.col)) {
mv_monster(monster, rogue.row, rogue.col);
}
NM: monster = monster->next_object;
}
}

fill_room_with_monsters(rn, n)
{
short i;
short row, col;
object *monster, *get_rand_monster();

n += n/2;

for (i = 0; i < n; i++) {
if (no_room_for_monster(rn)) break;
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] & MONSTER);

monster = get_rand_monster();
put_monster_at(row, col, monster);
}
}

get_monster_char_row_col(row, col)
{
object *monster, *object_at();
short retval;

monster = object_at(&level_monsters, row, col);
if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) {
retval = get_room_char((screen[row][col] & ~MONSTER),row,col);
return(retval);
}
if ((monster->ichar == 'X') && monster->identified) {
return(monster->identified);
}
return(monster->ichar);
}

get_monster_char(monster)
object *monster;
{
short retval;

if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) {
retval = get_room_char((screen[monster->row][monster->col] & ~MONSTER), monster->row, monster->col);
return(retval);
}
if ((monster->ichar == 'X') && monster->identified) {
return(monster->identified);
}
return(monster->ichar);
}

mv_monster(monster, row, col)
register object *monster;
short row, col;
{
short i, n;
char tried[6];

if (monster->m_flags & IS_ASLEEP) {
if ((monster->m_flags & WAKENS) &&
rogue_is_around(monster->row, monster->col) &&
rand_percent(WAKE_PERCENT)) {
wake_up(monster);
}
return;
}
if ((monster->m_flags & FLITS) && flit(monster)) {
return;
}
if ((monster->ichar == 'F') &&
!monster_can_go(monster, rogue.row, rogue.col)) {
return;
}
if ((monster->ichar == 'I') && monster->identified) {
return;
}
if ((monster->ichar == 'M') && m_confuse(monster)) {
return;
}
if (monster_can_go(monster, rogue.row, rogue.col)) {
monster_hit(monster, 0);
return;
}
if ((monster->ichar == 'D') && flame_broil(monster)) {
return;
}
if ((monster->ichar == 'O') && orc_gold(monster)) {
return;
}
if ((monster->trow == monster->row) &&
(monster->tcol == monster->col)) {
monster->trow = -1;
} else if (monster->trow != -1) {
row = monster->trow;
col = monster->tcol;
}
if (monster->row > row) {
row = monster->row - 1;
} else if (monster->row < row) {
row = monster->row + 1;
}
if ((screen[row][monster->col] & DOOR) &&
mtry(monster, row, monster->col)) {
return;
}
if (monster->col > col) {
col = monster->col - 1;
} else if (monster->col < col) {
col = monster->col + 1;
}
if ((screen[monster->row][col] & DOOR) &&
mtry(monster, monster->row, col)) {
return;
}
if (mtry(monster, row, col)) {
return;
}
for (i = 0; i <= 5; i++) tried[i] = 0;

for (i = 0; i < 6; i++) {
NEXT_TRY: n = get_rand(0, 5);
switch(n) {
case 0:
if (!tried[n] && mtry(monster, row, monster->col-1)) {
return;
}
break;
case 1:
if (!tried[n] && mtry(monster, row, monster->col)) {
return;
}
break;
case 2:
if (!tried[n] && mtry(monster, row, monster->col+1)) {
return;
}
break;
case 3:
if (!tried[n] && mtry(monster, monster->row-1, col)) {
return;
}
break;
case 4:
if (!tried[n] && mtry(monster, monster->row, col)) {
return;
}
break;
case 5:
if (!tried[n] && mtry(monster, monster->row+1, col)) {
return;
}
break;
}
if (!tried[n]) {
tried[n] = 1;
} else {
goto NEXT_TRY;
}
}
}

mtry(monster, row, col)
register object *monster;
register short row, col;
{
if (monster_can_go(monster, row, col)) {
move_monster_to(monster, row, col);
return(1);
}
return(0);
}

move_monster_to(monster, row, col)
register object *monster;
register short row, col;
{
short c;

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

c = mvinch(monster->row, monster->col);

if ((c >= 'A') && (c <= 'Z')) {
mvaddch(monster->row, monster->col,
get_room_char(screen[monster->row][monster->col],
monster->row, monster->col));
}
if (!blind && (detect_monster || can_see(row, col))) {
if ((!(monster->m_flags & IS_INVIS) || detect_monster)) {
mvaddch(row, col, get_monster_char(monster));
}
}
if ((screen[row][col] & DOOR) &&
(get_room_number(row, col) != current_room) &&
(screen[monster->row][monster->col] == FLOOR)) {
if (!blind)
mvaddch(monster->row, monster->col, ' ');
}
if (screen[row][col] & DOOR) {
door_course(monster,
(screen[monster->row][monster->col] & TUNNEL),
row, col);
} else {
monster->row = row;
monster->col = col;
}
}

monster_can_go(monster, row, col)
register object *monster;
register short row, col;
{
object *obj, *object_at();
short dr, dc;

dr = monster->row - row; /* check if move distance > 1 */
if ((dr >= 2) || (dr <= -2)) return(0);
dc = monster->col - col;
if ((dc >= 2) || (dc <= -2)) return(0);

if ((!screen[monster->row][col]) || (!screen[row][monster->col])) {
return(0);
}

if ((!is_passable(row, col)) || (screen[row][col] & MONSTER)) {
return(0);
}
if ((monster->row!=row)&&(monster->col!=col)&&((screen[row][col]&DOOR)
|| (screen[monster->row][monster->col]&DOOR))) {
return(0);
}
if (!(monster->m_flags & FLITS) && !(monster->m_flags & CAN_GO) &&
(monster->trow == -1)) {
if ((monster->row < rogue.row) && (row < monster->row)) return(0);
if ((monster->row > rogue.row) && (row > monster->row)) return(0);
if ((monster->col < rogue.col) && (col < monster->col)) return(0);
if ((monster->col > rogue.col) && (col > monster->col)) return(0);
}

if (screen[row][col] & SCROLL) {
obj = object_at(&level_objects, row, col);
if (obj->which_kind == SCARE_MONSTER) {
return(0);
}
}

return(1);
}

wake_up(monster)
object *monster;
{
monster->m_flags &= (~IS_ASLEEP);
}

wake_room(rn, entering, row, col)
{
object *monster;
short wake_percent;

wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;

monster = level_monsters.next_object;

while (monster) {
if (((monster->m_flags & WAKENS) || (rn == party_room)) &&
(rn == get_room_number(monster->row, monster->col))) {
if ((monster->ichar != 'X') && (rn == party_room)) {
monster->m_flags |= WAKENS;
}
if (entering) {
monster->trow = -1;
} else {
monster->trow = row;
monster->tcol = col;
}
if (rand_percent(wake_percent) &&
(monster->m_flags & WAKENS)) {
if (monster->ichar != 'X') {
wake_up(monster);
}
}
}
monster = monster->next_object;
}
}

char *monster_name(monster)
object *monster;
{
short ch;

if (blind || ((monster->m_flags & IS_INVIS) && !detect_monster)) {
return("something");
}
if (halluc) {
ch = get_rand('A', 'Z') - 'A';
return(monster_names[ch]);
}
ch = monster->ichar - 'A';
return(monster_names[ch]);
}

rogue_is_around(row, col)
{
short rdif, cdif, retval;

rdif = row - rogue.row;
cdif = col - rogue.col;

retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
return(retval);
}

start_wanderer()
{
object *monster, *get_rand_monster();
short row, col, i;
ANOTHER:
monster = get_rand_monster();
if ((!(monster->m_flags & WAKENS)) &&
(!(monster->m_flags & WANDERS))) {
free(monster);
goto ANOTHER;
}
wake_up(monster);

for (i = 0; i < 12; i++) {
get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT));
if (!can_see(row, col)) {
put_monster_at(row, col, monster);
return;
}
}
}

show_monsters()
{
object *monster;

if (blind) return;

monster = level_monsters.next_object;

while (monster) {
mvaddch(monster->row, monster->col, monster->ichar);
if (monster->ichar == 'X') {
monster->identified = 0;
}
monster = monster->next_object;
}
}

create_monster()
{
short row, col;
short i, j, inc1, inc2;
short found = 0;
object *monster;

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

for (i = inc1; i != (2 * -inc1); i -= inc1) {
for (j = inc2; j != (2 * -inc2); j -= inc2) {
if (!i && !j) continue;
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)) &&
(screen[row][col] & (FLOOR|TUNNEL|STAIRS))) {
found = 1;
goto FOUND;
}
}
}
FOUND:
if (found) {
monster = get_rand_monster();
put_monster_at(row, col, monster);
mvaddch(row, col, get_monster_char(monster));
if (monster->m_flags & WANDERS) {
wake_up(monster);
}
} else {
message("you hear a faint cry of anguish in the distance",0);
}
}

put_monster_at(row, col, monster)
object *monster;
{
monster->row = row; monster->col = col;
add_mask(row, col, MONSTER);
add_to_pack(monster, &level_monsters, 0);
}

can_see(row, col)
{
short retval;

retval = !blind && ((get_room_number(row, col) == current_room) ||
(rogue_is_around(row, col)));

return(retval);
}

flit(monster)
object *monster;
{
short inc1, inc2;
short i, j, row, col;

if (!rand_percent(FLIT_PERCENT)) {
return(0);
}
inc1 = get_rand(0, 1) ? 1 : -1;
inc2 = get_rand(0, 1) ? 1 : -1;

if (rand_percent(10)) {
return(1);
}
for (i = inc1; i != (2*(0-inc1)); i+=(0-inc1)) {
for (j = inc2; j != (2*(0-inc2)); j+=(0-inc2)) {

row = monster->row + i;
col = monster->col + j;
if ((row == rogue.row) && (col == rogue.col)) {
continue;
}

if (mtry(monster, row, col)) {
return(1);
}
}
}
return(1);
}

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

get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT));
add_mask(row, col, MONSTER);
monster->row = row;
monster->col = col;

}

get_rand_obj_char()
{
short r;
char *rs = "%!?]/):*";

r = get_rand(0, 7);

return(rs[r]);
}

no_room_for_monster(rn)
{
short i, j;

for (i = rooms[rn].left_col+1; i < rooms[rn].right_col; i++) {
for (j = rooms[rn].top_row+1; j < rooms[rn].bottom_row; j++) {
if (!(screen[i][j] & MONSTER)) {
return(0);
}
}
}
return(1);
}

aggravate()
{
struct object *monster;

message("you hear a high pitched humming noise");

monster = level_monsters.next_object;

while (monster) {
wake_up(monster);
if (monster->ichar == 'X') {
monster->identified = 0;
}
monster = monster->next_object;
}
}

monster_can_see(monster, row, col)
object *monster;
{
short rn, rdif, cdif, retval;

rn = get_room_number(row, col);

if ((rn != NO_ROOM) && (rn ==
get_room_number(monster->row, monster->col))) {
return(1);
}
rdif = row - monster->row;
cdif = col - monster->col;

retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
return(retval);
}

mv_aquatars()
{
object *monster;

monster = level_monsters.next_object;

while (monster) {
if (monster->ichar == 'A') {
mv_monster(monster, rogue.row, rogue.col);
}
monster = monster->next_object;
}
}
SHAR_EOF
echo shar: extracting move.c
cat - << \SHAR_EOF > move.c
#include <curses.h>
#include "object.h"
#include "room.h"
#include "move.h"
#include "monster.h"

extern short current_room, halluc, detect_monster, blind, being_held;
extern short confused, interrupted, has_amulet;
extern char *hunger_str;

single_move_rogue(dirch, pickup)
{
short row, col;
object *obj, *object_at(), *pick_up();
char description[SCOLS];
short n, status;

row = rogue.row;
col = rogue.col;

if (being_held) {
get_dir_rc(dirch, &row, &col);

if (!(screen[row][col] & MONSTER)) {
message("you are being held", 1);
return(MOVE_FAILED);
}
}
row = rogue.row;
col = rogue.col;

if (confused) {
dirch = get_rand_dir();
}

switch(dirch) {
case 'h':
col--;
break;
case 'j':
row++;
break;
case 'k':
row--;
break;
case 'l':
col++;
break;
case 'b':
col--;
row++;
break;
case 'y':
col--;
row--;
break;
case 'u':
col++;
row--;
break;
case 'n':
col++;
row++;
break;
}
if (screen[row][col] & MONSTER) {
rogue_hit(object_at(&level_monsters, row, col));
register_move();
return(MOVE_FAILED);
}
if (!can_move(rogue.row, rogue.col, row, col)) {
return(MOVE_FAILED);
}
if (screen[row][col] & DOOR) {
if (current_room == PASSAGE) {
current_room = get_room_number(row, col);
light_up_room();
wake_room(current_room, 1, row, col);
} else {
light_passage(row, col);
}
} else if ((screen[rogue.row][rogue.col] & DOOR) &&
(screen[row][col] & TUNNEL)) {
light_passage(row, col);
wake_room(current_room, 0, row, col);
darken_room(current_room);
current_room = PASSAGE;
} else if (screen[row][col] & TUNNEL) {
light_passage(row, col);
}
mvaddch(rogue.row, rogue.col,
get_room_char(screen[rogue.row][rogue.col], rogue.row, rogue.col));
mvaddch(row, col, rogue.fchar);
rogue.row = row; rogue.col = col;
if (screen[row][col] & CAN_PICK_UP) {
if (pickup) {
if (obj = pick_up(row, col, &status)) {
get_description(obj, description);
if (obj->what_is == GOLD) {
free(obj);
goto NOT_IN_PACK;
}
} else if (!status) {
goto MVED;
} else {
goto MOVE_ON;
}
} else {
MOVE_ON: obj = object_at(&level_objects, row, col);
strcpy(description, "moved onto ");
get_description(obj, description+11);
goto NOT_IN_PACK;
}
n = strlen(description);
description[n] = '(';
description[n+1] = obj->ichar;
description[n+2] = ')';
description[n+3] = 0;
NOT_IN_PACK: message(description, 1);
register_move();
return(STOPPED_ON_SOMETHING);
}
if ((screen[row][col] & DOOR) || (screen[row][col] & STAIRS)) {
register_move();
return(STOPPED_ON_SOMETHING);
}
MVED: if (register_move()) { /* fainted from hunger */
return(STOPPED_ON_SOMETHING);
}
return((confused ? STOPPED_ON_SOMETHING : MOVED));
}

multiple_move_rogue(dirch)
{
short row, col;
short m;

switch(dirch) {
case '\010':
case '\012':
case '\013':
case '\014':
case '\031':
case '\025':
case '\016':
case '\002':
do {
row = rogue.row;
col = rogue.col;
if (((m = single_move_rogue((dirch + 96), 1)) ==
MOVE_FAILED) || (m == STOPPED_ON_SOMETHING) ||
interrupted) {
break;
}
} while (!next_to_something(row, col));
break;
case 'H':
case 'J':
case 'K':
case 'L':
case 'B':
case 'Y':
case 'U':
case 'N':
while (!interrupted &&
single_move_rogue((dirch + 32), 1) == MOVED) ;
break;
}
}

is_passable(row, col)
{
if ((row < MIN_ROW) || (row > (LINES - 2)) || (col < 0) ||
(col > (COLS-1))) {
return(0);
}
return(screen[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS));
}

next_to_something(drow, dcol)
{
short i, j, i_end, j_end, row, col;
short pass_count = 0;

if (confused) {
return(1);
}
if (blind) {
return(0);
}
i_end = (rogue.row < (LINES-2)) ? 1 : 0;
j_end = (rogue.col < (COLS-1)) ? 1 : 0;

for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
if ((i == 0) && (j == 0)) continue;
if (((rogue.row+i)==drow)&&((rogue.col+j)==dcol)) {
continue;
}
if(screen[rogue.row+i][rogue.col+j]&(MONSTER|IS_OBJECT))return(1);
if ((((i - j) == 1) || ((i - j) == -1)) &&
(screen[rogue.row+i][rogue.col+j] & TUNNEL)) {
if (++pass_count > 1) {
return(1);
}
}
row = rogue.row+i; col = rogue.col+j;
if ((screen[row][col] & DOOR)||(is_object(row,col))) {
if (i == 0 || j == 0) {
return(1);
}
}
}
}
return(0);
}

can_move(row1, col1, row2, col2)
{
if (!is_passable(row2, col2)) {
return(0);
}
if ((row1 != row2) && (col1 != col2)) {
if ((screen[row1][col1]&DOOR)||(screen[row2][col2]&DOOR)) {
return(0);
}
if ((!screen[row1][col2]) || (!screen[row2][col1])) {
return(0);
}
}
return(1);
}

is_object(row, col)
{
return(screen[row][col] & IS_OBJECT);
}

move_onto()
{
short ch;
short first_miss = 1;

while (!is_direction(ch = getchar())) {
putchar(7);
fflush(stdout);
if (first_miss) {
message("direction? ", 0);
first_miss = 0;
}
}
check_message();
if (ch != CANCEL) {
single_move_rogue(ch, 0);
}
}

is_direction(c)
{
return( (c == 'h') ||
(c == 'j') ||
(c == 'k') ||
(c == 'l') ||
(c == 'b') ||
(c == 'y') ||
(c == 'u') ||
(c == 'n') ||
(c == CANCEL)
);
}

is_pack_letter(c)
{
return(((c >= 'a') && (c <= 'z')) || (c == CANCEL) || (c == LIST));
}

check_hunger()
{
short i, n;
short fainted = 0;

if (rogue.moves_left == HUNGRY) {
hunger_str = "hungry";
message(hunger_str, 0);
print_stats();
}
if (rogue.moves_left == WEAK) {
hunger_str = "weak";
message(hunger_str, 0);
print_stats();
}
if ((rogue.moves_left) <= FAINT) {
if (rogue.moves_left == FAINT) {
hunger_str = "faint";
message(hunger_str, 1);
print_stats();
}
n = get_rand(0, (FAINT - rogue.moves_left));
if (n > 0) {
fainted = 1;
if (rand_percent(40)) rogue.moves_left++;
message("you faint", 1);
for (i = 0; i < n; i++) {
if (rand_percent(50)) {
move_monsters();
}
}
message("you can move again", 1);
}
}
if (rogue.moves_left <= STARVE) {
killed_by(0, STARVATION);
}
rogue.moves_left--;
return(fainted);
}

register_move()
{
static short moves = 0;
short fainted;

if ((rogue.moves_left <= HUNGRY) || !has_amulet) {
fainted = check_hunger();
} else {
fainted = 0;
}

move_monsters();

if (++moves >= 80) {
moves = 0;
start_wanderer();
}
if (halluc) {
if (!(--halluc)) {
unhallucinate();
} else {
hallucinate();
}
}
if (blind) {
if (!(--blind)) {
unblind();
}
}
if (confused) {
if (!(--confused)) {
unconfuse();
}
}
heal();

return(fainted);
}

rest(count)
{
int i;

for (i = 0; i < count; i++) {
if (interrupted) break;
register_move();
}
}

get_rand_dir()
{
short d;

d = get_rand(1, 8);

switch(d) {
case 1:
return('j');
case 2:
return('k');
case 3:
return('l');
case 4:
return('h');
case 5:
return('y');
case 6:
return('u');
case 7:
return('b');
case 8:
return('n');
}
}

heal()
{
static short exp = -1, n, c = 0;

if (rogue.exp != exp) {
exp = rogue.exp;

switch(exp) {
case 1:
n = 20;
break;
case 2:
n = 18;
break;
case 3:
n = 17;
break;
case 4:
n = 14;
break;
case 5:
n = 13;
break;
case 6:
n = 10;
break;
case 7:
n = 9;
break;
case 8:
n = 8;
break;
case 9:
n = 7;
break;
case 10:
n = 4;
break;
case 11:
n = 3;
break;
case 12:
default:
n = 2;
}
}
if (rogue.hp_current == rogue.hp_max) {
c = 0;
return;
}

if (++c >= n) {
c = 0;
rogue.hp_current++;
if (rogue.hp_current < rogue.hp_max) {
if (rand_percent(50)) {
rogue.hp_current++;
}
}
print_stats();
}
}
SHAR_EOF
echo shar: extracting object.c
cat - << \SHAR_EOF > object.c
#include <curses.h>
#include "object.h"
#include "room.h"

object level_objects;
unsigned short screen[SROWS][SCOLS];

extern short current_level, max_level;
extern short party_room;

short has_amulet = 0;
short foods = 0;

fighter rogue = {
0, 0, /* armor, weapon */
12, 12, /* Hp */
16, 16, /* Str */
{0}, /* pack */
0, /* gold */
1, 0, /* exp, exp_points */
0, 0, /* row, col */
'@', /* char */
1200 /* moves */
};

struct identify id_potions[POTIONS] = {
{100, "blue \0 ", "of increase strength ",0},
{250, "red \0 ", "of restore strength ",0},
{100, "green \0 ", "of healing ",0},
{200, "grey \0 ", "of extra healing ",0},
{10, "brown \0 ", "of poison ",0},
{300, "clear \0 ", "of raise level ",0},
{10, "pink \0 ", "of blindness ",0},
{25, "white \0 ", "of hallucination ",0},
{100, "purple \0 ", "of detect monster ",0},
{100, "black \0 ", "of detect things ",0},
{10, "yellow \0 ", "of confusion ",0}
};

struct identify id_scrolls[SCROLLS] = {
{505, " ", "of protect armor ", 0},
{200, " ", "of hold monster ", 0},
{235, " ", "of enchant weapon ", 0},
{235, " ", "of enchant armor ", 0},
{175, " ", "of identify ", 0},
{190, " ", "of teleportation ", 0},
{25, " ", "of sleep ", 0},
{610, " ", "of scare monster ", 0},
{210, " ", "of remove curse ", 0},
{100, " ", "of create monster ",0},
{25, " ", "of aggravate monster ",0}
};

struct identify id_weapons[WEAPONS] = {
{150, "short bow ", "", 0},
{15, "arrows ", "", 0},
{35, "shurikens ", "", 0},
{370, "mace ", "", 0},
{480, "long sword ", "", 0},
{590, "two-handed sword ", "", 0}
};

struct identify id_armors[ARMORS] = {
{300, "leather armor ", "", (UNIDENTIFIED)},
{300, "ring mail ", "", (UNIDENTIFIED)},
{400, "scale mail ", "", (UNIDENTIFIED)},
{500, "chain mail ", "", (UNIDENTIFIED)},
{600, "banded mail ", "", (UNIDENTIFIED)},
{600, "splint mail ", "", (UNIDENTIFIED)},
{700, "plate mail ", "", (UNIDENTIFIED)}
};

struct identify id_wands[WANDS] = {
{25, " ", "of teleport away ",0},
{50, " ", "of slow monster ", 0},
{45, " ", "of kill monster ",0},
{8, " ", "of invisibility ",0},
{55, " ", "of polymorph ",0},
{2, " ", "of haste monster ",0},
{25, " ", "of put to sleep ",0},
{0, " ", "of do nothing ",0}
};

put_objects()
{
short row, col, i, n;
char *malloc();
object *obj, *get_rand_object();

if (current_level < max_level) return;

n = get_rand(2, 4);
if (rand_percent(35)) n++;

if (rand_percent(50)) {
strcpy(id_weapons[SHURIKEN].title, "daggers ");
}
if (rand_percent(5)) {
make_party();
}
for (i = 0; i < n; i++) {
obj = get_rand_object();
put_object_rand_location(obj);
add_to_pack(obj, &level_objects, 0);
}
put_gold();
}

put_gold()
{
short i, j;
short row,col;
object *obj, *get_an_object();

for (i = 0; i < MAXROOMS; i++) {
if (rooms[i].is_room && rand_percent(GOLD_PERCENT)) {
for (j = 0; j < 25; j++) {
row = get_rand(rooms[i].top_row+1,
rooms[i].bottom_row-1);
col = get_rand(rooms[i].left_col+1,
rooms[i].right_col-1);
if ((screen[row][col] == FLOOR) ||
(screen[row][col] == PASSAGE)) {
put_gold_at(row, col);
break;
}
}
continue;
}
}
}

put_gold_at(row, col)
{
object *obj;

obj = get_an_object();
obj->row = row; obj->col = col;
obj->what_is = GOLD;
obj->quantity = get_rand((2*current_level), (16*current_level));
add_mask(row, col, GOLD);
add_to_pack(obj, &level_objects, 0);
}

put_object_at(obj, row, col)
object *obj;
{
obj->row = row;
obj->col = col;
add_mask(row, col, obj->what_is);
add_to_pack(obj, &level_objects, 0);
}

object *object_at(pack, row, col)
object *pack;
{
object *obj;

obj = pack->next_object;

while (obj && (obj->row != row) || (obj->col != col)) {
obj = obj->next_object;
}
return(obj);
}

object *get_letter_object(ch)
{
object *obj;

obj = rogue.pack.next_object;

while (obj && (obj->ichar != ch)) {
obj = obj->next_object;
}
return(obj);
}

free_stuff(objlist)
object *objlist;
{
object *obj;

while (objlist->next_object) {
obj = objlist->next_object;
objlist->next_object =
objlist->next_object->next_object;
free(obj);
}
}

char *name_of(obj)
object *obj;
{
char *retstring;

switch(obj->what_is) {
case SCROLL:
retstring = obj->quantity > 1 ? "scrolls " : "scroll ";
break;
case POTION:
retstring = obj->quantity > 1 ? "potions " : "potion ";
break;
case FOOD:
retstring = obj->quantity > 1 ? "rations " : "ration ";
break;
case WAND:
retstring = "wand ";
break;
case WEAPON:
switch(obj->which_kind) {
case ARROW:
retstring=obj->quantity > 1 ? "arrows " : "arrow ";
break;
case SHURIKEN:
if (id_weapons[SHURIKEN].title[0] == 'd') {
retstring=obj->quantity > 1 ? "daggers " : "dagger ";
} else {
retstring=obj->quantity > 1?"shurikens ":"shuriken ";
}
break;
default:
retstring = id_weapons[obj->which_kind].title;
}
break;
default:
retstring = "unknown ";
break;
}
return(retstring);
}

object *get_rand_object()
{
object *obj, *get_an_object();

obj = get_an_object();

if (foods < (current_level/2)) {
obj->what_is = FOOD;
} else {
obj->what_is = get_rand_what_is();
}
obj->identified = 0;

switch(obj->what_is) {
case SCROLL:
get_rand_scroll(obj);
break;
case POTION:
get_rand_potion(obj);
break;
case WEAPON:
get_rand_weapon(obj);
break;
case ARMOR:
get_rand_armor(obj);
break;
case WAND:
get_rand_wand(obj);
break;
case FOOD:
foods++;
get_food(obj);
break;
}
return(obj);
}

get_rand_what_is()
{
short percent;
short what_is;

percent = get_rand(1, 92);

if (percent <= 30) {
what_is = SCROLL;
} else if (percent <= 60) {
what_is = POTION;
} else if (percent <= 65) {
what_is = WAND;
} else if (percent <= 75) {
what_is = WEAPON;
} else if (percent <= 85) {
what_is = ARMOR;
} else {
what_is = FOOD;
}
return(what_is);
}

get_rand_scroll(obj)
object *obj;
{
short percent;

percent = get_rand(0, 82);

if (percent <= 5) {
obj->which_kind = PROTECT_ARMOR;
} else if (percent <= 11) {
obj->which_kind = HOLD_MONSTER;
} else if (percent <= 20) {
obj->which_kind = CREATE_MONSTER;
} else if (percent <= 35) {
obj->which_kind = IDENTIFY;
} else if (percent <= 43) {
obj->which_kind = TELEPORT;
} else if (percent <= 52) {
obj->which_kind = SLEEP;
} else if (percent <= 57) {
obj->which_kind = SCARE_MONSTER;
} else if (percent <= 66) {
obj->which_kind = REMOVE_CURSE;
} else if (percent <= 71) {
obj->which_kind = ENCHANT_ARMOR;
} else if (percent <= 76) {
obj->which_kind = ENCHANT_WEAPON;
} else {
obj->which_kind = AGGRAVATE_MONSTER;
}
}

get_rand_potion(obj)
object *obj;
{
short percent;

percent = get_rand(1, 105);

if (percent <= 5) {
obj->which_kind = RAISE_LEVEL;
} else if (percent <= 15) {
obj->which_kind = DETECT_OBJECTS;
} else if (percent <= 25) {
obj->which_kind = DETECT_MONSTER;
} else if (percent <= 35) {
obj->which_kind = INCREASE_STRENGTH;
} else if (percent <= 45) {
obj->which_kind = RESTORE_STRENGTH;
} else if (percent <= 55) {
obj->which_kind = HEALING;
} else if (percent <= 65) {
obj->which_kind = EXTRA_HEALING;
} else if (percent <= 75) {
obj->which_kind = BLINDNESS;
} else if (percent <= 85) {
obj->which_kind = HALLUCINATION;
} else if (percent <= 95) {
obj->which_kind = CONFUSION;
} else {
obj->which_kind = POISON;
}
}

get_rand_weapon(obj)
object *obj;
{
short percent;
short i;
short blessing, cursed, increment;

obj->which_kind = get_rand(0, (WEAPONS-1));

if ((obj->which_kind == ARROW) || (obj->which_kind == SHURIKEN)) {
obj->quantity = get_rand(3, 15);
obj->quiver = get_rand(0, 126);
} else {
obj->quantity = 1;
}
obj->identified = 0;
obj->to_hit_enchantment = obj->damage_enchantment = 0;
get_weapon_thd(obj);

/* notice, long swords are ALWAYS cursed or blessed */

percent = get_rand(1, ((obj->which_kind == LONG_SWORD) ? 32 : 96));
blessing = get_rand(1, 3);
obj->is_cursed = 0;

if (percent <= 16) {
increment = 1;
} else if (percent <= 32) {
increment = -1;
obj->is_cursed = 1;
}
if (percent <= 32) {
for (i = 0; i < blessing; i++) {
if (rand_percent(50)) {
obj->to_hit_enchantment += increment;
} else {
obj->damage_enchantment += increment;
}
}
}
switch(obj->which_kind) {
case BOW:
obj->damage = "1d2";
break;
case ARROW:
obj->damage = "1d2";
break;
case SHURIKEN:
obj->damage = "1d4";
break;
case MACE:
obj->damage = "2d3";
break;
case LONG_SWORD:
obj->damage = "3d4";
break;
case TWO_HANDED_SWORD:
obj->damage = "4d5";
break;
}
}

get_rand_armor(obj)
object *obj;
{
short percent;
short blessing;

obj->which_kind = get_rand(0, (ARMORS-1));
obj->class = obj->which_kind + 2;
if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) {
obj->class--;
}
obj->is_cursed = 0;
obj->is_protected = 0;
obj->damage_enchantment = 0;

percent = get_rand(1, 100);
blessing = get_rand(1, 3);

if (percent <= 16) {
obj->is_cursed = 1;
obj->damage_enchantment -= blessing;
} else if (percent <= 33) {
obj->damage_enchantment += blessing;
}
}

get_rand_wand(obj)
object *obj;
{
obj->which_kind = get_rand(0, (WANDS-1));
obj->class = get_rand(3, 7);
}

get_food(obj)
object *obj;
{
obj->which_kind = obj->what_is = FOOD;
}

put_stairs()
{
short row, col;

get_rand_row_col(&row, &col, (FLOOR | TUNNEL));
screen[row][col] = STAIRS;
}

get_weapon_thd(obj)
object *obj;
{
switch(obj->which_kind) {
case BOW:
break;
case ARROW:
break;
case SHURIKEN:
break;
case MACE:
break;
case LONG_SWORD:
break;
case TWO_HANDED_SWORD:
break;
}
}

get_armor_class(obj)
object *obj;
{
if (obj) {
return(obj->class + obj->damage_enchantment);
}
return(0);
}

object *get_an_object()
{
object *obj;
char *malloc();

if (!(obj = (object *) malloc(sizeof(object)))) {
clean_up("Cannot allocate item");
}
obj->quantity = 1;
obj->ichar = 'L';
obj->picked_up = 0; /* not picked up yet */
return(obj);
}

make_party()
{
object *obj;
short n;

party_room = get_rand_room();
n = fill_room_with_objects(party_room);
fill_room_with_monsters(party_room, n);
}

show_objects()
{
object *obj;

obj = level_objects.next_object;

while (obj) {
mvaddch(obj->row, obj->col, get_room_char(obj->what_is));
obj = obj->next_object;
}
}

put_amulet()
{
short row, col;
object *obj, *get_an_object();

obj = get_an_object();
obj->what_is = AMULET;
put_object_rand_location(obj);
add_to_pack(obj, &level_objects, 0);
}

put_object_rand_location(obj)
object *obj;
{
short row, col;

get_rand_row_col(&row, &col, (FLOOR | TUNNEL));
add_mask(row, col, obj->what_is);
obj->row = row;
obj->col = col;

}
SHAR_EOF
echo shar: extracting pack.c
cat - << \SHAR_EOF > pack.c
#include <curses.h>
#include "move.h"
#include "object.h"

char *CURSE_MESSAGE = "you can't, it appears to be cursed";
char ichars[26];

extern short has_amulet;

object *add_to_pack(obj, pack, condense)
object *obj, *pack;
{
object *op, *check_duplicate();

if (condense) {
if (op = check_duplicate(obj, pack)) {
free(obj);
return(op);
} else {
obj->ichar = next_avail_ichar();
}
}

if (pack->next_object == 0) {
pack->next_object = obj;
} else {
op = pack->next_object;

while (op->next_object) {
op = op->next_object;
}
op->next_object = obj;
}
obj->next_object = 0;
return(obj);
}

remove_from_pack(obj, pack)
object *obj, *pack;
{
while (pack->next_object != obj) {
pack = pack->next_object;
}
pack->next_object = pack->next_object->next_object;
}

object *pick_up(row, col, status)
short *status;
{
object *obj, *object_at(), *add_to_pack();

obj = object_at(&level_objects, row, col);
*status = 1;

if ((obj->what_is == SCROLL) && (obj->which_kind == SCARE_MONSTER) &&
(obj->picked_up > 0)) {
message("the scroll turns to dust as you pick it up", 1);
remove_from_pack(obj, &level_objects);
remove_mask(row, col, SCROLL);
free(obj);
*status = 0;
if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) {
id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED;
}
return(0);
}
if (obj->what_is == GOLD) {
rogue.gold += obj->quantity;
remove_mask(row, col, GOLD);
remove_from_pack(obj, &level_objects);
print_stats();
return(obj); /* obj will be free()ed in single_move() */
}
if (get_pack_count(obj) >= MAX_PACK_COUNT) {
message("Pack too full", 1);
return(0);
}
if (obj->what_is == AMULET) {
has_amulet = 1;
}

remove_mask(row, col, obj->what_is);
remove_from_pack(obj, &level_objects);
obj = add_to_pack(obj, &rogue.pack, 1);
obj->picked_up++;
return(obj);
}

drop()
{
object *obj, *get_letter_object(), *new;
short ch;
object *get_an_object();
char description[SCOLS];

if (screen[rogue.row][rogue.col] & IS_OBJECT) {
message("There's already something there", 0);
return;
}
if (!rogue.pack.next_object) {
message("You have nothing to drop", 0);
return;
}
ch = get_pack_letter("drop what? ", IS_OBJECT);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("No such item.", 0);
return;
}
if (obj == rogue.weapon) {
if (obj->is_cursed) {
message(CURSE_MESSAGE, 0);
return;
}
rogue.weapon = 0;
} else if (obj == rogue.armor) {
if (obj->is_cursed) {
message(CURSE_MESSAGE, 0);
return;
}
rogue.armor = 0;
print_stats();
}
obj->row = rogue.row;
obj->col = rogue.col;

if ((obj->quantity > 1) && (obj->what_is != WEAPON)) {
obj->quantity--;
new = get_an_object();
*new = *obj;
new->quantity = 1;
obj = new;
goto ADD;
}
if (obj->what_is == AMULET) {
has_amulet = 0;
}
make_avail_ichar(obj->ichar);
remove_from_pack(obj, &rogue.pack);
ADD: add_to_pack(obj, &level_objects, 0);
add_mask(rogue.row, rogue.col, obj->what_is);
strcpy(description, "dropped ");
get_description(obj, description+8);
message(description, 0);
register_move();
}

object *check_duplicate(obj, pack)
object *obj, *pack;
{
object *op;

if (!(obj->what_is & (WEAPON | FOOD | SCROLL | POTION))) {
return(0);
}
op = pack->next_object;

while (op) {
if ((op->what_is == obj->what_is) &&
(op->which_kind == obj->which_kind)) {

if ((obj->what_is != WEAPON) ||
((obj->what_is == WEAPON) &&
((obj->which_kind == ARROW) ||
(obj->which_kind == SHURIKEN)) &&
(obj->quiver == op->quiver))) {
op->quantity += obj->quantity;
return(op);
}
}
op = op->next_object;
}
return(0);
}

next_avail_ichar()
{
short i;

for (i = 'a'; i < 'z'; i++) {
if (!ichars[i-'a']) {
ichars[i-'a'] = 1;
return(i);
}
}
return(0);
}

make_avail_ichar(ch)
{
ichars[ch - 'a'] = 0;
}

wait_for_ack(prompt)
{
if (prompt) {
printf("%s ", MORE);
fflush(stdout);
}
while (getchar() != ' ') ;
}

get_pack_letter(prompt, mask)
char *prompt;
unsigned short mask;
{
short first_miss = 1;
short ch;

message(prompt, 0);

while (!is_pack_letter(ch = getchar())) {
putchar(7);
fflush(stdout);
if (first_miss) {
WHICH: message(prompt, 0);
first_miss = 0;
}
}
if (ch == LIST) {
check_message();
inventory(&rogue.pack, mask);
goto WHICH;
}
check_message();
return(ch);
}

take_off()
{
char description[SCOLS];
object *obj;

if (rogue.armor) {
if (rogue.armor->is_cursed) {
message(CURSE_MESSAGE, 0);
} else {
mv_aquatars();
obj = rogue.armor;
rogue.armor = 0;
strcpy(description, "was wearing ");
get_description(obj, description+12);
message(description, 0);
print_stats();
register_move();
}
} else {
message("not wearing any", 0);
}
}

wear()
{
short ch;
register object *obj;
char description[SCOLS];

if (rogue.armor) {
message("your already wearing some", 0);
return;
}
ch = get_pack_letter("wear what? ", ARMOR);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("No such item.", 0);
return;
}
if (obj->what_is != ARMOR) {
message("You can't wear that", 0);
return;
}
rogue.armor = obj;
obj->identified = 1;
get_description(obj, description);
message(description, 0);
print_stats();
register_move();
}

wield()
{
short ch;
register object *obj;
char description[SCOLS];

if (rogue.weapon && rogue.weapon->is_cursed) {
message(CURSE_MESSAGE, 0);
return;
}
ch = get_pack_letter("wield what? ", WEAPON);

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("No such item.", 0);
return;
}
if (obj->what_is != WEAPON) {
message("You can't wield that", 0);
return;
}
if (obj == rogue.weapon) {
message("in use", 0);
} else {
rogue.weapon = obj;
get_description(obj, description);
message(description, 0);
register_move();
}
}

call_it()
{
short ch;
register object *obj;
struct identify *id_table, *get_id_table();
char buf[MAX_TITLE_LENGTH+2];

ch = get_pack_letter("call what? ", (SCROLL | POTION | WAND));

if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
message("No such item.", 0);
return;
}
if (!(obj->what_is & (SCROLL | POTION | WAND))) {
message("surely you already know what that's called", 0);
return;
}
id_table = get_id_table(obj);

if (get_input_line(buf, id_table[obj->which_kind].title)) {
id_table[obj->which_kind].id_status = CALLED;
strcpy(id_table[obj->which_kind].title, buf);
}
}

get_pack_count(new_obj)
object *new_obj;
{
object *obj;
short count = 0;

if (!(obj = rogue.pack.next_object)) {
return(0);
}
while (obj) {
if (obj->what_is != WEAPON) {
count += obj->quantity;
} else {
if ((new_obj->what_is != WEAPON) ||
((obj->which_kind != ARROW) &&
(obj->which_kind != SHURIKEN)) ||
(new_obj->which_kind != obj->which_kind) ||
(obj->quiver != new_obj->quiver)) {
count++;
}
}
obj = obj->next_object;
}
return(count);
}
SHAR_EOF

0 new messages