1
0
Fork 0

too proprietary

This commit is contained in:
dtb 2023-12-20 22:55:44 -07:00
parent 745c653366
commit a75414eb17
27 changed files with 0 additions and 11551 deletions

View File

@ -1,62 +0,0 @@
$NetBSD: CHANGES,v 1.4 2021/09/19 10:34:07 andvar Exp $
From: tektronix!zeus.TEK.COM!tims@ucbvax.Berkeley.EDU
Date: 30 Nov 87 15:08:15 PST (Mon)
To: okeeffe.Berkeley.EDU!mckusick@ucbvax.Berkeley.EDU (Kirk McKusick)
Subject: Re: Public domain rogue
Return-Path: tektronix!zeus.TEK.COM!tims@ucbvax.Berkeley.EDU
Here is a list of discrepancies from the documentation you sent me:
The -d option not implemented.
The -r option not implemented, use "rogue save_file" instead.
Strength is between 1 and 99, not 3 and 32.
The D command is not implemented.
Only scrolls,potions,wands,and rings may be "call"ed something.
The ^P command may be used to go 4 messages back, instead of just 1.
The @ command is not implemented.
There are no dark rooms.
ROGUEOPTS of flush,terse,seefloor,askme,inventory are ignored.
'askquit' is added to prevent ^\ from terminating the game accidentally.
If 'noaskquit' is
found in the ROGUEOPTS string, the ^\ kills the game, otherwise,
the player is asked if he really wants to quit. In either case, no
score file processing is attempted.
The score is keyed to winning scores, and no player may appear twice.
Other differences from "standard" rogue 5.3. This list covers externally
visible differences only.
There should be NO bugs with any severe consequences. Absolutely NO
game-stopping, or game-winning bugs should be present.
Traps fail occasionally, that is, they sometimes are sprung but miss.
The ^A command prints out some stuff you're probably not interested in.
The '&' command silently saves your screen into the file 'rogue.screen'
Any inventory selection command that takes '*' as a request to list all
appropriate items, can take one of "=?:)]!/" to list only rings,
scrolls, or whatever.
Scrolls and potions, once used, become identified. All other objects become
identified only by scroll of identification.
There is only one scroll of identification, and it works on any item.
ROGUEOPTS
Only the following are implemented:
file,jump,name,askquit,tombstone,passgo
"askquit" is used to prevent accidental termination of the game via ^\
You may drop objects in doorways.
Prints a picture of a skull, not a tombstone, upon death.
The save/restore game function is faster and machine-independent, but sometimes
requires modification when new variables are added to the source.
The potion of detect monster lasts for the whole level.
Their is no wand of light.
Some things are broken after porting to POSIX-ish.

View File

@ -1,17 +0,0 @@
SCOREFILE = \"/var/games/rogue.scores\"
SCREENDUMP = \"rogue.screen\"
CFLAGS += -D_PATH_SCOREFILE=$(SCOREFILE) -D_PATH_SCREENDUMP=$(SCREENDUMP)
CFLAGS += -lcurses
OBJ = hit.o init.o inventory.o level.o machdep.o main.o message.o monster.o \
move.o object.o pack.o play.o ring.o room.o save.o score.o spec_hit.o \
throw.o trap.o use.o zap.o
rogue: $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
clean:
rm -f $(OBJ) rogue
.PHONY: clean

View File

@ -1,443 +0,0 @@
/* $NetBSD: hit.c,v 1.10 2008/01/14 03:50:01 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* hit.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
static int damage_for_strength(void);
static int get_w_damage(const object *);
static int to_hit(const object *);
static object *fight_monster = NULL;
char hit_message[HIT_MESSAGE_SIZE] = "";
void
mon_hit(object *monster)
{
short damage, hit_chance;
const char *mn;
float minus;
if (fight_monster && (monster != fight_monster)) {
fight_monster = 0;
}
monster->trow = NO_ROOM;
if (cur_level >= (AMULET_LEVEL * 2)) {
hit_chance = 100;
} else {
hit_chance = monster->m_hit_chance;
hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
}
if (wizard) {
hit_chance /= 2;
}
if (!fight_monster) {
interrupted = 1;
}
mn = mon_name(monster);
if (!rand_percent(hit_chance)) {
if (!fight_monster) {
messagef(1, "%sthe %s misses", hit_message, mn);
hit_message[0] = 0;
}
return;
}
if (!fight_monster) {
messagef(1, "%sthe %s hit", hit_message, mn);
hit_message[0] = 0;
}
if (!(monster->m_flags & STATIONARY)) {
damage = get_damage(monster->m_damage, 1);
if (cur_level >= (AMULET_LEVEL * 2)) {
minus = (float)((AMULET_LEVEL * 2) - cur_level);
} else {
minus = (float)get_armor_class(rogue.armor) * 3.00;
minus = minus/100.00 * (float)damage;
}
damage -= (short)minus;
} else {
damage = monster->stationary_damage++;
}
if (wizard) {
damage /= 3;
}
if (damage > 0) {
rogue_damage(damage, monster, 0);
}
if (monster->m_flags & SPECIAL_HIT) {
special_hit(monster);
}
}
void
rogue_hit(object *monster, boolean force_hit){
if(check_imitator(monster))
return;
if(!rand_percent((force_hit ? 100 : get_hit_chance(rogue.weapon))
* (1 + wizard) /* <- hit chance */) && !fight_monster){
(void)strlcpy(hit_message, "you miss ", sizeof(hit_message));
}else{
if (con_mon)
s_con_mon(monster);
if(mon_damage(monster, get_weapon_damage(rogue.weapon)
* (1 + 2 * wizard) /* <- damage */)
&& !fight_monster) /* still alive? */
(void)strlcpy(hit_message, "you hit ",
sizeof(hit_message));
}
check_gold_seeker(monster);
wake_up(monster);
}
void
rogue_damage(short d, object *monster, short other)
{
if (d >= rogue.hp_current) {
rogue.hp_current = 0;
print_stats(STAT_HP);
killed_by(monster, other);
}
if (d > 0) {
rogue.hp_current -= d;
print_stats(STAT_HP);
}
}
int
get_damage(const char *ds, boolean r)
{
int i = 0, j, n, d, total = 0;
while (ds[i]) {
n = get_number(ds+i);
while ((ds[i] != 'd') && ds[i]) {
i++;
}
if (ds[i] == 'd') {
i++;
}
d = get_number(ds+i);
while ((ds[i] != '/') && ds[i]) {
i++;
}
if (ds[i] == '/') {
i++;
}
for (j = 0; j < n; j++) {
if (r) {
total += get_rand(1, d);
} else {
total += d;
}
}
}
return(total);
}
static int
get_w_damage(const object *obj)
{
char new_damage[32];
int tmp_to_hit, tmp_damage;
int i = 0;
if ((!obj) || (obj->what_is != WEAPON)) {
return(-1);
}
tmp_to_hit = get_number(obj->damage) + obj->hit_enchant;
while ((obj->damage[i] != 'd') && obj->damage[i]) {
i++;
}
if (obj->damage[i] == 'd') {
i++;
}
tmp_damage = get_number(obj->damage + i) + obj->d_enchant;
snprintf(new_damage, sizeof(new_damage), "%dd%d",
tmp_to_hit, tmp_damage);
return(get_damage(new_damage, 1));
}
int
get_number(const char *s)
{
int i = 0;
int total = 0;
while ((s[i] >= '0') && (s[i] <= '9')) {
total = (10 * total) + (s[i] - '0');
i++;
}
return(total);
}
long
lget_number(const char *s)
{
short i = 0;
long total = 0;
while ((s[i] >= '0') && (s[i] <= '9')) {
total = (10 * total) + (s[i] - '0');
i++;
}
return(total);
}
static int
to_hit(const object *obj)
{
if (!obj) {
return(1);
}
return(get_number(obj->damage) + obj->hit_enchant);
}
static int
damage_for_strength(void)
{
short strength;
strength = rogue.str_current + add_strength;
if (strength <= 6) {
return(strength-5);
}
if (strength <= 14) {
return(1);
}
if (strength <= 17) {
return(3);
}
if (strength <= 18) {
return(4);
}
if (strength <= 20) {
return(5);
}
if (strength <= 21) {
return(6);
}
if (strength <= 30) {
return(7);
}
return(8);
}
int
mon_damage(object *monster, short damage)
{
const char *mn;
short row, col;
monster->hp_to_kill -= damage;
if (monster->hp_to_kill <= 0) {
row = monster->row;
col = monster->col;
dungeon[row][col] &= ~MONSTER;
mvaddch(row, col, get_dungeon_char(row, col));
fight_monster = 0;
cough_up(monster);
mn = mon_name(monster);
messagef(1, "%sdefeated the %s", hit_message, mn);
hit_message[0] = 0;
add_exp(monster->kill_exp, 1);
take_from_pack(monster, &level_monsters);
if (monster->m_flags & HOLDS) {
being_held = 0;
}
free_object(monster);
return(0);
}
return(1);
}
void
fight(boolean to_the_death)
{
short ch, c, d;
short row, col;
boolean first_miss = 1;
short possible_damage;
object *monster;
ch = 0;
while (!is_direction(ch = rgetchar(), &d)) {
sound_bell();
if (first_miss) {
messagef(0, "direction?");
first_miss = 0;
}
}
check_message();
if (ch == CANCEL) {
return;
}
row = rogue.row; col = rogue.col;
get_dir_rc(d, &row, &col, 0);
c = mvinch(row, col);
if (((c < 'A') || (c > 'Z')) ||
(!can_move(rogue.row, rogue.col, row, col))) {
messagef(0, "I see no monster there");
return;
}
if (!(fight_monster = object_at(&level_monsters, row, col))) {
return;
}
if (!(fight_monster->m_flags & STATIONARY)) {
possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3);
} else {
possible_damage = fight_monster->stationary_damage - 1;
}
while (fight_monster) {
(void)one_move_rogue(ch, 0);
if (((!to_the_death) && (rogue.hp_current <= possible_damage)) ||
interrupted || (!(dungeon[row][col] & MONSTER))) {
fight_monster = 0;
} else {
monster = object_at(&level_monsters, row, col);
if (monster != fight_monster) {
fight_monster = 0;
}
}
}
}
void
get_dir_rc(short dir, short *row, short *col, short allow_off_screen)
{
switch(dir) {
case LEFT:
if (allow_off_screen || (*col > 0)) {
(*col)--;
}
break;
case DOWN:
if (allow_off_screen || (*row < (DROWS-2))) {
(*row)++;
}
break;
case UPWARD:
if (allow_off_screen || (*row > MIN_ROW)) {
(*row)--;
}
break;
case RIGHT:
if (allow_off_screen || (*col < (DCOLS-1))) {
(*col)++;
}
break;
case UPLEFT:
if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) {
(*row)--;
(*col)--;
}
break;
case UPRIGHT:
if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) {
(*row)--;
(*col)++;
}
break;
case DOWNRIGHT:
if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) {
(*row)++;
(*col)++;
}
break;
case DOWNLEFT:
if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) {
(*row)++;
(*col)--;
}
break;
}
}
int
get_hit_chance(const object *weapon)
{
short hit_chance;
hit_chance = 40;
hit_chance += 3 * to_hit(weapon);
hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
return(hit_chance);
}
int
get_weapon_damage(const object *weapon)
{
short damage;
damage = get_w_damage(weapon);
damage += damage_for_strength();
damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2);
return(damage);
}
void
s_con_mon(object *monster)
{
if (con_mon) {
monster->m_flags |= CONFUSED;
monster->moves_confused += get_rand(12, 22);
messagef(0, "the monster appears confused");
con_mon = 0;
}
}

View File

@ -1,365 +0,0 @@
/* $NetBSD: init.c,v 1.18 2008/08/08 16:10:47 drochner Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* init.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h> /* getuid(2) */
#include <sys/types.h> /* <pwd.h> */
#include <pwd.h> /* getpwuid(3) */
#include "random.h"
#include "rogue.h"
static void do_args(int, char **);
static void do_opts(void);
static void env_get_value(char **, char *, boolean);
static void init_str(char **, const char *);
static void player_init(void);
static char *rest_file = NULL;
static boolean init_curses = 0;
char login_name[MAX_OPT_LEN];
char *nick_name = NULL;
boolean cant_int = 0;
boolean did_int = 0;
boolean score_only;
boolean save_is_interactive = 1;
boolean ask_quit = 1;
boolean no_skull = 0;
boolean passgo = 0;
const char *error_file = "rogue.esave";
const char *byebye_string = "Okay, bye bye!";
gid_t gid, egid;
int
init(int argc, char *argv[])
{
int fd;
gid = getgid();
egid = getegid();
setegid(gid);
/* Check for dirty tricks with closed fds 0, 1, 2 */
fd = open("/dev/null", O_RDONLY);
if (fd < 3)
exit(1);
close(fd);
{
char *ps;
struct passwd *p;
if((p = getpwuid(getuid())) == NULL
|| strlen(p->pw_name)
>= (sizeof login_name)
/ (sizeof *login_name))
clean_up("Hey! Who are you?");
else
ps = p->pw_name;
strncpy(login_name, ps,
(sizeof login_name)/(sizeof *login_name) - 1);
login_name[(sizeof login_name)/(sizeof *login_name) - 1]
= '\0';
}
do_args(argc, argv);
do_opts();
if (!score_only && !rest_file) {
printf("Hello %s, just a moment while I dig the dungeon...",
nick_name);
fflush(stdout);
}
if (!initscr()) {
fprintf(stderr, "couldn't initialize screen\n");
exit (0);
}
if ((LINES < DROWS) || (COLS < DCOLS)) {
clean_up("must be played on at least 80 x 24 screen");
}
start_window();
init_curses = 1;
md_heed_signals();
if (score_only) {
put_scores(NULL, 0);
}
if (rest_file) {
restore(rest_file);
return(1);
}
mix_colors();
get_wand_and_ring_materials();
make_scroll_titles();
level_objects.next_object = NULL;
level_monsters.next_monster = NULL;
player_init();
ring_stats(0);
return(0);
}
static void
player_init(void)
{
object *obj;
rogue.pack.next_object = NULL;
obj = alloc_object();
get_food(obj, 1);
(void)add_to_pack(obj, &rogue.pack, 1);
obj = alloc_object(); /* initial armor */
obj->what_is = ARMOR;
obj->which_kind = RINGMAIL;
obj->class = RINGMAIL+2;
obj->is_protected = 0;
obj->d_enchant = 1;
(void)add_to_pack(obj, &rogue.pack, 1);
do_wear(obj);
obj = alloc_object(); /* initial weapons */
obj->what_is = WEAPON;
obj->which_kind = MACE;
obj->damage = "2d3";
obj->hit_enchant = obj->d_enchant = 1;
obj->identified = 1;
(void)add_to_pack(obj, &rogue.pack, 1);
do_wield(obj);
obj = alloc_object();
obj->what_is = WEAPON;
obj->which_kind = BOW;
obj->damage = "1d2";
obj->hit_enchant = 1;
obj->d_enchant = 0;
obj->identified = 1;
(void)add_to_pack(obj, &rogue.pack, 1);
obj = alloc_object();
obj->what_is = WEAPON;
obj->which_kind = ARROW;
obj->quantity = get_rand(25, 35);
obj->damage = "1d2";
obj->hit_enchant = 0;
obj->d_enchant = 0;
obj->identified = 1;
(void)add_to_pack(obj, &rogue.pack, 1);
}
void
clean_up(const char *estr)
{
if (save_is_interactive) {
if (init_curses) {
move(DROWS-1, 0);
refresh();
stop_window();
}
printf("\n%s\n", estr);
}
md_exit(0);
}
void
start_window(void)
{
cbreak();
noecho();
#ifndef BAD_NONL
nonl();
#endif
}
void
stop_window(void)
{
endwin();
}
void
byebye(int dummy __unused)
{
md_ignore_signals();
if (ask_quit) {
quit(1);
} else {
clean_up(byebye_string);
}
md_heed_signals();
}
void
onintr(int dummy __unused)
{
md_ignore_signals();
if (cant_int) {
did_int = 1;
} else {
check_message();
messagef(1, "interrupt");
}
md_heed_signals();
}
void
error_save(int dummy __unused)
{
save_is_interactive = 0;
save_into_file(error_file);
clean_up("");
}
static void
do_args(int argc, char *argv[])
{
int i, j;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
for (j = 1; argv[i][j]; j++) {
switch(argv[i][j]) {
case 's':
score_only = 1;
break;
}
}
} else {
rest_file = argv[i];
}
}
}
static void
do_opts(void)
{
char *eptr;
if ((eptr = md_getenv("ROGUEOPTS")) != NULL) {
for (;;) {
while ((*eptr) == ' ') {
eptr++;
}
if (!(*eptr)) {
break;
}
if (!strncmp(eptr, "fruit=", 6)) {
eptr += 6;
env_get_value(&fruit, eptr, 1);
} else if (!strncmp(eptr, "file=", 5)) {
eptr += 5;
env_get_value(&save_file, eptr, 0);
} else if (!strncmp(eptr, "jump", 4)) {
jump = 1;
} else if (!strncmp(eptr, "name=", 5)) {
eptr += 5;
env_get_value(&nick_name, eptr, 0);
} else if (!strncmp(eptr, "noaskquit", 9)) {
ask_quit = 0;
} else if (!strncmp(eptr, "noskull", 5) ||
!strncmp(eptr,"notomb", 6)) {
no_skull = 1;
} else if (!strncmp(eptr, "passgo", 5)) {
passgo = 1;
}
while ((*eptr) && (*eptr != ',')) {
eptr++;
}
if (!(*(eptr++))) {
break;
}
}
}
/* If some strings have not been set through ROGUEOPTS, assign defaults
* to them so that the options editor has data to work with.
*/
init_str(&nick_name, login_name);
init_str(&save_file, "rogue.save");
init_str(&fruit, "slime-mold");
}
static void
env_get_value(char **s, char *e, boolean add_blank)
{
short i = 0;
const char *t;
t = e;
while ((*e) && (*e != ',')) {
if (*e == ':') {
*e = ';'; /* ':' reserved for score file purposes */
}
e++;
if (++i >= MAX_OPT_LEN) {
break;
}
}
/* note: edit_opts() in room.c depends on this being the right size */
*s = md_malloc(MAX_OPT_LEN + 2);
if (*s == NULL)
clean_up("out of memory");
(void)strncpy(*s, t, i);
if (add_blank) {
(*s)[i++] = ' ';
}
(*s)[i] = '\0';
}
static void
init_str(char **str, const char *dflt)
{
if (!(*str)) {
/* note: edit_opts() in room.c depends on this size */
*str = md_malloc(MAX_OPT_LEN + 2);
if (*str == NULL)
clean_up("out of memory");
(void)strlcpy(*str, dflt, MAX_OPT_LEN + 2);
}
}

View File

@ -1,833 +0,0 @@
/* $NetBSD: inventory.c,v 1.15 2011/08/26 06:18:17 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* inventory.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdarg.h>
#include "random.h"
#include "rogue.h"
boolean is_wood[WANDS];
const char *press_space = " --press space to continue--";
static const char *const wand_materials[WAND_MATERIALS] = {
"steel ",
"bronze ",
"gold ",
"silver ",
"copper ",
"nickel ",
"cobalt ",
"tin ",
"iron ",
"magnesium ",
"chrome ",
"carbon ",
"platinum ",
"silicon ",
"titanium ",
"teak ",
"oak ",
"cherry ",
"birch ",
"pine ",
"cedar ",
"redwood ",
"balsa ",
"ivory ",
"walnut ",
"maple ",
"mahogany ",
"elm ",
"palm ",
"wooden "
};
static const char *const gems[GEMS] = {
"diamond ",
"stibotantalite ",
"lapi-lazuli ",
"ruby ",
"emerald ",
"sapphire ",
"amethyst ",
"quartz ",
"tiger-eye ",
"opal ",
"agate ",
"turquoise ",
"pearl ",
"garnet "
};
static const char *const syllables[MAXSYLLABLES] = {
"blech ",
"foo ",
"barf ",
"rech ",
"bar ",
"blech ",
"quo ",
"bloto ",
"oh ",
"caca ",
"blorp ",
"erp ",
"festr ",
"rot ",
"slie ",
"snorf ",
"iky ",
"yuky ",
"ooze ",
"ah ",
"bahl ",
"zep ",
"druhl ",
"flem ",
"behil ",
"arek ",
"mep ",
"zihr ",
"grit ",
"kona ",
"kini ",
"ichi ",
"tims ",
"ogr ",
"oo ",
"ighr ",
"coph ",
"swerr ",
"mihln ",
"poxi "
};
#define COMS 48
struct id_com_s {
short com_char;
const char *com_desc;
};
static const struct id_com_s com_id_tab[COMS] = {
{'?', "? prints help"},
{'r', "r read scroll"},
{'/', "/ identify object"},
{'e', "e eat food"},
{'h', "h left "},
{'w', "w wield a weapon"},
{'j', "j down"},
{'W', "W wear armor"},
{'k', "k up"},
{'T', "T take armor off"},
{'l', "l right"},
{'P', "P put on ring"},
{'y', "y up & left"},
{'R', "R remove ring"},
{'u', "u up & right"},
{'d', "d drop object"},
{'b', "b down & left"},
{'c', "c call object"},
{'n', "n down & right"},
{'\0', "<SHIFT><dir>: run that way"},
{')', ") print current weapon"},
{'\0', "<CTRL><dir>: run till adjacent"},
{']', "] print current armor"},
{'f', "f<dir> fight till death or near death"},
{'=', "= print current rings"},
{'t', "t<dir> throw something"},
{'\001', "^A print Hp-raise average"},
{'m', "m<dir> move onto without picking up"},
{'z', "z<dir> zap a wand in a direction"},
{'o', "o examine/set options"},
{'^', "^<dir> identify trap type"},
{'\022', "^R redraw screen"},
{'&', "& save screen into 'rogue.screen'"},
{'s', "s search for trap/secret door"},
{'\020', "^P repeat last message"},
{'>', "> go down a staircase"},
{'\033', "^[ cancel command"},
{'<', "< go up a staircase"},
{'S', "S save game"},
{'.', ". rest for a turn"},
{'Q', "Q quit"},
{',', ", pick something up"},
{'!', "! shell escape"},
{'i', "i inventory"},
{'F', "F<dir> fight till either of you dies"},
{'I', "I inventory single item"},
{'v', "v print version number"},
{'q', "q quaff potion" }
};
static int get_com_id(int *, short);
static int pr_com_id(int);
static int pr_motion_char(int);
void
inventory(const object *pack, unsigned short mask)
{
object *obj;
short i = 0, j;
size_t maxlen = 0, n;
short row, col;
struct {
short letter;
short sepchar;
char desc[DCOLS];
char savebuf[DCOLS+8];
} descs[MAX_PACK_COUNT+1];
obj = pack->next_object;
if (!obj) {
messagef(0, "your pack is empty");
return;
}
while (obj) {
if (obj->what_is & mask) {
descs[i].letter = obj->ichar;
descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
? '}' : ')';
get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
n = strlen(descs[i].desc) + 4;
if (n > maxlen) {
maxlen = n;
}
i++;
/*assert(i<=MAX_PACK_COUNT);*/
}
obj = obj->next_object;
}
if (maxlen < 27) maxlen = 27;
if (maxlen > DCOLS-2) maxlen = DCOLS-2;
col = DCOLS - (maxlen + 2);
for (row = 0; ((row <= i) && (row < DROWS)); row++) {
for (j = col; j < DCOLS; j++) {
descs[row].savebuf[j-col] = mvinch(row, j);
}
descs[row].savebuf[j-col] = 0;
if (row < i) {
mvprintw(row, col, " %c%c %s",
descs[row].letter, descs[row].sepchar,
descs[row].desc);
}
else {
mvaddstr(row, col, press_space);
}
clrtoeol();
}
refresh();
wait_for_ack();
move(0, 0);
clrtoeol();
for (j = 1; ((j <= i) && (j < DROWS)); j++) {
mvaddstr(j, col, descs[j].savebuf);
}
}
void
id_com(void)
{
int ch = 0;
short i, j, k;
while (ch != CANCEL) {
check_message();
messagef(0, "Character you want help for (* for all):");
refresh();
ch = getchar();
switch(ch) {
case LIST:
{
char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
short rows = (((COMS / 2) + (COMS % 2)) + 1);
boolean need_two_screens = FALSE;
if (rows > LINES) {
need_two_screens = 1;
rows = LINES;
}
k = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < DCOLS; j++) {
save[i][j] = mvinch(i, j);
}
}
MORE:
for (i = 0; i < rows; i++) {
move(i, 0);
clrtoeol();
}
for (i = 0; i < (rows-1); i++) {
if (i < (LINES-1)) {
if (((i + i) < COMS) && ((i+i+k) < COMS)) {
mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
}
if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
mvaddstr(i, (DCOLS/2),
com_id_tab[i+i+k+1].com_desc);
}
}
}
mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
refresh();
wait_for_ack();
if (need_two_screens) {
k += ((rows-1) * 2);
need_two_screens = 0;
goto MORE;
}
for (i = 0; i < rows; i++) {
move(i, 0);
for (j = 0; j < DCOLS; j++) {
addch(save[i][j]);
}
}
}
break;
default:
if (!pr_com_id(ch)) {
if (!pr_motion_char(ch)) {
check_message();
messagef(0, "unknown character");
}
}
ch = CANCEL;
break;
}
}
}
static int
pr_com_id(int ch)
{
int i;
if (!get_com_id(&i, ch)) {
return(0);
}
check_message();
messagef(0, "%s", com_id_tab[i].com_desc);
return(1);
}
static int
get_com_id(int *indexp, short ch)
{
short i;
for (i = 0; i < COMS; i++) {
if (com_id_tab[i].com_char == ch) {
*indexp = i;
return(1);
}
}
return(0);
}
static int
pr_motion_char(int ch)
{
if ( (ch == 'J') ||
(ch == 'K') ||
(ch == 'L') ||
(ch == 'H') ||
(ch == 'Y') ||
(ch == 'U') ||
(ch == 'N') ||
(ch == 'B') ||
(ch == '\012') ||
(ch == '\013') ||
(ch == '\010') ||
(ch == '\014') ||
(ch == '\025') ||
(ch == '\031') ||
(ch == '\016') ||
(ch == '\002')) {
const char *until;
int n = 0; /* XXX: GCC */
if (ch <= '\031') {
ch += 96;
until = " until adjacent";
} else {
ch += 32;
until = "";
}
(void)get_com_id(&n, ch);
check_message();
messagef(0, "run %s%s", com_id_tab[n].com_desc + 8, until);
return(1);
} else {
return(0);
}
}
void
mix_colors(void)
{
short i, j, k;
char t[MAX_ID_TITLE_LEN];
for (i = 0; i <= 32; i++) {
j = get_rand(0, (POTIONS - 1));
k = get_rand(0, (POTIONS - 1));
strlcpy(t, id_potions[j].title, sizeof(t));
strlcpy(id_potions[j].title, id_potions[k].title,
sizeof(id_potions[j].title));
strlcpy(id_potions[k].title, t, sizeof(id_potions[k].title));
}
}
void
make_scroll_titles(void)
{
short i, j, n;
short sylls, s;
size_t maxlen = sizeof(id_scrolls[0].title);
for (i = 0; i < SCROLS; i++) {
sylls = get_rand(2, 5);
(void)strlcpy(id_scrolls[i].title, "'", maxlen);
for (j = 0; j < sylls; j++) {
s = get_rand(1, (MAXSYLLABLES-1));
(void)strlcat(id_scrolls[i].title, syllables[s],
maxlen);
}
/* trim trailing space */
n = strlen(id_scrolls[i].title);
id_scrolls[i].title[n-1] = 0;
(void)strlcat(id_scrolls[i].title, "' ", maxlen);
}
}
struct sbuf {
char *buf;
size_t maxlen;
};
static void sbuf_init(struct sbuf *s, char *buf, size_t maxlen);
static void sbuf_addstr(struct sbuf *s, const char *str);
static void sbuf_addf(struct sbuf *s, const char *fmt, ...) __printflike(2,3);
static void desc_count(struct sbuf *s, int n);
static void desc_called(struct sbuf *s, const object *);
static
void
sbuf_init(struct sbuf *s, char *buf, size_t maxlen)
{
s->buf = buf;
s->maxlen = maxlen;
/*assert(maxlen>0);*/
s->buf[0] = 0;
}
static
void
sbuf_addstr(struct sbuf *s, const char *str)
{
strlcat(s->buf, str, s->maxlen);
}
static
void
sbuf_addf(struct sbuf *s, const char *fmt, ...)
{
va_list ap;
size_t initlen;
initlen = strlen(s->buf);
va_start(ap, fmt);
vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
va_end(ap);
}
static
void
desc_count(struct sbuf *s, int n)
{
if (n == 1) {
sbuf_addstr(s, "an ");
} else {
sbuf_addf(s, "%d ", n);
}
}
static
void
desc_called(struct sbuf *s, const object *obj)
{
struct id *id_table;
id_table = get_id_table(obj);
sbuf_addstr(s, name_of(obj));
sbuf_addstr(s, "called ");
sbuf_addstr(s, id_table[obj->which_kind].title);
}
void
get_desc(const object *obj, char *desc, size_t desclen)
{
const char *item_name;
struct id *id_table;
struct sbuf db;
unsigned short objtype_id_status;
if (obj->what_is == AMULET) {
(void)strlcpy(desc, "the amulet of Yendor ", desclen);
return;
}
if (obj->what_is == GOLD) {
snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
return;
}
item_name = name_of(obj);
id_table = get_id_table(obj);
if (wizard || id_table == NULL) {
objtype_id_status = IDENTIFIED;
}
else {
objtype_id_status = id_table[obj->which_kind].id_status;
}
if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
if (obj->identified) {
objtype_id_status = IDENTIFIED;
}
}
sbuf_init(&db, desc, desclen);
switch (obj->what_is) {
case FOOD:
if (obj->which_kind == RATION) {
if (obj->quantity > 1) {
sbuf_addf(&db,
"%d rations of %s", obj->quantity,
item_name);
} else {
sbuf_addf(&db, "some %s", item_name);
}
} else {
sbuf_addf(&db, "an %s", item_name);
}
break;
case SCROL:
desc_count(&db, obj->quantity);
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, item_name);
sbuf_addstr(&db, "entitled: ");
sbuf_addstr(&db, id_table[obj->which_kind].title);
} else if (objtype_id_status==CALLED) {
desc_called(&db, obj);
} else {
sbuf_addstr(&db, item_name);
sbuf_addstr(&db, id_table[obj->which_kind].real);
}
break;
case POTION:
desc_count(&db, obj->quantity);
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, id_table[obj->which_kind].title);
sbuf_addstr(&db, item_name);
} else if (objtype_id_status==CALLED) {
desc_called(&db, obj);
} else {
sbuf_addstr(&db, item_name);
sbuf_addstr(&db, id_table[obj->which_kind].real);
}
break;
case WAND:
desc_count(&db, obj->quantity);
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, id_table[obj->which_kind].title);
sbuf_addstr(&db, item_name);
} else if (objtype_id_status==CALLED) {
desc_called(&db, obj);
} else {
sbuf_addstr(&db, item_name);
sbuf_addstr(&db, id_table[obj->which_kind].real);
if (wizard || obj->identified) {
sbuf_addf(&db, "[%d]", obj->class);
}
}
break;
case RING:
desc_count(&db, obj->quantity);
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, id_table[obj->which_kind].title);
sbuf_addstr(&db, item_name);
} else if (objtype_id_status==CALLED) {
desc_called(&db, obj);
} else {
if ((wizard || obj->identified) &&
(obj->which_kind == DEXTERITY ||
obj->which_kind == ADD_STRENGTH)) {
sbuf_addf(&db, "%+d ", obj->class);
}
sbuf_addstr(&db, item_name);
sbuf_addstr(&db, id_table[obj->which_kind].real);
}
break;
case ARMOR:
/* no desc_count() */
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, id_table[obj->which_kind].title);
} else {
sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
id_table[obj->which_kind].title,
get_armor_class(obj));
}
break;
case WEAPON:
desc_count(&db, obj->quantity);
if (objtype_id_status==UNIDENTIFIED) {
sbuf_addstr(&db, name_of(obj));
} else {
sbuf_addf(&db, "%+d,%+d %s",
obj->hit_enchant, obj->d_enchant,
name_of(obj));
}
break;
}
if (obj->in_use_flags & BEING_WIELDED) {
sbuf_addstr(&db, "in hand");
} else if (obj->in_use_flags & BEING_WORN) {
sbuf_addstr(&db, "being worn");
} else if (obj->in_use_flags & ON_LEFT_HAND) {
sbuf_addstr(&db, "on left hand");
} else if (obj->in_use_flags & ON_RIGHT_HAND) {
sbuf_addstr(&db, "on right hand");
}
if (!strncmp(db.buf, "an ", 3)) {
if (!is_vowel(db.buf[3])) {
memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
db.buf[1] = ' ';
}
}
}
void
get_wand_and_ring_materials(void)
{
short i, j;
boolean used[WAND_MATERIALS];
for (i = 0; i < WAND_MATERIALS; i++) {
used[i] = 0;
}
for (i = 0; i < WANDS; i++) {
do {
j = get_rand(0, WAND_MATERIALS-1);
} while (used[j]);
used[j] = 1;
(void)strlcpy(id_wands[i].title, wand_materials[j],
sizeof(id_wands[i].title));
is_wood[i] = (j > MAX_METAL);
}
for (i = 0; i < GEMS; i++) {
used[i] = 0;
}
for (i = 0; i < RINGS; i++) {
do {
j = get_rand(0, GEMS-1);
} while (used[j]);
used[j] = 1;
(void)strlcpy(id_rings[i].title, gems[j],
sizeof(id_rings[i].title));
}
}
void
single_inv(short ichar)
{
short ch, ch2;
char desc[DCOLS];
object *obj;
ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
get_desc(obj, desc, sizeof(desc));
messagef(0, "%c%c %s", ch, ch2, desc);
}
struct id *
get_id_table(const object *obj)
{
switch(obj->what_is) {
case SCROL:
return(id_scrolls);
case POTION:
return(id_potions);
case WAND:
return(id_wands);
case RING:
return(id_rings);
case WEAPON:
return(id_weapons);
case ARMOR:
return(id_armors);
}
return((struct id *)0);
}
void
inv_armor_weapon(boolean is_weapon)
{
if (is_weapon) {
if (rogue.weapon) {
single_inv(rogue.weapon->ichar);
} else {
messagef(0, "not wielding anything");
}
} else {
if (rogue.armor) {
single_inv(rogue.armor->ichar);
} else {
messagef(0, "not wearing anything");
}
}
}
void
id_type(void)
{
const char *id;
int ch;
messagef(0, "what do you want identified?");
ch = rgetchar();
if ((ch >= 'A') && (ch <= 'Z')) {
id = m_names[ch-'A'];
} else if (ch < 32) {
check_message();
return;
} else {
switch(ch) {
case '@':
id = "you";
break;
case '%':
id = "staircase";
break;
case '^':
id = "trap";
break;
case '+':
id = "door";
break;
case '-':
case '|':
id = "wall of a room";
break;
case '.':
id = "floor";
break;
case '#':
id = "passage";
break;
case ' ':
id = "solid rock";
break;
case '=':
id = "ring";
break;
case '?':
id = "scroll";
break;
case '!':
id = "potion";
break;
case '/':
id = "wand or staff";
break;
case ')':
id = "weapon";
break;
case ']':
id = "armor";
break;
case '*':
id = "gold";
break;
case ':':
id = "food";
break;
case ',':
id = "the Amulet of Yendor";
break;
default:
id = "unknown character";
break;
}
}
check_message();
messagef(0, "'%c': %s", ch, id);
}

View File

@ -1,893 +0,0 @@
/* $NetBSD: level.c,v 1.10 2008/01/14 03:50:01 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* level.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
#define SWAP(x,y) (t = (x), (x) = (y), (y) = t)
static void add_mazes(void);
static int connect_rooms(short, short);
static void draw_simple_passage(short, short, short, short, short);
static void fill_it(int, boolean);
static void fill_out_level(void);
static int get_exp_level(long);
static void hide_boxed_passage(short, short, short, short, short);
static void make_maze(short, short, short, short, short, short);
static void make_room(short, short, short, short);
static boolean mask_room(short, short *, short *, unsigned short);
static void mix_random_rooms(void);
static void put_door(room *, short, short *, short *);
static void recursive_deadend(short, const short *, short, short);
static int same_col(int, int);
static int same_row(int, int);
short cur_level = 0;
short max_level = 1;
short cur_room;
const char *new_level_message = NULL;
short party_room = NO_ROOM;
static short r_de;
const long level_points[MAX_EXP_LEVEL] = {
10L,
20L,
40L,
80L,
160L,
320L,
640L,
1300L,
2600L,
5200L,
10000L,
20000L,
40000L,
80000L,
160000L,
320000L,
1000000L,
3333333L,
6666666L,
MAX_EXP,
99900000L
};
static short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
void
make_level(void)
{
short i, j;
short must_1, must_2, must_3;
boolean big_room;
must_2 = must_3 = 0;
if (cur_level < LAST_DUNGEON) {
cur_level++;
}
if (cur_level > max_level) {
max_level = cur_level;
}
must_1 = get_rand(0, 5);
switch(must_1) {
case 0:
must_1 = 0;
must_2 = 1;
must_3 = 2;
break;
case 1:
must_1 = 3;
must_2 = 4;
must_3 = 5;
break;
case 2:
must_1 = 6;
must_2 = 7;
must_3 = 8;
break;
case 3:
must_1 = 0;
must_2 = 3;
must_3 = 6;
break;
case 4:
must_1 = 1;
must_2 = 4;
must_3 = 7;
break;
case 5:
must_1 = 2;
must_2 = 5;
must_3 = 8;
break;
}
if (rand_percent(8)) {
party_room = 0;
}
big_room = ((party_room != NO_ROOM) && rand_percent(1));
if (big_room) {
make_room(BIG_ROOM, 0, 0, 0);
} else {
for (i = 0; i < MAXROOMS; i++) {
make_room(i, must_1, must_2, must_3);
}
}
if (!big_room) {
add_mazes();
mix_random_rooms();
for (j = 0; j < MAXROOMS; j++) {
i = random_rooms[j];
if (i < (MAXROOMS-1)) {
(void)connect_rooms(i, i+1);
}
if (i < (MAXROOMS-3)) {
(void)connect_rooms(i, i+3);
}
if (i < (MAXROOMS-2)) {
if (rooms[i+1].is_room & R_NOTHING) {
if (connect_rooms(i, i+2)) {
rooms[i+1].is_room = R_CROSS;
}
}
}
if (i < (MAXROOMS-6)) {
if (rooms[i+3].is_room & R_NOTHING) {
if (connect_rooms(i, i+6)) {
rooms[i+3].is_room = R_CROSS;
}
}
}
if (is_all_connected()) {
break;
}
}
fill_out_level();
}
if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
put_amulet();
}
}
static void
make_room(short rn, short r1, short r2, short r3)
{
short left_col, right_col, top_row, bottom_row;
short width, height;
short row_offset, col_offset;
short i, j, ch;
left_col = right_col = top_row = bottom_row = 0;
switch(rn) {
case 0:
left_col = 0;
right_col = COL1-1;
top_row = MIN_ROW;
bottom_row = ROW1-1;
break;
case 1:
left_col = COL1+1;
right_col = COL2-1;
top_row = MIN_ROW;
bottom_row = ROW1-1;
break;
case 2:
left_col = COL2+1;
right_col = DCOLS-1;
top_row = MIN_ROW;
bottom_row = ROW1-1;
break;
case 3:
left_col = 0;
right_col = COL1-1;
top_row = ROW1+1;
bottom_row = ROW2-1;
break;
case 4:
left_col = COL1+1;
right_col = COL2-1;
top_row = ROW1+1;
bottom_row = ROW2-1;
break;
case 5:
left_col = COL2+1;
right_col = DCOLS-1;
top_row = ROW1+1;
bottom_row = ROW2-1;
break;
case 6:
left_col = 0;
right_col = COL1-1;
top_row = ROW2+1;
bottom_row = DROWS - 2;
break;
case 7:
left_col = COL1+1;
right_col = COL2-1;
top_row = ROW2+1;
bottom_row = DROWS - 2;
break;
case 8:
left_col = COL2+1;
right_col = DCOLS-1;
top_row = ROW2+1;
bottom_row = DROWS - 2;
break;
case BIG_ROOM:
top_row = get_rand(MIN_ROW, MIN_ROW+5);
bottom_row = get_rand(DROWS-7, DROWS-2);
left_col = get_rand(0, 10);
right_col = get_rand(DCOLS-11, DCOLS-1);
rn = 0;
goto B;
}
height = get_rand(4, (bottom_row - top_row + 1));
width = get_rand(7, (right_col - left_col - 2));
row_offset = get_rand(0, ((bottom_row - top_row) - height + 1));
col_offset = get_rand(0, ((right_col - left_col) - width + 1));
top_row += row_offset;
bottom_row = top_row + height - 1;
left_col += col_offset;
right_col = left_col + width - 1;
if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) {
goto END;
}
B:
rooms[rn].is_room = R_ROOM;
for (i = top_row; i <= bottom_row; i++) {
for (j = left_col; j <= right_col; j++) {
if ((i == top_row) || (i == bottom_row)) {
ch = HORWALL;
} else if ( ((i != top_row) && (i != bottom_row)) &&
((j == left_col) || (j == right_col))) {
ch = VERTWALL;
} else {
ch = FLOOR;
}
dungeon[i][j] = ch;
}
}
END:
rooms[rn].top_row = top_row;
rooms[rn].bottom_row = bottom_row;
rooms[rn].left_col = left_col;
rooms[rn].right_col = right_col;
}
static int
connect_rooms(short room1, short room2)
{
short row1, col1, row2, col2, dir;
if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) ||
(!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) {
return(0);
}
if (same_row(room1, room2) &&
(rooms[room1].left_col > rooms[room2].right_col)) {
put_door(&rooms[room1], LEFT, &row1, &col1);
put_door(&rooms[room2], RIGHT, &row2, &col2);
dir = LEFT;
} else if (same_row(room1, room2) &&
(rooms[room2].left_col > rooms[room1].right_col)) {
put_door(&rooms[room1], RIGHT, &row1, &col1);
put_door(&rooms[room2], LEFT, &row2, &col2);
dir = RIGHT;
} else if (same_col(room1, room2) &&
(rooms[room1].top_row > rooms[room2].bottom_row)) {
put_door(&rooms[room1], UPWARD, &row1, &col1);
put_door(&rooms[room2], DOWN, &row2, &col2);
dir = UPWARD;
} else if (same_col(room1, room2) &&
(rooms[room2].top_row > rooms[room1].bottom_row)) {
put_door(&rooms[room1], DOWN, &row1, &col1);
put_door(&rooms[room2], UPWARD, &row2, &col2);
dir = DOWN;
} else {
return(0);
}
do {
draw_simple_passage(row1, col1, row2, col2, dir);
} while (rand_percent(4));
rooms[room1].doors[dir/2].oth_room = room2;
rooms[room1].doors[dir/2].oth_row = row2;
rooms[room1].doors[dir/2].oth_col = col2;
rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1;
rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1;
rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1;
return(1);
}
void
clear_level(void)
{
short i, j;
for (i = 0; i < MAXROOMS; i++) {
rooms[i].is_room = R_NOTHING;
for (j = 0; j < 4; j++) {
rooms[i].doors[j].oth_room = NO_ROOM;
}
}
for (i = 0; i < MAX_TRAPS; i++) {
traps[i].trap_type = NO_TRAP;
}
for (i = 0; i < DROWS; i++) {
for (j = 0; j < DCOLS; j++) {
dungeon[i][j] = NOTHING;
}
}
detect_monster = see_invisible = 0;
being_held = bear_trap = 0;
party_room = NO_ROOM;
rogue.row = rogue.col = -1;
clear();
}
static void
put_door(room *rm, short dir, short *row, short *col)
{
short wall_width;
wall_width = (rm->is_room & R_MAZE) ? 0 : 1;
switch(dir) {
case UPWARD:
case DOWN:
*row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row);
do {
*col = get_rand(rm->left_col+wall_width,
rm->right_col-wall_width);
} while (!(dungeon[*row][*col] & (HORWALL | TUNNEL)));
break;
case RIGHT:
case LEFT:
*col = (dir == LEFT) ? rm->left_col : rm->right_col;
do {
*row = get_rand(rm->top_row+wall_width,
rm->bottom_row-wall_width);
} while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL)));
break;
}
if (rm->is_room & R_ROOM) {
dungeon[*row][*col] = DOOR;
}
if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) {
dungeon[*row][*col] |= HIDDEN;
}
rm->doors[dir/2].door_row = *row;
rm->doors[dir/2].door_col = *col;
}
static void
draw_simple_passage(short row1, short col1, short row2, short col2, short dir)
{
short i, middle, t;
if ((dir == LEFT) || (dir == RIGHT)) {
if (col1 > col2) {
SWAP(row1, row2);
SWAP(col1, col2);
}
middle = get_rand(col1+1, col2-1);
for (i = col1+1; i != middle; i++) {
dungeon[row1][i] = TUNNEL;
}
for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
dungeon[i][middle] = TUNNEL;
}
for (i = middle; i != col2; i++) {
dungeon[row2][i] = TUNNEL;
}
} else {
if (row1 > row2) {
SWAP(row1, row2);
SWAP(col1, col2);
}
middle = get_rand(row1+1, row2-1);
for (i = row1+1; i != middle; i++) {
dungeon[i][col1] = TUNNEL;
}
for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
dungeon[middle][i] = TUNNEL;
}
for (i = middle; i != row2; i++) {
dungeon[i][col2] = TUNNEL;
}
}
if (rand_percent(HIDE_PERCENT)) {
hide_boxed_passage(row1, col1, row2, col2, 1);
}
}
static int
same_row(int room1, int room2)
{
return((room1 / 3) == (room2 / 3));
}
static int
same_col(int room1, int room2)
{
return((room1 % 3) == (room2 % 3));
}
static void
add_mazes(void)
{
short i, j;
short start;
short maze_percent;
if (cur_level > 1) {
start = get_rand(0, (MAXROOMS-1));
maze_percent = (cur_level * 5) / 4;
if (cur_level > 15) {
maze_percent += cur_level;
}
for (i = 0; i < MAXROOMS; i++) {
j = ((start + i) % MAXROOMS);
if (rooms[j].is_room & R_NOTHING) {
if (rand_percent(maze_percent)) {
rooms[j].is_room = R_MAZE;
make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1),
get_rand(rooms[j].left_col+1, rooms[j].right_col-1),
rooms[j].top_row, rooms[j].bottom_row,
rooms[j].left_col, rooms[j].right_col);
hide_boxed_passage(rooms[j].top_row, rooms[j].left_col,
rooms[j].bottom_row, rooms[j].right_col,
get_rand(0, 2));
}
}
}
}
}
static void
fill_out_level(void)
{
short i, rn;
mix_random_rooms();
r_de = NO_ROOM;
for (i = 0; i < MAXROOMS; i++) {
rn = random_rooms[i];
if ((rooms[rn].is_room & R_NOTHING) ||
((rooms[rn].is_room & R_CROSS) && (rand() & 1))) {
fill_it(rn, 1);
}
}
if (r_de != NO_ROOM) {
fill_it(r_de, 0);
}
}
static void
fill_it(int rn, boolean do_rec_de)
{
short i, tunnel_dir, door_dir, drow, dcol;
short target_room, rooms_found = 0;
short srow, scol, t;
static short offsets[4] = {-1, 1, 3, -3};
boolean did_this = 0;
for (i = 0; i < 10; i++) {
srow = get_rand(0, 3);
scol = get_rand(0, 3);
t = offsets[srow];
offsets[srow] = offsets[scol];
offsets[scol] = t;
}
for (i = 0; i < 4; i++) {
target_room = rn + offsets[i];
if (((target_room < 0) || (target_room >= MAXROOMS)) ||
(!(same_row(rn,target_room) || same_col(rn,target_room))) ||
(!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) {
continue;
}
if (same_row(rn, target_room)) {
tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ?
RIGHT : LEFT;
} else {
tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ?
DOWN : UPWARD;
}
door_dir = ((tunnel_dir + 4) % DIRS);
if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) {
continue;
}
if (((!do_rec_de) || did_this) ||
(!mask_room(rn, &srow, &scol, TUNNEL))) {
srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2;
scol = (rooms[rn].left_col + rooms[rn].right_col) / 2;
}
put_door(&rooms[target_room], door_dir, &drow, &dcol);
rooms_found++;
draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
rooms[rn].is_room = R_DEADEND;
dungeon[srow][scol] = TUNNEL;
if ((i < 3) && (!did_this)) {
did_this = 1;
if(rand() & 1)
continue;
}
if ((rooms_found < 2) && do_rec_de) {
recursive_deadend(rn, offsets, srow, scol);
}
break;
}
}
static void
recursive_deadend(short rn, const short *offsets, short srow, short scol)
{
short i, de;
short drow, dcol, tunnel_dir;
rooms[rn].is_room = R_DEADEND;
dungeon[srow][scol] = TUNNEL;
for (i = 0; i < 4; i++) {
de = rn + offsets[i];
if (((de < 0) || (de >= MAXROOMS)) ||
(!(same_row(rn, de) || same_col(rn, de)))) {
continue;
}
if (!(rooms[de].is_room & R_NOTHING)) {
continue;
}
drow = (rooms[de].top_row + rooms[de].bottom_row) / 2;
dcol = (rooms[de].left_col + rooms[de].right_col) / 2;
if (same_row(rn, de)) {
tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ?
RIGHT : LEFT;
} else {
tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ?
DOWN : UPWARD;
}
draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
r_de = de;
recursive_deadend(de, offsets, drow, dcol);
}
}
static boolean
mask_room(short rn, short *row, short *col, unsigned short mask)
{
short i, j;
for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
if (dungeon[i][j] & mask) {
*row = i;
*col = j;
return(1);
}
}
}
return(0);
}
static void
make_maze(short r, short c, short tr, short br, short lc, short rc)
{
char dirs[4];
short i, t;
dirs[0] = UPWARD;
dirs[1] = DOWN;
dirs[2] = LEFT;
dirs[3] = RIGHT;
dungeon[r][c] = TUNNEL;
if (rand_percent(20)) {
for (i = 0; i < 10; i++) {
short t1, t2;
t1 = get_rand(0, 3);
t2 = get_rand(0, 3);
SWAP(dirs[t1], dirs[t2]);
}
}
for (i = 0; i < 4; i++) {
switch(dirs[i]) {
case UPWARD:
if (((r-1) >= tr) &&
(dungeon[r-1][c] != TUNNEL) &&
(dungeon[r-1][c-1] != TUNNEL) &&
(dungeon[r-1][c+1] != TUNNEL) &&
(dungeon[r-2][c] != TUNNEL)) {
make_maze((r-1), c, tr, br, lc, rc);
}
break;
case DOWN:
if (((r+1) <= br) &&
(dungeon[r+1][c] != TUNNEL) &&
(dungeon[r+1][c-1] != TUNNEL) &&
(dungeon[r+1][c+1] != TUNNEL) &&
(dungeon[r+2][c] != TUNNEL)) {
make_maze((r+1), c, tr, br, lc, rc);
}
break;
case LEFT:
if (((c-1) >= lc) &&
(dungeon[r][c-1] != TUNNEL) &&
(dungeon[r-1][c-1] != TUNNEL) &&
(dungeon[r+1][c-1] != TUNNEL) &&
(dungeon[r][c-2] != TUNNEL)) {
make_maze(r, (c-1), tr, br, lc, rc);
}
break;
case RIGHT:
if (((c+1) <= rc) &&
(dungeon[r][c+1] != TUNNEL) &&
(dungeon[r-1][c+1] != TUNNEL) &&
(dungeon[r+1][c+1] != TUNNEL) &&
(dungeon[r][c+2] != TUNNEL)) {
make_maze(r, (c+1), tr, br, lc, rc);
}
break;
}
}
}
static void
hide_boxed_passage(short row1, short col1, short row2, short col2, short n)
{
short i, j, t;
short row, col, row_cut, col_cut;
short h, w;
if (cur_level > 2) {
if (row1 > row2) {
SWAP(row1, row2);
}
if (col1 > col2) {
SWAP(col1, col2);
}
h = row2 - row1;
w = col2 - col1;
if ((w >= 5) || (h >= 5)) {
row_cut = ((h >= 2) ? 1 : 0);
col_cut = ((w >= 2) ? 1 : 0);
for (i = 0; i < n; i++) {
for (j = 0; j < 10; j++) {
row = get_rand(row1 + row_cut, row2 - row_cut);
col = get_rand(col1 + col_cut, col2 - col_cut);
if (dungeon[row][col] == TUNNEL) {
dungeon[row][col] |= HIDDEN;
break;
}
}
}
}
}
}
/*
* try not to put in room NR
*/
void
put_player(short nr)
{
short rn = nr, misses;
short row, col;
for (misses = 0; ((misses < 2) && (rn == nr)); misses++) {
gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS));
rn = get_room_number(row, col);
}
rogue.row = row;
rogue.col = col;
if (dungeon[rogue.row][rogue.col] & TUNNEL) {
cur_room = PASSAGE;
} else {
cur_room = rn;
}
if (cur_room != PASSAGE) {
light_up_room(cur_room);
} else {
light_passage(rogue.row, rogue.col);
}
rn = get_room_number(rogue.row, rogue.col);
wake_room(rn, 1, rogue.row, rogue.col);
if (new_level_message) {
messagef(0, "%s", new_level_message);
new_level_message = NULL;
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
}
int
drop_check(void)
{
if (wizard) {
return(1);
}
if (dungeon[rogue.row][rogue.col] & STAIRS) {
if (levitate) {
messagef(0, "you're floating in the air!");
return(0);
}
return(1);
}
messagef(0, "I see no way down");
return(0);
}
int
check_up(void)
{
if (!wizard) {
if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
messagef(0, "I see no way up");
return(0);
}
if (!has_amulet()) {
messagef(0, "your way is magically blocked");
return(0);
}
}
new_level_message = "you feel a wrenching sensation in your gut";
if (cur_level == 1) {
win();
} else {
cur_level -= 2;
return(1);
}
return(0);
}
void
add_exp(int e, boolean promotion)
{
short new_exp;
short i, hp;
rogue.exp_points += e;
if (rogue.exp_points >= level_points[rogue.exp-1]) {
new_exp = get_exp_level(rogue.exp_points);
if (rogue.exp_points > MAX_EXP) {
rogue.exp_points = MAX_EXP + 1;
}
for (i = rogue.exp+1; i <= new_exp; i++) {
messagef(0, "welcome to level %d", i);
if (promotion) {
hp = hp_raise();
rogue.hp_current += hp;
rogue.hp_max += hp;
}
rogue.exp = i;
print_stats(STAT_HP | STAT_EXP);
}
} else {
print_stats(STAT_EXP);
}
}
static int
get_exp_level(long e)
{
short i;
for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
if (level_points[i] > e) {
break;
}
}
return(i+1);
}
int
hp_raise(void)
{
int hp;
hp = (wizard ? 10 : get_rand(3, 10));
return(hp);
}
void
show_average_hp(void)
{
float real_average;
float effective_average;
if (rogue.exp == 1) {
real_average = effective_average = 0.00;
} else {
real_average = (float)
((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1);
effective_average = (float)(rogue.hp_max - INIT_HP) / (rogue.exp - 1);
}
messagef(0, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average,
effective_average, extra_hp, less_hp);
}
static void
mix_random_rooms(void)
{
short i, t;
short x, y;
for (i = 0; i < (3 * MAXROOMS); i++) {
do {
x = get_rand(0, (MAXROOMS-1));
y = get_rand(0, (MAXROOMS-1));
} while (x == y);
SWAP(random_rooms[x], random_rooms[y]);
}
}

View File

@ -1,388 +0,0 @@
/* $NetBSD: machdep.c,v 1.20 2012/12/01 11:37:27 mbalmer Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* machdep.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include "rogue.h"
#include "pathnames.h"
/* md_slurp:
*
* This routine throws away all keyboard input that has not
* yet been read. It is used to get rid of input that the user may have
* typed-ahead.
*
* This function is not necessary, so it may be stubbed. The might cause
* message-line output to flash by because the game has continued to read
* input without waiting for the user to read the message. Not such a
* big deal.
*/
void
md_slurp(void)
{
/*(void)fpurge(stdin);*/ /* fpurge(3) isn't in musl */
}
/* md_heed_signals():
*
* This routine tells the program to call particular routines when
* certain interrupts/events occur:
*
* SIGINT: call onintr() to interrupt fight with monster or long rest.
* SIGQUIT: call byebye() to check for game termination.
* SIGHUP: call error_save() to save game when terminal hangs up.
*
* On VMS, SIGINT and SIGQUIT correspond to ^C and ^Y.
*
* This routine is not strictly necessary and can be stubbed. This will
* mean that the game cannot be interrupted properly with keyboard
* input, this is not usually critical.
*/
void
md_heed_signals(void)
{
signal(SIGINT, onintr);
signal(SIGQUIT, byebye);
signal(SIGHUP, error_save);
}
/* md_ignore_signals():
*
* This routine tells the program to completely ignore the events mentioned
* in md_heed_signals() above. The event handlers will later be turned on
* by a future call to md_heed_signals(), so md_heed_signals() and
* md_ignore_signals() need to work together.
*
* This function should be implemented or the user risks interrupting
* critical sections of code, which could cause score file, or saved-game
* file, corruption.
*/
void
md_ignore_signals(void)
{
signal(SIGQUIT, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
}
/* md_get_file_id():
*
* This function returns an integer that uniquely identifies the specified
* file. It need not check for the file's existence. In UNIX, the inode
* number is used.
*
* This function is used to identify saved-game files.
*/
int
md_get_file_id(const char *fname)
{
struct stat sbuf;
if (stat(fname, &sbuf)) {
return(-1);
}
return((int)sbuf.st_ino);
}
/* md_link_count():
*
* This routine returns the number of hard links to the specified file.
*
* This function is not strictly necessary. On systems without hard links
* this routine can be stubbed by just returning 1.
*/
int
md_link_count(const char *fname)
{
struct stat sbuf;
stat(fname, &sbuf);
return((int)sbuf.st_nlink);
}
/* md_gct(): (Get Current Time)
*
* This function returns the current year, month(1-12), day(1-31), hour(0-23),
* minute(0-59), and second(0-59). This is used for identifying the time
* at which a game is saved.
*
* This function is not strictly necessary. It can be stubbed by returning
* zeros instead of the correct year, month, etc. If your operating
* system doesn't provide all of the time units requested here, then you
* can provide only those that it does, and return zeros for the others.
* If you cannot provide good time values, then users may be able to copy
* saved-game files and play them.
*/
void
md_gct(struct rogue_time *rt_buf)
{
struct tm *t;
time_t seconds;
time(&seconds);
t = localtime(&seconds);
rt_buf->year = t->tm_year;
rt_buf->month = t->tm_mon + 1;
rt_buf->day = t->tm_mday;
rt_buf->hour = t->tm_hour;
rt_buf->minute = t->tm_min;
rt_buf->second = t->tm_sec;
}
/* md_gfmt: (Get File Modification Time)
*
* This routine returns a file's date of last modification in the same format
* as md_gct() above.
*
* This function is not strictly necessary. It is used to see if saved-game
* files have been modified since they were saved. If you have stubbed the
* routine md_gct() above by returning constant values, then you may do
* exactly the same here.
* Or if md_gct() is implemented correctly, but your system does not provide
* file modification dates, you may return some date far in the past so
* that the program will never know that a saved-game file being modified.
* You may also do this if you wish to be able to restore games from
* saved-games that have been modified.
*/
void
md_gfmt(const char *fname, struct rogue_time *rt_buf)
{
struct stat sbuf;
time_t seconds;
struct tm *t;
stat(fname, &sbuf);
seconds = sbuf.st_mtime;
t = localtime(&seconds);
rt_buf->year = t->tm_year;
rt_buf->month = t->tm_mon + 1;
rt_buf->day = t->tm_mday;
rt_buf->hour = t->tm_hour;
rt_buf->minute = t->tm_min;
rt_buf->second = t->tm_sec;
}
/* md_df: (Delete File)
*
* This function deletes the specified file, and returns true (1) if the
* operation was successful. This is used to delete saved-game files
* after restoring games from them.
*
* Again, this function is not strictly necessary, and can be stubbed
* by simply returning 1. In this case, saved-game files will not be
* deleted and can be replayed.
*/
boolean
md_df(const char *fname)
{
if (unlink(fname)) {
return(0);
}
return(1);
}
/* md_sleep:
*
* This routine causes the game to pause for the specified number of
* seconds.
*
* This routine is not particularly necessary at all. It is used for
* delaying execution, which is useful to this program at some times.
*/
void
md_sleep(int nsecs)
{
(void)sleep(nsecs);
}
/* md_getenv()
*
* This routine gets certain values from the user's environment. These
* values are strings, and each string is identified by a name. The names
* of the values needed, and their use, is as follows:
*
* ROGUEOPTS
* A string containing the various game options. This need not be
* defined.
* HOME
* The user's home directory. This is only used when the user specifies
* '~' as the first character of a saved-game file. This string need
* not be defined.
* SHELL
* The user's favorite shell. If not found, "/bin/sh" is assumed.
*
* If your system does not provide a means of searching for these values,
* you will have to do it yourself. None of the values above really need
* to be defined; you can get by with simply always returning zero.
* Returning zero indicates that their is no defined value for the
* given string.
*/
char *
md_getenv(const char *name)
{
char *value;
value = getenv(name);
return(value);
}
/* md_malloc()
*
* This routine allocates, and returns a pointer to, the specified number
* of bytes. This routines absolutely MUST be implemented for your
* particular system or the program will not run at all. Return zero
* when no more memory can be allocated.
*/
void *
md_malloc(size_t n)
{
char *t;
t = malloc(n);
return(t);
}
/* md_exit():
*
* This function causes the program to discontinue execution and exit.
* This function must be implemented or the program will continue to
* hang when it should quit.
*/
void
md_exit(int status)
{
exit(status);
}
/* md_lock():
*
* This function is intended to give the user exclusive access to the score
* file. It does so by flock'ing the score file. The full path name of the
* score file should be defined for any particular site in rogue.h. The
* constants _PATH_SCOREFILE defines this file name.
*
* When the parameter 'l' is non-zero (true), a lock is requested. Otherwise
* the lock is released.
*/
void
md_lock(boolean l)
{
static int fd = -1;
short tries;
if (l) {
setegid(egid);
if ((fd = open(_PATH_SCOREFILE, O_RDONLY)) < 1) {
setegid(gid);
messagef(0, "cannot lock score file");
return;
}
setegid(gid);
for (tries = 0; tries < 5; tries++)
if (!flock(fd, LOCK_EX|LOCK_NB))
return;
} else {
(void)flock(fd, LOCK_UN|LOCK_NB);
(void)close(fd);
}
}
/* md_shell():
*
* This function spawns a shell for the user to use. When this shell is
* terminated, the game continues.
*
* It is important that the game not give the shell the privileges the
* game uses to access the scores file. This version of the game runs
* with privileges low by default; only the saved gid (if setgid) or uid
* (if setuid) will be privileged, but that privilege is discarded by
* exec().
*/
void
md_shell(const char *shell)
{
int w;
pid_t pid;
pid = fork();
switch (pid) {
case -1:
break;
case 0:
execl(shell, shell, (char *)NULL);
_exit(255);
default:
waitpid(pid, &w, 0);
break;
}
}

View File

@ -1,16 +0,0 @@
#include "rogue.h"
void md_slurp(void);
void md_heed_signals(void);
void md_ignore_signals(void);
int md_get_file_id(const char *fname);
int md_link_count(const char *fname);
void md_gct(struct rogue_time *rt_buf);
void md_gfmt(const char *fname, struct rogue_time *rt_buf);
boolean md_df(const char *fname);
void md_sleep(int nsecs);
char *md_getenv(const char *name);
void *md_malloc(size_t n);
void md_exit(int status);
void md_lock(boolean l);
void md_shell(const char *shell);

View File

@ -1,72 +0,0 @@
/* $NetBSD: main.c,v 1.9 2008/07/20 01:03:22 lukem Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* main.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* srand(3) */
#include <time.h> /* time(3) */
#include "rogue.h"
int
main(int argc, char *argv[]){
srand(time(NULL));
if(init(argc, argv)) /* restored game */
goto PL;
for (;;) {
clear_level();
make_level();
put_objects();
put_stairs();
add_traps();
put_mons();
put_player(party_room);
print_stats(STAT_ALL);
PL: play_level();
free_stuff(&level_objects);
free_stuff(&level_monsters);
}
}

View File

@ -1,368 +0,0 @@
/* $NetBSD: message.c,v 1.16 2023/08/01 07:55:57 mrg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* message.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <signal.h>
#include <termios.h>
#include <stdarg.h>
#include "rogue.h"
static char msgs[NMESSAGES][DCOLS] = {"", "", "", "", ""};
static short msg_col = 0, imsg = -1;
static boolean rmsg = 0;
boolean msg_cleared = 1;
char hunger_str[HUNGER_STR_LEN] = "";
const char *more = "-more-";
static void save_screen(void);
static
void
message(const char *msg, boolean intrpt)
{
cant_int = 1;
if (!save_is_interactive) {
return;
}
if (intrpt) {
interrupted = 1;
md_slurp();
}
if (!msg_cleared) {
mvaddstr(MIN_ROW-1, msg_col, more);
refresh();
wait_for_ack();
check_message();
}
if (!rmsg) {
imsg = (imsg + 1) % NMESSAGES;
(void)strlcpy(msgs[imsg], msg, sizeof(msgs[imsg]));
}
mvaddstr(MIN_ROW-1, 0, msg);
addch(' ');
refresh();
msg_cleared = 0;
msg_col = strlen(msg);
cant_int = 0;
if (did_int) {
did_int = 0;
onintr(0);
}
}
void
messagef(boolean intrpt, const char *fmt, ...)
{
va_list ap;
char buf[DCOLS];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
message(buf, intrpt);
}
void
remessage(short c)
{
if (imsg != -1) {
check_message();
rmsg = 1;
while (c > imsg) {
c -= NMESSAGES;
}
message(msgs[((imsg - c) % NMESSAGES)], 0);
rmsg = 0;
move(rogue.row, rogue.col);
refresh();
}
}
void
check_message(void)
{
if (msg_cleared) {
return;
}
move(MIN_ROW-1, 0);
clrtoeol();
refresh();
msg_cleared = 1;
}
int
get_input_line(const char *prompt, const char *insert,
char *buf, size_t buflen,
const char *if_cancelled,
boolean add_blank, boolean do_echo)
{
short ch;
size_t i = 0, n;
message(prompt, 0);
n = strlen(prompt);
if (insert[0]) {
mvaddstr(0, n + 1, insert);
(void)strlcpy(buf, insert, buflen);
i = strlen(buf);
move(0, (n + i + 1));
refresh();
}
while (((ch = rgetchar()) != '\r') && (ch != '\n') && (ch != CANCEL)) {
if ((ch >= ' ') && (ch <= '~') && (i < buflen-2)) {
if ((ch != ' ') || (i > 0)) {
buf[i++] = ch;
if (do_echo) {
addch(ch);
}
}
}
if ((ch == '\b') && (i > 0)) {
if (do_echo) {
mvaddch(0, i + n, ' ');
move(MIN_ROW-1, i+n);
}
i--;
}
refresh();
}
check_message();
if (add_blank) {
buf[i++] = ' ';
} else {
while ((i > 0) && (buf[i-1] == ' ')) {
i--;
}
}
buf[i] = 0;
if ((ch == CANCEL) || (i == 0) || ((i == 1) && add_blank)) {
if (if_cancelled) {
message(if_cancelled, 0);
}
return(0);
}
return(i);
}
int
rgetchar(void)
{
int ch;
for(;;) {
ch = getchar();
switch(ch) {
case '\022': /* ^R */
wrefresh(curscr);
break;
#ifdef UNIX_BSD4_2
case '\032': /* ^Z */
printf("%s", CL);
fflush(stdout);
tstp();
break;
#endif
case '&':
save_screen();
break;
default:
return(ch);
}
}
}
/*
Level: 99 Gold: 999999 Hp: 999(999) Str: 99(99) Arm: 99 Exp: 21/10000000 Hungry
0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5
*/
void
print_stats(int stat_mask)
{
char buf[16];
boolean label;
int row = DROWS - 1;
label = (stat_mask & STAT_LABEL) ? 1 : 0;
if (stat_mask & STAT_LEVEL) {
if (label) {
mvaddstr(row, 0, "Level: ");
}
/* max level taken care of in make_level() */
mvprintw(row, 7, "%-2d", cur_level);
}
if (stat_mask & STAT_GOLD) {
if (label) {
mvaddstr(row, 10, "Gold: ");
}
if (rogue.gold > MAX_GOLD) {
rogue.gold = MAX_GOLD;
}
mvprintw(row, 16, "%-6ld", rogue.gold);
}
if (stat_mask & STAT_HP) {
if (label) {
mvaddstr(row, 23, "Hp: ");
}
if (rogue.hp_max > MAX_HP) {
rogue.hp_current -= (rogue.hp_max - MAX_HP);
rogue.hp_max = MAX_HP;
}
snprintf(buf, sizeof(buf), "%d(%d)",
rogue.hp_current, rogue.hp_max);
mvprintw(row, 27, "%-8s", buf);
}
if (stat_mask & STAT_STRENGTH) {
if (label) {
mvaddstr(row, 36, "Str: ");
}
if (rogue.str_max > MAX_STRENGTH) {
rogue.str_current -= (rogue.str_max - MAX_STRENGTH);
rogue.str_max = MAX_STRENGTH;
}
snprintf(buf, sizeof(buf), "%d(%d)",
(rogue.str_current + add_strength), rogue.str_max);
mvprintw(row, 41, "%-6s", buf);
}
if (stat_mask & STAT_ARMOR) {
if (label) {
mvaddstr(row, 48, "Arm: ");
}
if (rogue.armor && (rogue.armor->d_enchant > MAX_ARMOR)) {
rogue.armor->d_enchant = MAX_ARMOR;
}
mvprintw(row, 53, "%-2d", get_armor_class(rogue.armor));
}
if (stat_mask & STAT_EXP) {
if (label) {
mvaddstr(row, 56, "Exp: ");
}
if (rogue.exp_points > MAX_EXP) {
rogue.exp_points = MAX_EXP;
}
if (rogue.exp > MAX_EXP_LEVEL) {
rogue.exp = MAX_EXP_LEVEL;
}
snprintf(buf, sizeof(buf), "%d/%lu",
rogue.exp, (unsigned long)rogue.exp_points);
mvprintw(row, 61, "%-11s", buf);
}
if (stat_mask & STAT_HUNGER) {
mvaddstr(row, 73, hunger_str);
clrtoeol();
}
refresh();
}
static void
save_screen(void)
{
FILE *fp;
short i, j;
char buf[DCOLS+2];
if ((fp = fopen(_PATH_SCREENDUMP, "w")) != NULL) {
for (i = 0; i < DROWS; i++) {
for (j=0; j<DCOLS; j++) {
buf[j] = mvinch(i, j);
}
/*buf[DCOLS] = 0; -- redundant */
for (j=DCOLS; j>0 && buf[j-1]==' '; j--);
buf[j] = 0;
fputs(buf, fp);
putc('\n', fp);
}
fclose(fp);
} else {
sound_bell();
}
}
void
sound_bell(void)
{
putchar(7);
fflush(stdout);
}
boolean
is_digit(int ch)
{
return((ch >= '0') && (ch <= '9'));
}
int
r_index(const char *str, int ch, boolean last)
{
int i = 0;
if (last) {
for (i = strlen(str) - 1; i >= 0; i--) {
if (str[i] == ch) {
return(i);
}
}
} else {
for (i = 0; str[i]; i++) {
if (str[i] == ch) {
return(i);
}
}
}
return(-1);
}

View File

@ -1,880 +0,0 @@
/* $NetBSD: monster.c,v 1.17 2013/08/11 03:44:27 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* monster.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
object level_monsters;
boolean mon_disappeared;
const char *const m_names[] = {
"aquator",
"bat",
"centaur",
"dragon",
"emu",
"venus fly-trap",
"griffin",
"hobgoblin",
"ice monster",
"jabberwock",
"kestrel",
"leprechaun",
"medusa",
"nymph",
"orc",
"phantom",
"quagga",
"rattlesnake",
"snake",
"troll",
"black unicorn",
"vampire",
"wraith",
"xeroc",
"yeti",
"zombie"
};
#define FILL 0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
static object mon_tab[MONSTERS] = {
{(ASLEEP|WAKENS|WANDERS|RUSTS),"0d0",25,'A',20,9,18,100,0,0, FILL},
{(ASLEEP|WANDERS|FLITS|FLIES),"1d3",10,'B',2,1,8,60,0,0, FILL},
{(ASLEEP|WANDERS),"3d3/2d5",32,'C',15,7,16,85,0,10, FILL},
{(ASLEEP|WAKENS|FLAMES),"4d6/4d9",145,'D',5000,21,126,100,0,90, FILL},
{(ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0, FILL},
{(HOLDS|STATIONARY),"5d5",73,'F',91,12,126,80,0,0, FILL},
{(ASLEEP|WAKENS|WANDERS|FLIES),"5d5/5d5",115,'G',
2000,20,126,85,0,10, FILL},
{(ASLEEP|WAKENS|WANDERS),"1d3/1d2",15,'H',3,1,10,67,0,0, FILL},
{(ASLEEP|FREEZES),"0d0",15,'I',5,2,11,68,0,0, FILL},
{(ASLEEP|WANDERS),"3d10/4d5",132,'J',3000,21,126,100,0,0, FILL},
{(ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0, FILL},
{(ASLEEP|STEALS_GOLD),"0d0",25,'L',21,6,16,75,0,0, FILL},
{(ASLEEP|WAKENS|WANDERS|CONFUSES),"4d4/3d7",97,'M',
250,18,126,85,0,25, FILL},
{(ASLEEP|STEALS_ITEM),"0d0",25,'N',39,10,19,75,0,100, FILL},
{(ASLEEP|WANDERS|WAKENS|SEEKS_GOLD),"1d6",25,'O',5,4,13,70,0,10, FILL},
{(ASLEEP|INVISIBLE|WANDERS|FLITS),"5d4",76,'P',120,15,24,80,0,50, FILL},
{(ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20, FILL},
{(ASLEEP|WAKENS|WANDERS|STINGS),"2d5",19,'R',10,3,12,70,0,0, FILL},
{(ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0, FILL},
{(ASLEEP|WAKENS|WANDERS),"4d6/1d4",75,'T',125,13,22,75,0,33, FILL},
{(ASLEEP|WAKENS|WANDERS),"4d10",90,'U',
200,17,26,85,0,33, FILL},
{(ASLEEP|WAKENS|WANDERS|DRAINS_LIFE),"1d14/1d4",55,'V',
350,19,126,85,0,18, FILL},
{(ASLEEP|WANDERS|DROPS_LEVEL),"2d8",45,'W',55,14,23,75,0,0, FILL},
{(ASLEEP|IMITATES),"4d6",42,'X',110,16,25,75,0,0, FILL},
{(ASLEEP|WANDERS),"3d6",35,'Y',50,11,20,80,0,20, FILL},
{(ASLEEP|WAKENS|WANDERS),"1d7",21,'Z',8,5,14,69,0,0, FILL}
};
static void aim_monster(object *);
static int flit(object *);
static int move_confused(object *);
static int mtry(object *, short, short);
static int no_room_for_monster(int);
static void put_m_at(short, short, object *);
static int rogue_is_around(int, int);
void
put_mons(void)
{
short i;
short n;
object *monster;
short row, col;
n = get_rand(4, 6);
for (i = 0; i < n; i++) {
monster = gr_monster(NULL, 0);
if ((monster->m_flags & WANDERS) && (rand() & 1)) {
wake_up(monster);
}
gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
put_m_at(row, col, monster);
}
}
object *
gr_monster(object *monster, int mn)
{
if (!monster) {
monster = alloc_object();
for (;;) {
mn = get_rand(0, MONSTERS-1);
if ((cur_level >= mon_tab[mn].first_level) &&
(cur_level <= mon_tab[mn].last_level)) {
break;
}
}
}
*monster = mon_tab[mn];
if (monster->m_flags & IMITATES) {
monster->disguise = gr_obj_char();
}
if (cur_level > (AMULET_LEVEL + 2)) {
monster->m_flags |= HASTED;
}
monster->trow = NO_ROOM;
return(monster);
}
void
mv_mons(void)
{
object *monster, *next_monster, *test_mons;
boolean flew;
if (haste_self % 2) {
return;
}
monster = level_monsters.next_monster;
while (monster) {
next_monster = monster->next_monster;
mon_disappeared = 0;
if (monster->m_flags & HASTED) {
mv_1_monster(monster, rogue.row, rogue.col);
if (mon_disappeared) {
goto NM;
}
} else if (monster->m_flags & SLOWED) {
monster->slowed_toggle = !monster->slowed_toggle;
if (monster->slowed_toggle) {
goto NM;
}
}
if ((monster->m_flags & CONFUSED) && move_confused(monster)) {
goto NM;
}
flew = 0;
if ( (monster->m_flags & FLIES) &&
!(monster->m_flags & NAPPING) &&
!mon_can_go(monster, rogue.row, rogue.col)) {
flew = 1;
mv_1_monster(monster, rogue.row, rogue.col);
if (mon_disappeared) {
goto NM;
}
}
if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
mv_1_monster(monster, rogue.row, rogue.col);
}
NM: test_mons = level_monsters.next_monster;
monster = NULL;
while (test_mons)
{
if (next_monster == test_mons)
{
monster = next_monster;
break;
}
test_mons = test_mons -> next_monster;
}
}
}
void
party_monsters(int rn, int n)
{
short i, j;
short row, col;
object *monster;
boolean found;
row = col = 0;
n += n;
for (i = 0; i < MONSTERS; i++) {
mon_tab[i].first_level -= (cur_level % 3);
}
for (i = 0; i < n; i++) {
if (no_room_for_monster(rn)) {
break;
}
for (j = found = 0; ((!found) && (j < 250)); j++) {
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);
if ((!(dungeon[row][col] & MONSTER)) &&
(dungeon[row][col] & (FLOOR | TUNNEL))) {
found = 1;
}
}
if (found) {
monster = gr_monster((object *)0, 0);
if (!(monster->m_flags & IMITATES)) {
monster->m_flags |= WAKENS;
}
put_m_at(row, col, monster);
}
}
for (i = 0; i < MONSTERS; i++) {
mon_tab[i].first_level += (cur_level % 3);
}
}
char
gmc_row_col(int row, int col)
{
object *monster;
if ((monster = object_at(&level_monsters, row, col)) != NULL) {
if ((!(detect_monster || see_invisible || r_see_invisible) &&
(monster->m_flags & INVISIBLE)) || blind) {
return(monster->trail_char);
}
if (monster->m_flags & IMITATES) {
return(monster->disguise);
}
return(monster->m_char);
} else {
return('&'); /* BUG if this ever happens */
}
}
char
gmc(object *monster)
{
if ((!(detect_monster || see_invisible || r_see_invisible) &&
(monster->m_flags & INVISIBLE))
|| blind) {
return(monster->trail_char);
}
if (monster->m_flags & IMITATES) {
return(monster->disguise);
}
return(monster->m_char);
}
void
mv_1_monster(object *monster, short row, short col)
{
short i, n;
boolean tried[6];
if (monster->m_flags & ASLEEP) {
if (monster->m_flags & NAPPING) {
if (--monster->nap_length <= 0) {
monster->m_flags &= (~(NAPPING | ASLEEP));
}
return;
}
if ((monster->m_flags & WAKENS) &&
rogue_is_around(monster->row, monster->col) &&
rand_percent(((stealthy > 0) ?
(WAKE_PERCENT / (STEALTH_FACTOR + stealthy)) :
WAKE_PERCENT))) {
wake_up(monster);
}
return;
} else if (monster->m_flags & ALREADY_MOVED) {
monster->m_flags &= (~ALREADY_MOVED);
return;
}
if ((monster->m_flags & FLITS) && flit(monster)) {
return;
}
if ((monster->m_flags & STATIONARY) &&
(!mon_can_go(monster, rogue.row, rogue.col))) {
return;
}
if (monster->m_flags & FREEZING_ROGUE) {
return;
}
if ((monster->m_flags & CONFUSES) && m_confuse(monster)) {
return;
}
if (mon_can_go(monster, rogue.row, rogue.col)) {
mon_hit(monster);
return;
}
if ((monster->m_flags & FLAMES) && flame_broil(monster)) {
return;
}
if ((monster->m_flags & SEEKS_GOLD) && seek_gold(monster)) {
return;
}
if ((monster->trow == monster->row) &&
(monster->tcol == monster->col)) {
monster->trow = NO_ROOM;
} else if (monster->trow != NO_ROOM) {
row = monster->trow;
col = monster->tcol;
}
if (monster->row > row) {
row = monster->row - 1;
} else if (monster->row < row) {
row = monster->row + 1;
}
if ((dungeon[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 ((dungeon[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)) {
goto O;
}
break;
case 1:
if (!tried[n] && mtry(monster, row, monster->col)) {
goto O;
}
break;
case 2:
if (!tried[n] && mtry(monster, row, monster->col+1)) {
goto O;
}
break;
case 3:
if (!tried[n] && mtry(monster, monster->row-1, col)) {
goto O;
}
break;
case 4:
if (!tried[n] && mtry(monster, monster->row, col)) {
goto O;
}
break;
case 5:
if (!tried[n] && mtry(monster, monster->row+1, col)) {
goto O;
}
break;
}
if (!tried[n]) {
tried[n] = 1;
} else {
goto NEXT_TRY;
}
}
O:
if ((monster->row == monster->o_row) && (monster->col == monster->o_col)) {
if (++(monster->o) > 4) {
if ((monster->trow == NO_ROOM) &&
(!mon_sees(monster, rogue.row, rogue.col))) {
monster->trow = get_rand(1, (DROWS - 2));
monster->tcol = get_rand(0, (DCOLS - 1));
} else {
monster->trow = NO_ROOM;
monster->o = 0;
}
}
} else {
monster->o_row = monster->row;
monster->o_col = monster->col;
monster->o = 0;
}
}
static int
mtry(object *monster, short row, short col)
{
if (mon_can_go(monster, row, col)) {
move_mon_to(monster, row, col);
return(1);
}
return(0);
}
void
move_mon_to(object *monster, short row, short col)
{
short c;
int mrow, mcol;
mrow = monster->row;
mcol = monster->col;
dungeon[mrow][mcol] &= ~MONSTER;
dungeon[row][col] |= MONSTER;
c = mvinch(mrow, mcol);
if ((c >= 'A') && (c <= 'Z')) {
if (!detect_monster) {
mvaddch(mrow, mcol, monster->trail_char);
} else {
if (rogue_can_see(mrow, mcol)) {
mvaddch(mrow, mcol, monster->trail_char);
} else {
if (monster->trail_char == '.') {
monster->trail_char = ' ';
}
mvaddch(mrow, mcol, monster->trail_char);
}
}
}
monster->trail_char = mvinch(row, col);
if (!blind && (detect_monster || rogue_can_see(row, col))) {
if ((!(monster->m_flags & INVISIBLE) ||
(detect_monster || see_invisible || r_see_invisible))) {
mvaddch(row, col, gmc(monster));
}
}
if ((dungeon[row][col] & DOOR) &&
(get_room_number(row, col) != cur_room) &&
(dungeon[mrow][mcol] == FLOOR) && !blind) {
mvaddch(mrow, mcol, ' ');
}
if (dungeon[row][col] & DOOR) {
dr_course(monster, ((dungeon[mrow][mcol] & TUNNEL) ? 1 : 0),
row, col);
} else {
monster->row = row;
monster->col = col;
}
}
int
mon_can_go(const object *monster, short row, short col)
{
object *obj;
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 ((!dungeon[monster->row][col]) || (!dungeon[row][monster->col])) {
return(0);
}
if ((!is_passable(row, col)) || (dungeon[row][col] & MONSTER)) {
return(0);
}
if ((monster->row!=row)&&(monster->col!=col)&&((dungeon[row][col]&DOOR) ||
(dungeon[monster->row][monster->col]&DOOR))) {
return(0);
}
if (!(monster->m_flags & (FLITS | CONFUSED | CAN_FLIT)) &&
(monster->trow == NO_ROOM)) {
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 (dungeon[row][col] & OBJECT) {
obj = object_at(&level_objects, row, col);
if ((obj->what_is == SCROL) && (obj->which_kind == SCARE_MONSTER)) {
return(0);
}
}
return(1);
}
void
wake_up(object *monster)
{
if (!(monster->m_flags & NAPPING)) {
monster->m_flags &= (~(ASLEEP | IMITATES | WAKENS));
}
}
void
wake_room(short rn, boolean entering, short row, short col)
{
object *monster;
short wake_percent;
boolean in_room;
wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;
if (stealthy > 0) {
wake_percent /= (STEALTH_FACTOR + stealthy);
}
monster = level_monsters.next_monster;
while (monster) {
in_room = (rn == get_room_number(monster->row, monster->col));
if (in_room) {
if (entering) {
monster->trow = NO_ROOM;
} else {
monster->trow = row;
monster->tcol = col;
}
}
if ((monster->m_flags & WAKENS) &&
(rn == get_room_number(monster->row, monster->col))) {
if (rand_percent(wake_percent)) {
wake_up(monster);
}
}
monster = monster->next_monster;
}
}
const char *
mon_name(const object *monster)
{
short ch;
if (blind || ((monster->m_flags & INVISIBLE) &&
!(detect_monster || see_invisible || r_see_invisible))) {
return("something");
}
if (halluc) {
ch = get_rand('A', 'Z') - 'A';
return(m_names[ch]);
}
ch = monster->m_char - 'A';
return(m_names[ch]);
}
static int
rogue_is_around(int row, int col)
{
short rdif, cdif, retval;
rdif = row - rogue.row;
cdif = col - rogue.col;
retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
return(retval);
}
void
wanderer(void)
{
object *monster;
short row, col, i;
boolean found = 0;
monster = NULL; /* XXXGCC -Wuninitialized [powerpc] */
for (i = 0; ((i < 15) && (!found)); i++) {
monster = gr_monster(NULL, 0);
if (!(monster->m_flags & (WAKENS | WANDERS))) {
free_object(monster);
} else {
found = 1;
}
}
if (found) {
found = 0;
wake_up(monster);
for (i = 0; ((i < 25) && (!found)); i++) {
gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
if (!rogue_can_see(row, col)) {
put_m_at(row, col, monster);
found = 1;
}
}
if (!found) {
free_object(monster);
}
}
}
void
show_monsters(void)
{
object *monster;
detect_monster = 1;
if (blind) {
return;
}
monster = level_monsters.next_monster;
while (monster) {
mvaddch(monster->row, monster->col, monster->m_char);
if (monster->m_flags & IMITATES) {
monster->m_flags &= (~IMITATES);
monster->m_flags |= WAKENS;
}
monster = monster->next_monster;
}
}
void
create_monster(void)
{
short row, col;
short i;
boolean found = 0;
object *monster;
row = rogue.row;
col = rogue.col;
for (i = 0; i < 9; i++) {
rand_around(i, &row, &col);
if (((row == rogue.row) && (col == rogue.col)) ||
(row < MIN_ROW) || (row > (DROWS-2)) ||
(col < 0) || (col > (DCOLS-1))) {
continue;
}
if ((!(dungeon[row][col] & MONSTER)) &&
(dungeon[row][col] & (FLOOR|TUNNEL|STAIRS|DOOR))) {
found = 1;
break;
}
}
if (found) {
monster = gr_monster((object *)0, 0);
put_m_at(row, col, monster);
mvaddch(row, col, gmc(monster));
if (monster->m_flags & (WANDERS | WAKENS)) {
wake_up(monster);
}
} else {
messagef(0, "you hear a faint cry of anguish in the distance");
}
}
static void
put_m_at(short row, short col, object *monster)
{
monster->row = row;
monster->col = col;
dungeon[row][col] |= MONSTER;
monster->trail_char = mvinch(row, col);
(void)add_to_pack(monster, &level_monsters, 0);
aim_monster(monster);
}
static void
aim_monster(object *monster)
{
short i, rn, d, r;
rn = get_room_number(monster->row, monster->col);
if (rn == NO_ROOM)
clean_up("aim_monster: monster not in room");
r = get_rand(0, 12);
for (i = 0; i < 4; i++) {
d = (r + i) % 4;
if (rooms[rn].doors[d].oth_room != NO_ROOM) {
monster->trow = rooms[rn].doors[d].door_row;
monster->tcol = rooms[rn].doors[d].door_col;
break;
}
}
}
int
rogue_can_see(int row, int col)
{
int retval;
retval = !blind &&
(((get_room_number(row, col) == cur_room) &&
!(rooms[cur_room].is_room & R_MAZE)) ||
rogue_is_around(row, col));
return(retval);
}
static int
move_confused(object *monster)
{
short i, row, col;
if (!(monster->m_flags & ASLEEP)) {
if (--monster->moves_confused <= 0) {
monster->m_flags &= (~CONFUSED);
}
if (monster->m_flags & STATIONARY) {
return rand() & 1;
} else if (rand_percent(15)) {
return(1);
}
row = monster->row;
col = monster->col;
for (i = 0; i < 9; i++) {
rand_around(i, &row, &col);
if ((row == rogue.row) && (col == rogue.col)) {
return(0);
}
if (mtry(monster, row, col)) {
return(1);
}
}
}
return(0);
}
static int
flit(object *monster)
{
short i, row, col;
if (!rand_percent(FLIT_PERCENT + ((monster->m_flags & FLIES) ? 20 : 0))) {
return(0);
}
if (rand_percent(10)) {
return(1);
}
row = monster->row;
col = monster->col;
for (i = 0; i < 9; i++) {
rand_around(i, &row, &col);
if ((row == rogue.row) && (col == rogue.col)) {
continue;
}
if (mtry(monster, row, col)) {
return(1);
}
}
return(1);
}
char
gr_obj_char(void)
{
short r;
const char *rs = "%!?]=/):*";
r = get_rand(0, 8);
return(rs[r]);
}
static int
no_room_for_monster(int rn)
{
short i, j;
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 (!(dungeon[i][j] & MONSTER)) {
return(0);
}
}
}
return(1);
}
void
aggravate(void)
{
object *monster;
messagef(0, "you hear a high pitched humming noise");
monster = level_monsters.next_monster;
while (monster) {
wake_up(monster);
monster->m_flags &= (~IMITATES);
if (rogue_can_see(monster->row, monster->col)) {
mvaddch(monster->row, monster->col, monster->m_char);
}
monster = monster->next_monster;
}
}
boolean
mon_sees(const object *monster, int row, int col)
{
short rn, rdif, cdif, retval;
rn = get_room_number(row, col);
if ( (rn != NO_ROOM) &&
(rn == get_room_number(monster->row, monster->col)) &&
!(rooms[rn].is_room & R_MAZE)) {
return(1);
}
rdif = row - monster->row;
cdif = col - monster->col;
retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
return(retval);
}
void
mv_aquatars(void)
{
object *monster;
monster = level_monsters.next_monster;
while (monster) {
if ((monster->m_char == 'A') &&
mon_can_go(monster, rogue.row, rogue.col)) {
mv_1_monster(monster, rogue.row, rogue.col);
monster->m_flags |= ALREADY_MOVED;
}
monster = monster->next_monster;
}
}

View File

@ -1,646 +0,0 @@
/* $NetBSD: move.c,v 1.13 2011/05/23 23:01:17 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* move.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
short m_moves = 0;
boolean jump = 0;
const char you_can_move_again[] = "you can move again";
static boolean can_turn(short, short);
static boolean check_hunger(boolean);
static char gr_dir(void);
static void heal(void);
static boolean next_to_something(int, int);
static void turn_passage(short, boolean);
int
one_move_rogue(short dirch, short pickup)
{
short row, col;
object *obj;
char desc[DCOLS];
short status, d = 0; /* XXX: GCC */
row = rogue.row;
col = rogue.col;
if (confused) {
dirch = gr_dir();
}
(void)is_direction(dirch, &d);
get_dir_rc(d, &row, &col, 1);
if (!can_move(rogue.row, rogue.col, row, col)) {
return(MOVE_FAILED);
}
if (being_held || bear_trap) {
if (!(dungeon[row][col] & MONSTER)) {
if (being_held) {
messagef(1, "you are being held");
} else {
messagef(0, "you are still stuck in the bear trap");
(void)reg_move();
}
return(MOVE_FAILED);
}
}
if (r_teleport) {
if (rand_percent(R_TELE_PERCENT)) {
tele();
return(STOPPED_ON_SOMETHING);
}
}
if (dungeon[row][col] & MONSTER) {
object *monster;
if((monster = object_at(&level_monsters, row, col)) != NULL)
rogue_hit(monster, 0);
(void)reg_move();
return MOVE_FAILED;
}
if (dungeon[row][col] & DOOR) {
if (cur_room == PASSAGE) {
cur_room = get_room_number(row, col);
if (cur_room == NO_ROOM)
clean_up("one_move_rogue: door to nowhere");
light_up_room(cur_room);
wake_room(cur_room, 1, row, col);
} else {
light_passage(row, col);
}
} else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
(dungeon[row][col] & TUNNEL)) {
light_passage(row, col);
wake_room(cur_room, 0, rogue.row, rogue.col);
darken_room(cur_room);
cur_room = PASSAGE;
} else if (dungeon[row][col] & TUNNEL) {
light_passage(row, col);
}
mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
mvaddch(row, col, rogue.fchar);
if (!jump) {
refresh();
}
rogue.row = row;
rogue.col = col;
if (dungeon[row][col] & OBJECT) {
if (levitate && pickup) {
return(STOPPED_ON_SOMETHING);
}
if (pickup && !levitate) {
if ((obj = pick_up(row, col, &status)) != NULL) {
get_desc(obj, desc, sizeof(desc));
if (obj->what_is == GOLD) {
free_object(obj);
messagef(1, "%s", desc);
goto NOT_IN_PACK;
}
} else if (!status) {
goto MVED;
} else {
goto MOVE_ON;
}
} else {
MOVE_ON:
obj = object_at(&level_objects, row, col);
get_desc(obj, desc, sizeof(desc));
messagef(1, "moved onto %s", desc);
goto NOT_IN_PACK;
}
messagef(1, "%s(%c)", desc, obj->ichar);
NOT_IN_PACK:
(void)reg_move();
return(STOPPED_ON_SOMETHING);
}
if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
if ((!levitate) && (dungeon[row][col] & TRAP)) {
trap_player(row, col);
}
(void)reg_move();
return(STOPPED_ON_SOMETHING);
}
MVED: if (reg_move()) { /* fainted from hunger */
return(STOPPED_ON_SOMETHING);
}
return((confused ? STOPPED_ON_SOMETHING : MOVED));
}
void
multiple_move_rogue(short 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 = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
(m == STOPPED_ON_SOMETHING) ||
interrupted) {
break;
}
} while (!next_to_something(row, col));
if ( (!interrupted) && passgo && (m == MOVE_FAILED) &&
(dungeon[rogue.row][rogue.col] & TUNNEL)) {
turn_passage(dirch + 96, 0);
}
break;
case 'H':
case 'J':
case 'K':
case 'L':
case 'B':
case 'Y':
case 'U':
case 'N':
while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED))
;
if ( (!interrupted) && passgo &&
(dungeon[rogue.row][rogue.col] & TUNNEL)) {
turn_passage(dirch + 32, 1);
}
break;
}
}
boolean
is_passable(int row, int col)
{
if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
(col > (DCOLS-1))) {
return(0);
}
if (dungeon[row][col] & HIDDEN) {
return((dungeon[row][col] & TRAP) ? 1 : 0);
}
return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
}
static boolean
next_to_something(int drow, int dcol)
{
short i, j, i_end, j_end, row, col;
short pass_count = 0;
unsigned short s;
if (confused) {
return(1);
}
if (blind) {
return(0);
}
i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
j_end = (rogue.col < (DCOLS-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;
}
row = rogue.row + i;
col = rogue.col + j;
s = dungeon[row][col];
if (s & HIDDEN) {
continue;
}
/* If the rogue used to be right, up, left, down, or right of
* row,col, and now isn't, then don't stop */
if (s & (MONSTER | OBJECT | STAIRS)) {
if (((row == drow) || (col == dcol)) &&
(!((row == rogue.row) || (col == rogue.col)))) {
continue;
}
return(1);
}
if (s & TRAP) {
if (!(s & HIDDEN)) {
if (((row == drow) || (col == dcol)) &&
(!((row == rogue.row) || (col == rogue.col)))) {
continue;
}
return(1);
}
}
if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
if (++pass_count > 1) {
return(1);
}
}
if ((s & DOOR) && ((i == 0) || (j == 0))) {
return(1);
}
}
}
return(0);
}
boolean
can_move(int row1, int col1, int row2, int col2)
{
if (!is_passable(row2, col2)) {
return(0);
}
if ((row1 != row2) && (col1 != col2)) {
if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
return(0);
}
if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
return(0);
}
}
return(1);
}
void
move_onto(void)
{
short ch, d;
boolean first_miss = 1;
while (!is_direction(ch = rgetchar(), &d)) {
sound_bell();
if (first_miss) {
messagef(0, "direction? ");
first_miss = 0;
}
}
check_message();
if (ch != CANCEL) {
(void)one_move_rogue(ch, 0);
}
}
boolean
is_direction(short c, short *d)
{
switch(c) {
case 'h':
*d = LEFT;
break;
case 'j':
*d = DOWN;
break;
case 'k':
*d = UPWARD;
break;
case 'l':
*d = RIGHT;
break;
case 'b':
*d = DOWNLEFT;
break;
case 'y':
*d = UPLEFT;
break;
case 'u':
*d = UPRIGHT;
break;
case 'n':
*d = DOWNRIGHT;
break;
case CANCEL:
break;
default:
return(0);
}
return(1);
}
static boolean
check_hunger(boolean msg_only)
{
short i, n;
boolean fainted = 0;
if (rogue.moves_left == HUNGRY) {
(void)strlcpy(hunger_str, "hungry", sizeof(hunger_str));
messagef(0, "%s", hunger_str);
print_stats(STAT_HUNGER);
}
if (rogue.moves_left == WEAK) {
(void)strlcpy(hunger_str, "weak", sizeof(hunger_str));
messagef(1, "%s", hunger_str);
print_stats(STAT_HUNGER);
}
if (rogue.moves_left <= FAINT) {
if (rogue.moves_left == FAINT) {
(void)strlcpy(hunger_str, "faint", sizeof(hunger_str));
messagef(1, "%s", hunger_str);
print_stats(STAT_HUNGER);
}
n = get_rand(0, (FAINT - rogue.moves_left));
if (n > 0) {
fainted = 1;
if (rand_percent(40)) {
rogue.moves_left++;
}
messagef(1, "you faint");
for (i = 0; i < n; i++) {
if(rand() & 1)
mv_mons();
}
messagef(1, "%s", you_can_move_again);
}
}
if (msg_only) {
return(fainted);
}
if (rogue.moves_left <= STARVE) {
killed_by(NULL, STARVATION);
}
switch(e_rings) {
/*case -2:
Subtract 0, i.e. do nothing.
break;*/
case -1:
rogue.moves_left -= (rogue.moves_left % 2);
break;
case 0:
rogue.moves_left--;
break;
case 1:
rogue.moves_left--;
(void)check_hunger(1);
rogue.moves_left -= (rogue.moves_left % 2);
break;
case 2:
rogue.moves_left--;
(void)check_hunger(1);
rogue.moves_left--;
break;
}
return(fainted);
}
boolean
reg_move(void)
{
boolean fainted;
if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
fainted = check_hunger(0);
} else {
fainted = 0;
}
mv_mons();
if (++m_moves >= 120) {
m_moves = 0;
wanderer();
}
if (halluc) {
if (!(--halluc)) {
unhallucinate();
} else {
hallucinate();
}
}
if (blind) {
if (!(--blind)) {
unblind();
}
}
if (confused) {
if (!(--confused)) {
unconfuse();
}
}
if (bear_trap) {
bear_trap--;
}
if (levitate) {
if (!(--levitate)) {
messagef(1, "you float gently to the ground");
if (dungeon[rogue.row][rogue.col] & TRAP) {
trap_player(rogue.row, rogue.col);
}
}
}
if (haste_self) {
if (!(--haste_self)) {
messagef(0, "you feel yourself slowing down");
}
}
heal();
if (auto_search > 0) {
search(auto_search, auto_search);
}
return(fainted);
}
void
rest(int count)
{
int i;
interrupted = 0;
for (i = 0; i < count; i++) {
if (interrupted) {
break;
}
(void)reg_move();
}
}
static char
gr_dir(void)
{
short d;
d = get_rand(1, 8);
switch(d) {
case 1:
d = 'j';
break;
case 2:
d = 'k';
break;
case 3:
d = 'l';
break;
case 4:
d = 'h';
break;
case 5:
d = 'y';
break;
case 6:
d = 'u';
break;
case 7:
d = 'b';
break;
case 8:
d = 'n';
break;
}
return(d);
}
static void
heal(void)
{
static short heal_exp = -1, n, c = 0;
static boolean alt;
if (rogue.hp_current == rogue.hp_max) {
c = 0;
return;
}
if (rogue.exp != heal_exp) {
heal_exp = rogue.exp;
switch(heal_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 (++c >= n) {
c = 0;
rogue.hp_current++;
if ((alt = !alt) != 0) {
rogue.hp_current++;
}
if ((rogue.hp_current += regeneration) > rogue.hp_max) {
rogue.hp_current = rogue.hp_max;
}
print_stats(STAT_HP);
}
}
static boolean
can_turn(short nrow, short ncol)
{
if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
return(1);
}
return(0);
}
static void
turn_passage(short dir, boolean fast)
{
short crow = rogue.row, ccol = rogue.col, turns = 0;
short ndir = 0;
if ((dir != 'h') && can_turn(crow, ccol + 1)) {
turns++;
ndir = 'l';
}
if ((dir != 'l') && can_turn(crow, ccol - 1)) {
turns++;
ndir = 'h';
}
if ((dir != 'k') && can_turn(crow + 1, ccol)) {
turns++;
ndir = 'j';
}
if ((dir != 'j') && can_turn(crow - 1, ccol)) {
turns++;
ndir = 'k';
}
if (turns == 1) {
multiple_move_rogue(ndir - (fast ? 32 : 96));
}
}

View File

@ -1,794 +0,0 @@
/* $NetBSD: object.c,v 1.14 2009/08/12 08:44:45 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* object.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
object level_objects;
unsigned short dungeon[DROWS][DCOLS];
short foods = 0;
char *fruit = NULL;
static object *free_list = NULL;
fighter rogue = {
INIT_AW, /* armor */
INIT_AW, /* weapon */
INIT_RINGS, /* left ring */
INIT_RINGS, /* right ring */
INIT_HP, /* Hp current */
INIT_HP, /* Hp max */
INIT_STR, /* Str current */
INIT_STR, /* Str max */
INIT_PACK, /* pack */
INIT_GOLD, /* gold */
INIT_EXPLEVEL, /* exp level */
INIT_EXP, /* exp points */
0, 0, /* row, col */
INIT_CHAR, /* char */
INIT_MOVES /* moves */
};
struct id id_potions[POTIONS] = {
{100, "blue ", "of increase strength ", 0},
{250, "red ", "of restore strength ", 0},
{100, "green ", "of healing ", 0},
{200, "grey ", "of extra healing ", 0},
{10, "brown ", "of poison ", 0},
{300, "clear ", "of raise level ", 0},
{10, "pink ", "of blindness ", 0},
{25, "white ", "of hallucination ", 0},
{100, "purple ", "of detect monster ", 0},
{100, "black ", "of detect things ", 0},
{10, "yellow ", "of confusion ", 0},
{80, "plaid ", "of levitation ", 0},
{150, "burgundy ", "of haste self ", 0},
{145, "beige ", "of see invisible ", 0}
};
struct id id_scrolls[SCROLS] = {
{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},
{80, "", "of create monster ",0},
{25, "", "of aggravate monster ",0},
{180, "", "of magic mapping ", 0},
{90, "", "of confuse monster ", 0}
};
struct id id_weapons[WEAPONS] = {
{150, "short bow ", "", 0},
{8, "darts ", "", 0},
{15, "arrows ", "", 0},
{27, "daggers ", "", 0},
{35, "shurikens ", "", 0},
{360, "mace ", "", 0},
{470, "long sword ", "", 0},
{580, "two-handed sword ", "", 0}
};
struct id 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 id id_wands[WANDS] = {
{25, "", "of teleport away ",0},
{50, "", "of slow monster ", 0},
{8, "", "of invisibility ",0},
{55, "", "of polymorph ",0},
{2, "", "of haste monster ",0},
{20, "", "of magic missile ",0},
{20, "", "of cancellation ",0},
{0, "", "of do nothing ",0},
{35, "", "of drain life ",0},
{20, "", "of cold ",0},
{20, "", "of fire ",0}
};
struct id id_rings[RINGS] = {
{250, "", "of stealth ",0},
{100, "", "of teleportation ", 0},
{255, "", "of regeneration ",0},
{295, "", "of slow digestion ",0},
{200, "", "of add strength ",0},
{250, "", "of sustain strength ",0},
{250, "", "of dexterity ",0},
{25, "", "of adornment ",0},
{300, "", "of see invisible ",0},
{290, "", "of maintain armor ",0},
{270, "", "of searching ",0},
};
static void gr_armor(object *);
static void gr_potion(object *);
static void gr_scroll(object *);
static void gr_wand(object *);
static void gr_weapon(object *, int);
static unsigned short gr_what_is(void);
static void make_party(void);
static void plant_gold(short, short, boolean);
static void put_gold(void);
static void rand_place(object *);
void
put_objects(void)
{
short i, n;
object *obj;
if (cur_level < max_level) {
return;
}
n = get_rand(2, 4) + (rand() & 1);
while (rand_percent(33)) {
n++;
}
if (party_room != NO_ROOM) {
make_party();
}
for (i = 0; i < n; i++) {
obj = gr_object();
rand_place(obj);
}
put_gold();
}
static void
put_gold(void)
{
short i, j;
short row,col;
boolean is_maze, is_room;
for (i = 0; i < MAXROOMS; i++) {
is_maze = (rooms[i].is_room & R_MAZE) ? 1 : 0;
is_room = (rooms[i].is_room & R_ROOM) ? 1 : 0;
if (!(is_room || is_maze)) {
continue;
}
if (is_maze || rand_percent(GOLD_PERCENT)) {
for (j = 0; j < 50; 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 ((dungeon[row][col] == FLOOR) ||
(dungeon[row][col] == TUNNEL)) {
plant_gold(row, col, is_maze);
break;
}
}
}
}
}
static void
plant_gold(short row, short col, boolean is_maze)
{
object *obj;
obj = alloc_object();
obj->row = row; obj->col = col;
obj->what_is = GOLD;
obj->quantity = get_rand((2 * cur_level), (16 * cur_level));
if (is_maze) {
obj->quantity += obj->quantity / 2;
}
dungeon[row][col] |= OBJECT;
(void)add_to_pack(obj, &level_objects, 0);
}
void
place_at(object *obj, int row, int col)
{
obj->row = row;
obj->col = col;
dungeon[row][col] |= OBJECT;
(void)add_to_pack(obj, &level_objects, 0);
}
object *
object_at(object *pack, short row, short col)
{
object *obj = NULL;
if (dungeon[row][col] & (MONSTER | OBJECT)) {
obj = pack->next_object;
while (obj && ((obj->row != row) || (obj->col != col))) {
obj = obj->next_object;
}
if (!obj) {
messagef(1, "object_at(): inconsistent");
}
}
return(obj);
}
object *
get_letter_object(int ch)
{
object *obj;
obj = rogue.pack.next_object;
while (obj && (obj->ichar != ch)) {
obj = obj->next_object;
}
return(obj);
}
void
free_stuff(object *objlist)
{
object *obj;
while (objlist->next_object) {
obj = objlist->next_object;
objlist->next_object =
objlist->next_object->next_object;
free_object(obj);
}
}
const char *
name_of(const object *obj)
{
const char *retstring;
switch(obj->what_is) {
case SCROL:
retstring = obj->quantity > 1 ? "scrolls " : "scroll ";
break;
case POTION:
retstring = obj->quantity > 1 ? "potions " : "potion ";
break;
case FOOD:
if (obj->which_kind == RATION) {
retstring = "food ";
} else {
retstring = fruit;
}
break;
case WAND:
retstring = is_wood[obj->which_kind] ? "staff " : "wand ";
break;
case WEAPON:
switch(obj->which_kind) {
case DART:
retstring=obj->quantity > 1 ? "darts " : "dart ";
break;
case ARROW:
retstring=obj->quantity > 1 ? "arrows " : "arrow ";
break;
case DAGGER:
retstring=obj->quantity > 1 ? "daggers " : "dagger ";
break;
case SHURIKEN:
retstring=obj->quantity > 1?"shurikens ":"shuriken ";
break;
default:
retstring = id_weapons[obj->which_kind].title;
}
break;
case ARMOR:
retstring = "armor ";
break;
case RING:
retstring = "ring ";
break;
case AMULET:
retstring = "amulet ";
break;
default:
retstring = "unknown ";
break;
}
return(retstring);
}
object *
gr_object(void)
{
object *obj;
obj = alloc_object();
if (foods < (cur_level / 3)) {
obj->what_is = FOOD;
foods++;
} else {
obj->what_is = gr_what_is();
}
switch(obj->what_is) {
case SCROL:
gr_scroll(obj);
break;
case POTION:
gr_potion(obj);
break;
case WEAPON:
gr_weapon(obj, 1);
break;
case ARMOR:
gr_armor(obj);
break;
case WAND:
gr_wand(obj);
break;
case FOOD:
get_food(obj, 0);
break;
case RING:
gr_ring(obj, 1);
break;
}
return(obj);
}
static unsigned short
gr_what_is(void)
{
short percent;
unsigned short what_is;
percent = get_rand(1, 91);
if (percent <= 30) {
what_is = SCROL;
} else if (percent <= 60) {
what_is = POTION;
} else if (percent <= 64) {
what_is = WAND;
} else if (percent <= 74) {
what_is = WEAPON;
} else if (percent <= 83) {
what_is = ARMOR;
} else if (percent <= 88) {
what_is = FOOD;
} else {
what_is = RING;
}
return(what_is);
}
static void
gr_scroll(object *obj)
{
short percent;
percent = get_rand(0, 91);
obj->what_is = SCROL;
if (percent <= 5) {
obj->which_kind = PROTECT_ARMOR;
} else if (percent <= 10) {
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 <= 50) {
obj->which_kind = SLEEP;
} else if (percent <= 55) {
obj->which_kind = SCARE_MONSTER;
} else if (percent <= 64) {
obj->which_kind = REMOVE_CURSE;
} else if (percent <= 69) {
obj->which_kind = ENCH_ARMOR;
} else if (percent <= 74) {
obj->which_kind = ENCH_WEAPON;
} else if (percent <= 80) {
obj->which_kind = AGGRAVATE_MONSTER;
} else if (percent <= 86) {
obj->which_kind = CON_MON;
} else {
obj->which_kind = MAGIC_MAPPING;
}
}
static void
gr_potion(object *obj)
{
short percent;
percent = get_rand(1, 118);
obj->what_is = POTION;
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 if (percent <= 105) {
obj->which_kind = POISON;
} else if (percent <= 110) {
obj->which_kind = LEVITATION;
} else if (percent <= 114) {
obj->which_kind = HASTE_SELF;
} else {
obj->which_kind = SEE_INVISIBLE;
}
}
static void
gr_weapon(object *obj, int assign_wk)
{
short percent;
short i;
short blessing, increment;
obj->what_is = WEAPON;
if (assign_wk) {
obj->which_kind = get_rand(0, (WEAPONS - 1));
}
if ((obj->which_kind == ARROW) || (obj->which_kind == DAGGER) ||
(obj->which_kind == SHURIKEN) || (obj->which_kind == DART)) {
obj->quantity = get_rand(3, 15);
obj->quiver = get_rand(0, 126);
} else {
obj->quantity = 1;
}
obj->hit_enchant = obj->d_enchant = 0;
percent = get_rand(1, 96);
blessing = get_rand(1, 3);
if (percent <= 32) {
if (percent <= 16) {
increment = 1;
} else {
increment = -1;
obj->is_cursed = 1;
}
for (i = 0; i < blessing; i++) {
if(rand() & 1)
obj->hit_enchant += increment;
else
obj->d_enchant += increment;
}
}
switch(obj->which_kind) {
case BOW:
case DART:
obj->damage = "1d1";
break;
case ARROW:
obj->damage = "1d2";
break;
case DAGGER:
obj->damage = "1d3";
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;
}
}
static void
gr_armor(object *obj)
{
short percent;
short blessing;
obj->what_is = ARMOR;
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_protected = 0;
obj->d_enchant = 0;
percent = get_rand(1, 100);
blessing = get_rand(1, 3);
if (percent <= 16) {
obj->is_cursed = 1;
obj->d_enchant -= blessing;
} else if (percent <= 33) {
obj->d_enchant += blessing;
}
}
static void
gr_wand(object *obj)
{
obj->what_is = WAND;
obj->which_kind = get_rand(0, (WANDS - 1));
obj->class = get_rand(3, 7);
}
void
get_food(object *obj, boolean force_ration)
{
obj->what_is = FOOD;
if (force_ration || rand_percent(80)) {
obj->which_kind = RATION;
} else {
obj->which_kind = FRUIT;
}
}
void
put_stairs(void)
{
short row, col;
gr_row_col(&row, &col, (FLOOR | TUNNEL));
dungeon[row][col] |= STAIRS;
}
int
get_armor_class(const object *obj)
{
if (obj) {
return(obj->class + obj->d_enchant);
}
return(0);
}
object *
alloc_object(void)
{
object *obj;
if (free_list) {
obj = free_list;
free_list = free_list->next_object;
} else if (!(obj = md_malloc(sizeof(object)))) {
messagef(0, "cannot allocate object, saving game");
save_into_file(error_file);
clean_up("alloc_object: save failed");
}
obj->quantity = 1;
obj->ichar = 'L';
obj->picked_up = obj->is_cursed = 0;
obj->in_use_flags = NOT_USED;
obj->identified = UNIDENTIFIED;
obj->damage = "1d1";
return(obj);
}
void
free_object(object *obj)
{
obj->next_object = free_list;
free_list = obj;
}
static void
make_party(void)
{
short n;
party_room = gr_room();
n = rand_percent(99) ? party_objects(party_room) : 11;
if (rand_percent(99)) {
party_monsters(party_room, n);
}
}
void
show_objects(void)
{
object *obj;
short mc, rc, row, col;
object *monster;
obj = level_objects.next_object;
while (obj) {
row = obj->row;
col = obj->col;
rc = get_mask_char(obj->what_is);
if (dungeon[row][col] & MONSTER) {
if ((monster =
object_at(&level_monsters, row, col)) != NULL) {
monster->trail_char = rc;
}
}
mc = mvinch(row, col);
if (((mc < 'A') || (mc > 'Z')) &&
((row != rogue.row) || (col != rogue.col))) {
mvaddch(row, col, rc);
}
obj = obj->next_object;
}
monster = level_monsters.next_object;
while (monster) {
if (monster->m_flags & IMITATES) {
mvaddch(monster->row, monster->col, (int)monster->disguise);
}
monster = monster->next_monster;
}
}
void
put_amulet(void)
{
object *obj;
obj = alloc_object();
obj->what_is = AMULET;
rand_place(obj);
}
static void
rand_place(object *obj)
{
short row, col;
gr_row_col(&row, &col, (FLOOR | TUNNEL));
place_at(obj, row, col);
}
void
c_object_for_wizard(void)
{
short ch, max, wk;
object *obj;
char buf[80];
max = 0;
if (pack_count(NULL) >= MAX_PACK_COUNT) {
messagef(0, "pack full");
return;
}
messagef(0, "type of object?");
while (r_index("!?:)]=/,\033", (ch = rgetchar()), 0) == -1) {
sound_bell();
}
check_message();
if (ch == '\033') {
return;
}
obj = alloc_object();
switch(ch) {
case '!':
obj->what_is = POTION;
max = POTIONS - 1;
break;
case '?':
obj->what_is = SCROL;
max = SCROLS - 1;
break;
case ',':
obj->what_is = AMULET;
break;
case ':':
get_food(obj, 0);
break;
case ')':
gr_weapon(obj, 0);
max = WEAPONS - 1;
break;
case ']':
gr_armor(obj);
max = ARMORS - 1;
break;
case '/':
gr_wand(obj);
max = WANDS - 1;
break;
case '=':
max = RINGS - 1;
obj->what_is = RING;
break;
}
if ((ch != ',') && (ch != ':')) {
GIL:
if (get_input_line("which kind?", "", buf, sizeof(buf), "", 0, 1)) {
wk = get_number(buf);
if ((wk >= 0) && (wk <= max)) {
obj->which_kind = wk;
if (obj->what_is == RING) {
gr_ring(obj, 0);
}
} else {
sound_bell();
goto GIL;
}
} else {
free_object(obj);
return;
}
}
get_desc(obj, buf, sizeof(buf));
messagef(0, "%s", buf);
(void)add_to_pack(obj, &rogue.pack, 1);
}

View File

@ -1,565 +0,0 @@
/* $NetBSD: pack.c,v 1.12 2011/05/23 23:01:17 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* pack.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "rogue.h"
const char curse_message[] = "you can't, it appears to be cursed";
static object *check_duplicate(object *, object *);
static boolean is_pack_letter(short *, unsigned short *);
static boolean mask_pack(const object *, unsigned short);
static short next_avail_ichar(void);
object *
add_to_pack(object *obj, object *pack, int condense)
{
object *op;
if (condense) {
if ((op = check_duplicate(obj, pack)) != NULL) {
free_object(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);
}
void
take_from_pack(object *obj, object *pack)
{
while (pack->next_object != obj) {
pack = pack->next_object;
}
pack->next_object = pack->next_object->next_object;
}
/* Note: *status is set to 0 if the rogue attempts to pick up a scroll
* of scare-monster and it turns to dust. *status is otherwise set to 1.
*/
object *
pick_up(int row, int col, short *status)
{
object *obj;
*status = 1;
if (levitate) {
messagef(0, "you're floating in the air!");
return NULL;
}
obj = object_at(&level_objects, row, col);
if (!obj) {
messagef(1, "pick_up(): inconsistent");
return(obj);
}
if ( (obj->what_is == SCROL) &&
(obj->which_kind == SCARE_MONSTER) &&
obj->picked_up) {
messagef(0, "the scroll turns to dust as you pick it up");
dungeon[row][col] &= (~OBJECT);
vanish(obj, 0, &level_objects);
*status = 0;
if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) {
id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED;
}
return NULL;
}
if (obj->what_is == GOLD) {
rogue.gold += obj->quantity;
dungeon[row][col] &= ~(OBJECT);
take_from_pack(obj, &level_objects);
print_stats(STAT_GOLD);
return(obj); /* obj will be free_object()ed in caller */
}
if (pack_count(obj) >= MAX_PACK_COUNT) {
messagef(1, "pack too full");
return NULL;
}
dungeon[row][col] &= ~(OBJECT);
take_from_pack(obj, &level_objects);
obj = add_to_pack(obj, &rogue.pack, 1);
obj->picked_up = 1;
return(obj);
}
void
drop(void)
{
object *obj, *new;
short ch;
char desc[DCOLS];
if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) {
messagef(0, "there's already something there");
return;
}
if (!rogue.pack.next_object) {
messagef(0, "you have nothing to drop");
return;
}
if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (obj->in_use_flags & BEING_WIELDED) {
if (obj->is_cursed) {
messagef(0, "%s", curse_message);
return;
}
unwield(rogue.weapon);
} else if (obj->in_use_flags & BEING_WORN) {
if (obj->is_cursed) {
messagef(0, "%s", curse_message);
return;
}
mv_aquatars();
unwear(rogue.armor);
print_stats(STAT_ARMOR);
} else if (obj->in_use_flags & ON_EITHER_HAND) {
if (obj->is_cursed) {
messagef(0, "%s", curse_message);
return;
}
un_put_on(obj);
}
obj->row = rogue.row;
obj->col = rogue.col;
if ((obj->quantity > 1) && (obj->what_is != WEAPON)) {
obj->quantity--;
new = alloc_object();
*new = *obj;
new->quantity = 1;
obj = new;
} else {
obj->ichar = 'L';
take_from_pack(obj, &rogue.pack);
}
place_at(obj, rogue.row, rogue.col);
get_desc(obj, desc, sizeof(desc));
messagef(0, "dropped %s", desc);
(void)reg_move();
}
static object *
check_duplicate(object *obj, object *pack)
{
object *op;
if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) {
return(0);
}
if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) {
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 == DAGGER) ||
(obj->which_kind == DART) ||
(obj->which_kind == SHURIKEN)) &&
(obj->quiver == op->quiver))) {
op->quantity += obj->quantity;
return(op);
}
}
op = op->next_object;
}
return(0);
}
static short
next_avail_ichar(void)
{
object *obj;
int i;
boolean ichars[26];
for (i = 0; i < 26; i++) {
ichars[i] = 0;
}
obj = rogue.pack.next_object;
while (obj) {
if (obj->ichar >= 'a' && obj->ichar <= 'z') {
ichars[(obj->ichar - 'a')] = 1;
}
obj = obj->next_object;
}
for (i = 0; i < 26; i++) {
if (!ichars[i]) {
return(i + 'a');
}
}
return('?');
}
void
wait_for_ack(void)
{
while (rgetchar() != ' ')
;
}
short
pack_letter(const char *prompt, unsigned short mask)
{
short ch;
unsigned short tmask = mask;
if (!mask_pack(&rogue.pack, mask)) {
messagef(0, "nothing appropriate");
return(CANCEL);
}
for (;;) {
messagef(0, "%s", prompt);
for (;;) {
ch = rgetchar();
if (!is_pack_letter(&ch, &mask)) {
sound_bell();
} else {
break;
}
}
if (ch == LIST) {
check_message();
mask = tmask;
inventory(&rogue.pack, mask);
} else {
break;
}
mask = tmask;
}
check_message();
return(ch);
}
void
take_off(void)
{
char desc[DCOLS];
object *obj;
if (rogue.armor) {
if (rogue.armor->is_cursed) {
messagef(0, "%s", curse_message);
} else {
mv_aquatars();
obj = rogue.armor;
unwear(rogue.armor);
get_desc(obj, desc, sizeof(desc));
messagef(0, "was wearing %s", desc);
print_stats(STAT_ARMOR);
(void)reg_move();
}
} else {
messagef(0, "not wearing any");
}
}
void
wear(void)
{
short ch;
object *obj;
char desc[DCOLS];
if (rogue.armor) {
messagef(0, "you're already wearing some");
return;
}
ch = pack_letter("wear what?", ARMOR);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (obj->what_is != ARMOR) {
messagef(0, "you can't wear that");
return;
}
obj->identified = 1;
get_desc(obj, desc, sizeof(desc));
messagef(0, "wearing %s", desc);
do_wear(obj);
print_stats(STAT_ARMOR);
(void)reg_move();
}
void
unwear(object *obj)
{
if (obj) {
obj->in_use_flags &= (~BEING_WORN);
}
rogue.armor = NULL;
}
void
do_wear(object *obj)
{
rogue.armor = obj;
obj->in_use_flags |= BEING_WORN;
obj->identified = 1;
}
void
wield(void)
{
short ch;
object *obj;
char desc[DCOLS];
if (rogue.weapon && rogue.weapon->is_cursed) {
messagef(0, "%s", curse_message);
return;
}
ch = pack_letter("wield what?", WEAPON);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "No such item.");
return;
}
if (obj->what_is & (ARMOR | RING)) {
messagef(0, "you can't wield %s",
((obj->what_is == ARMOR) ? "armor" : "rings"));
return;
}
if (obj->in_use_flags & BEING_WIELDED) {
messagef(0, "in use");
} else {
unwield(rogue.weapon);
get_desc(obj, desc, sizeof(desc));
messagef(0, "wielding %s", desc);
do_wield(obj);
(void)reg_move();
}
}
void
do_wield(object *obj)
{
rogue.weapon = obj;
obj->in_use_flags |= BEING_WIELDED;
}
void
unwield(object *obj)
{
if (obj) {
obj->in_use_flags &= (~BEING_WIELDED);
}
rogue.weapon = NULL;
}
void
call_it(void)
{
short ch;
object *obj;
struct id *id_table;
char buf[MAX_TITLE_LENGTH+2];
ch = pack_letter("call what?", (SCROL | POTION | WAND | RING));
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (!(obj->what_is & (SCROL | POTION | WAND | RING))) {
messagef(0, "surely you already know what that's called");
return;
}
id_table = get_id_table(obj);
if (get_input_line("call it:", "", buf, sizeof(buf),
id_table[obj->which_kind].title, 1, 1)) {
id_table[obj->which_kind].id_status = CALLED;
(void)strlcpy(id_table[obj->which_kind].title, buf,
sizeof(id_table[obj->which_kind].title));
}
}
short
pack_count(const object *new_obj)
{
object *obj;
short count = 0;
obj = rogue.pack.next_object;
while (obj) {
if (obj->what_is != WEAPON) {
count += obj->quantity;
} else if (!new_obj) {
count++;
} else if ((new_obj->what_is != WEAPON) ||
((obj->which_kind != ARROW) &&
(obj->which_kind != DAGGER) &&
(obj->which_kind != DART) &&
(obj->which_kind != SHURIKEN)) ||
(new_obj->which_kind != obj->which_kind) ||
(obj->quiver != new_obj->quiver)) {
count++;
}
obj = obj->next_object;
}
return(count);
}
static boolean
mask_pack(const object *pack, unsigned short mask)
{
while (pack->next_object) {
pack = pack->next_object;
if (pack->what_is & mask) {
return(1);
}
}
return(0);
}
static boolean
is_pack_letter(short *c, unsigned short *mask)
{
if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') ||
(*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) {
switch(*c) {
case '?':
*mask = SCROL;
break;
case '!':
*mask = POTION;
break;
case ':':
*mask = FOOD;
break;
case ')':
*mask = WEAPON;
break;
case ']':
*mask = ARMOR;
break;
case '/':
*mask = WAND;
break;
case '=':
*mask = RING;
break;
case ',':
*mask = AMULET;
break;
}
*c = LIST;
return(1);
}
return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST));
}
boolean
has_amulet(void)
{
return(mask_pack(&rogue.pack, AMULET));
}
void
kick_into_pack(void)
{
object *obj;
char desc[DCOLS];
short stat;
if (!(dungeon[rogue.row][rogue.col] & OBJECT)) {
messagef(0, "nothing here");
} else {
if ((obj = pick_up(rogue.row, rogue.col, &stat)) != NULL) {
get_desc(obj, desc, sizeof(desc));
if (obj->what_is == GOLD) {
messagef(0, "%s", desc);
free_object(obj);
} else {
messagef(0, "%s(%c)", desc, obj->ichar);
}
}
if (obj || (!stat)) {
(void)reg_move();
}
}
}

View File

@ -1,186 +0,0 @@
/* $NetBSD: play.c,v 1.10 2019/02/03 03:19:25 mrg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* play.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "rogue.h"
boolean interrupted = 0;
static const char unknown_command[] = "unknown command";
void
play_level(void)
{
short ch;
int count;
enum { NORMAL, COUNTED, CHECK } state;
state = NORMAL;
for(;;){
switch(state){
case NORMAL:
interrupted = 0;
if (hit_message[0]){
messagef(1, "%s", hit_message);
hit_message[0] = 0;
}
if(trap_door){
trap_door = 0;
return;
}
move(rogue.row, rogue.col);
refresh();
ch = rgetchar();
case CHECK:
check_message();
count = 0;
}
state = NORMAL;
switch(ch){
case '.': rest((count > 0) ? count : 1); break;
case 's': search(((count > 0) ? count : 1), 0); break;
case 'i': inventory(&rogue.pack, ALL_OBJECTS); 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':
(void)one_move_rogue(ch, 1);
break;
case 'H': case 'J': case 'K': case 'L': case 'Y': case 'U':
case 'N': case 'B': 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 ',': kick_into_pack(); break;
case 'd': drop(); break;
case 'P': put_on_ring(); break;
case 'R': remove_ring(); break;
case '\020':
do {
remessage(count++);
ch = rgetchar();
} while (ch == '\020');
state = CHECK;
break;
case '\027': wizardize(); break;
case '>': if(drop_check())
return;
break;
case '<': if(check_up())
return;
break;
case ')': case ']':
inv_armor_weapon(ch == ')');
break;
case '=': inv_rings(); break;
case '^': id_trap(); break;
case '/': id_type(); break;
case '?': id_com(); break;
case '!': do_shell(); break;
case 'o': edit_opts(); break;
case 'I': single_inv(0); break;
case 'T': take_off(); break;
case 'W': wear(); break;
case 'w': wield(); break;
case 'c': call_it(); break;
case 'z': zapp(); break;
case 't': throw(); break;
case 'v':
messagef(0, "rogue-clone: Version III (trinity mod)."
" (Tim Stoehr was here), tektronix!zeus!tims");
break;
case 'Q': quit(0);
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
move(rogue.row, rogue.col);
refresh();
do{
if(count < 100)
count = (10 * count) + (ch - '0');
ch = rgetchar();
}while (is_digit(ch));
if(ch != CANCEL)
state = COUNTED;
break;
case ' ': break;
case '\011': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
inventory(&level_objects, ALL_OBJECTS); break;
case '\023': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
draw_magic_map(); break;
case '\024': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
show_traps(); break;
case '\017': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
show_objects(); break;
case '\001': show_average_hp(); break;
case '\003': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
c_object_for_wizard(); break;
case '\015': if(!wizard){
messagef(0, "%s", unknown_command);
break;
}
show_monsters(); break;
case 'S': save_game(); break;
default: messagef(0, "%s", unknown_command); break;
}
}
}

View File

@ -1,2 +0,0 @@
#define get_rand(x, y) (((rand() % ((y) - (x))) + 1) + (x)) /* 0 index */
#define rand_percent(odds) ((get_rand(1, 100)) <= (odds))

View File

@ -1,332 +0,0 @@
/* $NetBSD: ring.c,v 1.9 2008/01/14 03:50:02 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* ring.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
static const char left_or_right[] = "left or right hand?";
static const char no_ring[] = "there's no ring on that hand";
short stealthy;
short r_rings;
short add_strength;
short e_rings;
short regeneration;
short ring_exp;
short auto_search;
boolean r_teleport;
boolean r_see_invisible;
boolean sustain_strength;
boolean maintain_armor;
void
put_on_ring(void)
{
short ch;
char desc[DCOLS];
object *ring;
if (r_rings == 2) {
messagef(0, "wearing two rings already");
return;
}
if ((ch = pack_letter("put on what?", RING)) == CANCEL) {
return;
}
if (!(ring = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (!(ring->what_is & RING)) {
messagef(0, "that's not a ring");
return;
}
if (ring->in_use_flags & (ON_LEFT_HAND | ON_RIGHT_HAND)) {
messagef(0, "that ring is already being worn");
return;
}
if (r_rings == 1) {
ch = (rogue.left_ring ? 'r' : 'l');
} else {
messagef(0, "%s", left_or_right);
do {
ch = rgetchar();
} while ((ch != CANCEL) && (ch != 'l') && (ch != 'r') && (ch != '\n') &&
(ch != '\r'));
}
if ((ch != 'l') && (ch != 'r')) {
check_message();
return;
}
if (((ch == 'l') && rogue.left_ring)||((ch == 'r') && rogue.right_ring)) {
check_message();
messagef(0, "there's already a ring on that hand");
return;
}
if (ch == 'l') {
do_put_on(ring, 1);
} else {
do_put_on(ring, 0);
}
ring_stats(1);
check_message();
get_desc(ring, desc, sizeof(desc));
messagef(0, "%s", desc);
(void)reg_move();
}
/*
* Do not call ring_stats() from within do_put_on(). It will cause
* serious problems when do_put_on() is called from read_pack() in restore().
*/
void
do_put_on(object *ring, boolean on_left)
{
if (on_left) {
ring->in_use_flags |= ON_LEFT_HAND;
rogue.left_ring = ring;
} else {
ring->in_use_flags |= ON_RIGHT_HAND;
rogue.right_ring = ring;
}
}
void
remove_ring(void)
{
boolean left = 0, right = 0;
short ch;
char buf[DCOLS];
object *ring;
ring = NULL;
if (r_rings == 0) {
inv_rings();
} else if (rogue.left_ring && !rogue.right_ring) {
left = 1;
} else if (!rogue.left_ring && rogue.right_ring) {
right = 1;
} else {
messagef(0, "%s", left_or_right);
do {
ch = rgetchar();
} while ((ch != CANCEL) && (ch != 'l') && (ch != 'r') &&
(ch != '\n') && (ch != '\r'));
left = (ch == 'l');
right = (ch == 'r');
check_message();
}
if (left || right) {
if (left) {
if (rogue.left_ring) {
ring = rogue.left_ring;
} else {
messagef(0, "%s", no_ring);
}
} else {
if (rogue.right_ring) {
ring = rogue.right_ring;
} else {
messagef(0, "%s", no_ring);
}
}
if (ring->is_cursed) {
messagef(0, "%s", curse_message);
} else {
un_put_on(ring);
get_desc(ring, buf, sizeof(buf));
messagef(0, "removed %s", buf);
(void)reg_move();
}
}
}
void
un_put_on(object *ring)
{
if (ring && (ring->in_use_flags & ON_LEFT_HAND)) {
ring->in_use_flags &= (~ON_LEFT_HAND);
rogue.left_ring = NULL;
} else if (ring && (ring->in_use_flags & ON_RIGHT_HAND)) {
ring->in_use_flags &= (~ON_RIGHT_HAND);
rogue.right_ring = NULL;
}
ring_stats(1);
}
void
gr_ring(object *ring, boolean assign_wk)
{
ring->what_is = RING;
if (assign_wk) {
ring->which_kind = get_rand(0, (RINGS - 1));
}
ring->class = 0;
switch(ring->which_kind) {
/*
case STEALTH:
break;
case SLOW_DIGEST:
break;
case REGENERATION:
break;
case R_SEE_INVISIBLE:
break;
case SUSTAIN_STRENGTH:
break;
case R_MAINTAIN_ARMOR:
break;
case SEARCHING:
break;
*/
case R_TELEPORT:
ring->is_cursed = 1;
break;
case ADD_STRENGTH:
case DEXTERITY:
while ((ring->class = (get_rand(0, 4) - 2)) == 0)
;
ring->is_cursed = (ring->class < 0);
break;
case ADORNMENT:
ring->is_cursed = rand() & 1;
break;
}
}
void
inv_rings(void)
{
char buf[DCOLS];
if (r_rings == 0) {
messagef(0, "not wearing any rings");
} else {
if (rogue.left_ring) {
get_desc(rogue.left_ring, buf, sizeof(buf));
messagef(0, "%s", buf);
}
if (rogue.right_ring) {
get_desc(rogue.right_ring, buf, sizeof(buf));
messagef(0, "%s", buf);
}
}
if (wizard) {
messagef(0, "ste %d, r_r %d, e_r %d, r_t %d, s_s %d, a_s %d, reg %d, r_e %d, s_i %d, m_a %d, aus %d",
stealthy, r_rings, e_rings, r_teleport, sustain_strength,
add_strength, regeneration, ring_exp, r_see_invisible,
maintain_armor, auto_search);
}
}
void
ring_stats(boolean pr)
{
short i;
object *ring;
stealthy = 0;
r_rings = 0;
e_rings = 0;
r_teleport = 0;
sustain_strength = 0;
add_strength = 0;
regeneration = 0;
ring_exp = 0;
r_see_invisible = 0;
maintain_armor = 0;
auto_search = 0;
for (i = 0; i < 2; i++) {
if (!(ring = ((i == 0) ? rogue.left_ring : rogue.right_ring))) {
continue;
}
r_rings++;
e_rings++;
switch(ring->which_kind) {
case STEALTH:
stealthy++;
break;
case R_TELEPORT:
r_teleport = 1;
break;
case REGENERATION:
regeneration++;
break;
case SLOW_DIGEST:
e_rings -= 2;
break;
case ADD_STRENGTH:
add_strength += ring->class;
break;
case SUSTAIN_STRENGTH:
sustain_strength = 1;
break;
case DEXTERITY:
ring_exp += ring->class;
break;
case ADORNMENT:
break;
case R_SEE_INVISIBLE:
r_see_invisible = 1;
break;
case MAINTAIN_ARMOR:
maintain_armor = 1;
break;
case SEARCHING:
auto_search += 2;
break;
}
}
if (pr) {
print_stats(STAT_STRENGTH);
relight();
}
}

View File

@ -1,107 +0,0 @@
.\" $NetBSD: rogue.6,v 1.11 2005/09/15 02:09:41 wiz Exp $
.\"
.\" Copyright (c) 1988, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)rogue.6 8.1 (Berkeley) 5/31/93
.\"
.Dd May 31, 1993
.Dt ROGUE 6
.Os
.Sh NAME
.Nm rogue
.Nd exploring The Dungeons of Doom
.Sh SYNOPSIS
.Nm
.Op Fl s
.Op Ar save_file
.\" .Op Fl r
.\" .Op Fl d
.Sh DESCRIPTION
.Nm
is a computer fantasy game with a new twist.
It is CRT oriented and the object of the game is to survive the attacks of
various monsters and get a lot of gold, rather than the puzzle solving
orientation of most computer fantasy games.
.Pp
To get started you really only need to know two commands.
The command
.Ic \&?
will give you a list of the available commands and the command
.Ic \&/
will identify the things you see on the screen.
.Pp
To win the game (as opposed to merely playing to beat other people's high
scores) you must locate the Amulet of Yendor which is somewhere below
the 20th level of the dungeon and get it out.
Nobody has achieved this yet and if somebody does, they will probably go
down in history as a hero among heroes.
.Pp
When the game ends, either by your death, when you quit, or if you (by
some miracle) manage to win,
.Nm
will give you a list of the top-ten scorers.
The scoring is based entirely upon how much gold you get.
There is a 10% penalty for getting yourself killed.
.Pp
If
.Ar save_file
is specified,
rogue will be restored from the specified saved game file.
.Pp
The
.Fl s
option will print out the list of scores.
.Pp
For more detailed directions, read the document
.Rs
.%T A Guide to the Dungeons of Doom
.Re
.Sh FILES
.Bl -tag -width /var/games/rogue.scores -compact
.It Pa /var/games/rogue.scores
Score file
.It Pa ~/rogue.save
Default save file
.El
.Sh SEE ALSO
.Rs
.%A Michael C. Toy
.%A Kenneth C. R. C. Arnold
.%T A guide to the Dungeons of Doom
.Re
.Sh AUTHORS
.An Timothy Stoehr
.An Michael C. Toy
.An Kenneth C. R. C. Arnold
.An Glenn Wichman
.Sh BUGS
Probably infinite, although none are known.
However, that Ice Monsters sometimes transfix you permanently is
.Em not
a bug.
It's a feature.

View File

@ -1,702 +0,0 @@
/* $NetBSD: rogue.h,v 1.24 2013/08/11 03:44:27 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)rogue.h 8.1 (Berkeley) 5/31/93
*/
/*
* rogue.h
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) This notice shall not be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*/
#define __dead
#define __printflike(a,b)
#define __unreachable()
#define __unused
#define boolean char
#define NOTHING ((unsigned short) 0)
#define OBJECT ((unsigned short) 01)
#define MONSTER ((unsigned short) 02)
#define STAIRS ((unsigned short) 04)
#define HORWALL ((unsigned short) 010)
#define VERTWALL ((unsigned short) 020)
#define DOOR ((unsigned short) 040)
#define FLOOR ((unsigned short) 0100)
#define TUNNEL ((unsigned short) 0200)
#define TRAP ((unsigned short) 0400)
#define HIDDEN ((unsigned short) 01000)
#define ARMOR ((unsigned short) 01)
#define WEAPON ((unsigned short) 02)
#define SCROL ((unsigned short) 04)
#define POTION ((unsigned short) 010)
#define GOLD ((unsigned short) 020)
#define FOOD ((unsigned short) 040)
#define WAND ((unsigned short) 0100)
#define RING ((unsigned short) 0200)
#define AMULET ((unsigned short) 0400)
#define ALL_OBJECTS ((unsigned short) 0777)
#define LEATHER 0
#define RINGMAIL 1
#define SCALE 2
#define CHAIN 3
#define BANDED 4
#define SPLINT 5
#define PLATE 6
#define ARMORS 7
#define BOW 0
#define DART 1
#define ARROW 2
#define DAGGER 3
#define SHURIKEN 4
#define MACE 5
#define LONG_SWORD 6
#define TWO_HANDED_SWORD 7
#define WEAPONS 8
#define MAX_PACK_COUNT 24
#define PROTECT_ARMOR 0
#define HOLD_MONSTER 1
#define ENCH_WEAPON 2
#define ENCH_ARMOR 3
#define IDENTIFY 4
#define TELEPORT 5
#define SLEEP 6
#define SCARE_MONSTER 7
#define REMOVE_CURSE 8
#define CREATE_MONSTER 9
#define AGGRAVATE_MONSTER 10
#define MAGIC_MAPPING 11
#define CON_MON 12
#define SCROLS 13
#define INCREASE_STRENGTH 0
#define RESTORE_STRENGTH 1
#define HEALING 2
#define EXTRA_HEALING 3
#define POISON 4
#define RAISE_LEVEL 5
#define BLINDNESS 6
#define HALLUCINATION 7
#define DETECT_MONSTER 8
#define DETECT_OBJECTS 9
#define CONFUSION 10
#define LEVITATION 11
#define HASTE_SELF 12
#define SEE_INVISIBLE 13
#define POTIONS 14
#define TELE_AWAY 0
#define SLOW_MONSTER 1
#define INVISIBILITY 2
#define POLYMORPH 3
#define HASTE_MONSTER 4
#define MAGIC_MISSILE 5
#define CANCELLATION 6
#define DO_NOTHING 7
#define DRAIN_LIFE 8
#define COLD 9
#define FIRE 10
#define WANDS 11
#define STEALTH 0
#define R_TELEPORT 1
#define REGENERATION 2
#define SLOW_DIGEST 3
#define ADD_STRENGTH 4
#define SUSTAIN_STRENGTH 5
#define DEXTERITY 6
#define ADORNMENT 7
#define R_SEE_INVISIBLE 8
#define MAINTAIN_ARMOR 9
#define SEARCHING 10
#define RINGS 11
#define RATION 0
#define FRUIT 1
#define NOT_USED ((unsigned short) 0)
#define BEING_WIELDED ((unsigned short) 01)
#define BEING_WORN ((unsigned short) 02)
#define ON_LEFT_HAND ((unsigned short) 04)
#define ON_RIGHT_HAND ((unsigned short) 010)
#define ON_EITHER_HAND ((unsigned short) 014)
#define BEING_USED ((unsigned short) 017)
#define NO_TRAP -1
#define TRAP_DOOR 0
#define BEAR_TRAP 1
#define TELE_TRAP 2
#define DART_TRAP 3
#define SLEEPING_GAS_TRAP 4
#define RUST_TRAP 5
#define TRAPS 6
#define STEALTH_FACTOR 3
#define R_TELE_PERCENT 8
#define UNIDENTIFIED ((unsigned short) 00) /* MUST BE ZERO! */
#define IDENTIFIED ((unsigned short) 01)
#define CALLED ((unsigned short) 02)
#define DROWS 24
#define DCOLS 80
#define NMESSAGES 5
#define MAX_TITLE_LENGTH 30
#define MAXSYLLABLES 40
#define MAX_METAL 14
#define WAND_MATERIALS 30
#define GEMS 14
#define GOLD_PERCENT 46
#define MAX_OPT_LEN 40
#define MAX_ID_TITLE_LEN 64
struct id {
short value;
char title[MAX_ID_TITLE_LEN];
const char *real;
unsigned short id_status;
};
/* The following #defines provide more meaningful names for some of the
* struct object fields that are used for monsters. This, since each monster
* and object (scrolls, potions, etc) are represented by a struct object.
* Ideally, this should be handled by some kind of union structure.
*/
#define m_damage damage
#define hp_to_kill quantity
#define m_char ichar
#define first_level is_protected
#define last_level is_cursed
#define m_hit_chance class
#define stationary_damage identified
#define drop_percent which_kind
#define trail_char d_enchant
#define slowed_toggle quiver
#define moves_confused hit_enchant
#define nap_length picked_up
#define disguise what_is
#define next_monster next_object
struct obj { /* comment is monster meaning */
unsigned long m_flags; /* monster flags */
const char *damage; /* damage it does */
short quantity; /* hit points to kill */
short ichar; /* 'A' is for aquator */
short kill_exp; /* exp for killing it */
short is_protected; /* level starts */
short is_cursed; /* level ends */
short class; /* chance of hitting you */
short identified; /* 'F' damage, 1,2,3... */
unsigned short which_kind; /* item carry/drop % */
short o_row, o_col, o; /* o is how many times stuck at o_row, o_col */
short row, col; /* current row, col */
short d_enchant; /* room char when detect_monster */
short quiver; /* monster slowed toggle */
short trow, tcol; /* target row, col */
short hit_enchant; /* how many moves is confused */
unsigned short what_is; /* imitator's charactor (?!%: */
short picked_up; /* sleep from wand of sleep */
unsigned short in_use_flags;
struct obj *next_object; /* next monster */
};
typedef struct obj object;
#define INIT_AW NULL
#define INIT_RINGS NULL
#define INIT_HP 12
#define INIT_STR 16
#define INIT_EXPLEVEL 1
#define INIT_EXP 0
#define INIT_PACK {0,NULL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL}
#define INIT_GOLD 0
#define INIT_CHAR '@'
#define INIT_MOVES 1250
struct fightr {
object *armor;
object *weapon;
object *left_ring, *right_ring;
short hp_current;
short hp_max;
short str_current;
short str_max;
object pack;
long gold;
short exp;
long exp_points;
short row, col;
short fchar;
short moves_left;
};
typedef struct fightr fighter;
struct dr {
short oth_room;
short oth_row,
oth_col;
short door_row,
door_col;
};
typedef struct dr door;
struct rm {
short bottom_row, right_col, left_col, top_row;
door doors[4];
unsigned short is_room;
};
typedef struct rm room;
#define MAXROOMS 9
#define BIG_ROOM 10
#define NO_ROOM (-1)
#define PASSAGE (-3) /* cur_room value */
#define AMULET_LEVEL 26
#define R_NOTHING ((unsigned short) 01)
#define R_ROOM ((unsigned short) 02)
#define R_MAZE ((unsigned short) 04)
#define R_DEADEND ((unsigned short) 010)
#define R_CROSS ((unsigned short) 020)
#define MAX_EXP_LEVEL 21
#define MAX_EXP 10000001L
#define MAX_GOLD 999999
#define MAX_ARMOR 99
#define MAX_HP 999
#define MAX_STRENGTH 99
#define LAST_DUNGEON 99
#define STAT_LEVEL 01
#define STAT_GOLD 02
#define STAT_HP 04
#define STAT_STRENGTH 010
#define STAT_ARMOR 020
#define STAT_EXP 040
#define STAT_HUNGER 0100
#define STAT_LABEL 0200
#define STAT_ALL 0377
#define PARTY_TIME 10 /* one party somewhere in each 10 level span */
#define MAX_TRAPS 10 /* maximum traps per level */
#define HIDE_PERCENT 12
struct tr {
short trap_type;
short trap_row, trap_col;
};
typedef struct tr trap;
extern fighter rogue;
extern room rooms[];
extern trap traps[];
extern unsigned short dungeon[DROWS][DCOLS];
extern object level_objects;
extern struct id id_scrolls[];
extern struct id id_potions[];
extern struct id id_wands[];
extern struct id id_rings[];
extern struct id id_weapons[];
extern struct id id_armors[];
extern object level_monsters;
#define MONSTERS 26
#define HASTED 01L
#define SLOWED 02L
#define INVISIBLE 04L
#define ASLEEP 010L
#define WAKENS 020L
#define WANDERS 040L
#define FLIES 0100L
#define FLITS 0200L
#define CAN_FLIT 0400L /* can, but usually doesn't, flit */
#define CONFUSED 01000L
#define RUSTS 02000L
#define HOLDS 04000L
#define FREEZES 010000L
#define STEALS_GOLD 020000L
#define STEALS_ITEM 040000L
#define STINGS 0100000L
#define DRAINS_LIFE 0200000L
#define DROPS_LEVEL 0400000L
#define SEEKS_GOLD 01000000L
#define FREEZING_ROGUE 02000000L
#define RUST_VANISHED 04000000L
#define CONFUSES 010000000L
#define IMITATES 020000000L
#define FLAMES 040000000L
#define STATIONARY 0100000000L /* damage will be 1,2,3,... */
#define NAPPING 0200000000L /* can't wake up for a while */
#define ALREADY_MOVED 0400000000L
#define SPECIAL_HIT (RUSTS|HOLDS|FREEZES|STEALS_GOLD|STEALS_ITEM|STINGS|DRAINS_LIFE|DROPS_LEVEL)
#define WAKE_PERCENT 45
#define FLIT_PERCENT 40
#define PARTY_WAKE_PERCENT 75
#define HYPOTHERMIA 1
#define STARVATION 2
#define POISON_DART 3
#define QUIT 4
#define WIN 5
#define KFIRE 6
#define UPWARD 0
#define UPRIGHT 1
#define RIGHT 2
#define DOWNRIGHT 3
#define DOWN 4
#define DOWNLEFT 5
#define LEFT 6
#define UPLEFT 7
#define DIRS 8
#define ROW1 7
#define ROW2 15
#define COL1 26
#define COL2 52
#define MOVED 0
#define MOVE_FAILED -1
#define STOPPED_ON_SOMETHING -2
#define CANCEL '\033'
#define LIST '*'
#define HUNGRY 300
#define WEAK 150
#define FAINT 20
#define STARVE 0
#define MIN_ROW 1
struct rogue_time {
short year; /* >= 1987 */
short month; /* 1 - 12 */
short day; /* 1 - 31 */
short hour; /* 0 - 23 */
short minute; /* 0 - 59 */
short second; /* 0 - 59 */
};
#include <curses.h>
/*
* external routine declarations.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
object *alloc_object(void);
object *get_letter_object(int);
object *gr_monster(object *, int);
object *gr_object(void);
char *md_getenv(const char *);
const char *
md_gln(void);
void *md_malloc(size_t);
const char *mon_name(const object *);
const char *name_of(const object *);
object *object_at(object *, short, short);
object *pick_up(int, int, short *);
void add_exp(int, boolean);
void add_traps(void);
void aggravate(void);
void bounce(short, short, short, short, short);
void byebye(int);
void c_object_for_wizard(void);
void call_it(void);
boolean can_move(int, int, int, int);
void check_gold_seeker(object *);
boolean check_imitator(object *);
void check_message(void);
int check_up(void);
void clean_up(const char *) __dead;
void clear_level(void);
void cnfs(void);
void cough_up(object *);
void create_monster(void);
void darken_room(short);
void do_put_on(object *, boolean);
void do_shell(void);
void do_wear(object *);
void do_wield(object *);
void dr_course(object *, boolean, short, short);
void draw_magic_map(void);
void drop(void);
int drop_check(void);
void eat(void);
void edit_opts(void);
void error_save(int) __dead;
void fight(boolean);
boolean flame_broil(object *);
void free_object(object *);
void free_stuff(object *);
int get_armor_class(const object *);
int get_damage(const char *, boolean);
void get_desc(const object *, char *, size_t);
void get_dir_rc(short, short *, short *, short);
char get_dungeon_char(short, short);
void get_food(object *, boolean);
int get_hit_chance(const object *);
int get_input_line(const char *, const char *, char *, size_t, const char *, boolean, boolean);
char get_mask_char(unsigned short);
int get_number(const char *);
short get_room_number(int, int);
void get_wand_and_ring_materials(void);
int get_weapon_damage(const object *);
char gmc(object *);
char gmc_row_col(int, int);
char gr_obj_char(void);
void gr_ring(object *, boolean);
short gr_room(void);
void gr_row_col(short *, short *, unsigned short);
void hallucinate(void);
boolean has_amulet(void);
int hp_raise(void);
void id_com(void);
void id_trap(void);
void id_type(void);
boolean imitating(short, short);
int init(int, char **);
void insert_score(char [][82], char [][30], const char *, short, short, const object *, int);
void inv_armor_weapon(boolean);
void inv_rings(void);
void inventory(const object *, unsigned short);
boolean is_all_connected(void);
boolean is_digit(int);
boolean is_direction(short, short *);
boolean is_passable(int, int);
boolean is_vowel(short);
void kick_into_pack(void);
void killed_by(const object *, short) __dead;
long lget_number(const char *);
void light_passage(int, int);
void light_up_room(int);
boolean m_confuse(object *);
void make_level(void);
void make_scroll_titles(void);
boolean md_df(const char *);
void md_exit(int) __dead;
void md_gct(struct rogue_time *);
int md_get_file_id(const char *);
void md_gfmt(const char *, struct rogue_time *);
void md_heed_signals(void);
void md_ignore_signals(void);
int md_link_count(const char *);
void md_lock(boolean);
void md_shell(const char *);
void md_sleep(int);
void md_slurp(void);
/*void message(const char *, boolean);*/
void messagef(boolean, const char *, ...) __printflike(2, 3);
void mix_colors(void);
int mon_can_go(const object *, short, short);
int mon_damage(object *, short);
void mon_hit(object *);
boolean mon_sees(const object *, int, int);
void move_mon_to(object *, short, short);
void move_onto(void);
void multiple_move_rogue(short);
void mv_1_monster(object *, short, short);
void mv_aquatars(void);
void mv_mons(void);
int name_cmp(char *, const char *);
void nickize(char *, const char *, const char *);
int one_move_rogue(short, short);
void onintr(int);
short pack_count(const object *);
short pack_letter(const char *, unsigned short);
void pad(const char *, short);
void party_monsters(int, int);
short party_objects(int);
void place_at(object *, int, int);
void play_level(void);
void print_stats(int);
void put_amulet(void);
void put_mons(void);
void put_objects(void);
void put_on_ring(void);
void put_player(short);
void put_scores(const object *, short) __dead;
void put_stairs(void);
void quaff(void);
void quit(boolean);
int r_index(const char *, int, boolean);
void rand_around(short, short *, short *);
void read_scroll(void);
boolean reg_move(void);
void relight(void);
void remessage(short);
void remove_ring(void);
void rest(int);
void restore(const char *);
int rgetchar(void);
void ring_stats(boolean);
int rogue_can_see(int, int);
void rogue_damage(short, object *, short);
void rogue_hit(object *, boolean);
void rust(object *);
void s_con_mon(object *);
void save_game(void);
void save_into_file(const char *);
void search(short, boolean);
boolean seek_gold(object *);
void show_average_hp(void);
void show_monsters(void);
void show_objects(void);
void show_traps(void);
void single_inv(short);
void sound_bell(void);
void special_hit(object *);
void start_window(void);
void stop_window(void);
void take_a_nap(void);
void take_from_pack(object *, object *);
void take_off(void);
void tele(void);
void throw(void);
void trap_player(short, short);
void un_put_on(object *);
void unblind(void);
void unconfuse(void);
void unhallucinate(void);
void unwear(object *);
void unwield(object *);
void vanish(object *, short, object *);
void wait_for_ack(void);
void wake_room(short, boolean, short, short);
void wake_up(object *);
void wanderer(void);
void wear(void);
void wield(void);
void win(void) __dead;
void wizardize(void);
long xxx(boolean);
void xxxx(char *, short);
void zapp(void);
object *add_to_pack(object *, object *, int);
struct id *get_id_table(const object *);
extern boolean ask_quit;
extern boolean being_held;
extern boolean cant_int;
extern boolean con_mon;
extern boolean detect_monster;
extern boolean did_int;
extern boolean interrupted;
extern boolean is_wood[];
extern boolean jump;
extern boolean maintain_armor;
extern boolean mon_disappeared;
extern boolean msg_cleared;
extern boolean no_skull;
extern boolean passgo;
extern boolean r_see_invisible;
extern boolean r_teleport;
extern boolean save_is_interactive;
extern boolean score_only;
extern boolean see_invisible;
extern boolean sustain_strength;
extern boolean trap_door;
extern boolean wizard;
#define HIT_MESSAGE_SIZE 80
extern char hit_message[HIT_MESSAGE_SIZE];
#define HUNGER_STR_LEN 8
extern char hunger_str[HUNGER_STR_LEN];
extern char login_name[MAX_OPT_LEN];
extern const char *byebye_string;
extern const char curse_message[];
extern const char *error_file;
extern char *fruit;
extern const char *const m_names[];
extern const char *more;
extern const char *new_level_message;
extern char *nick_name;
extern const char *press_space;
extern char *save_file;
extern const char you_can_move_again[];
extern const long level_points[];
extern short add_strength;
extern short auto_search;
extern short bear_trap;
extern short blind;
extern short confused;
extern short cur_level;
extern short cur_room;
extern short e_rings;
extern short extra_hp;
extern short foods;
extern short halluc;
extern short haste_self;
extern short less_hp;
extern short levitate;
extern short m_moves;
extern short max_level;
extern short party_room;
extern short r_rings;
extern short regeneration;
extern short ring_exp;
extern short stealthy;
extern gid_t gid;
extern gid_t egid;

View File

@ -1,664 +0,0 @@
/* $NetBSD: room.c,v 1.14 2019/02/03 03:19:25 mrg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* room.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
room rooms[MAXROOMS];
static boolean rooms_visited[MAXROOMS];
#define NOPTS 7
static const struct option {
const char *prompt;
boolean is_bool;
char **strval;
boolean *bval;
} options[NOPTS] = {
{
"Show position only at end of run (\"jump\"): ",
1, NULL, &jump
},
{
"Follow turnings in passageways (\"passgo\"): ",
1, NULL, &passgo
},
{
"Don't print skull when killed (\"noskull\" or \"notombstone\"): ",
1, NULL, &no_skull
},
{
"Ask player before saying 'Okay, bye-bye!' (\"askquit\"): ",
1, NULL, &ask_quit
},
{
"Name (\"name\"): ",
0, &nick_name, NULL
},
{
"Fruit (\"fruit\"): ",
0, &fruit, NULL
},
{
"Save file (\"file\"): ",
0, &save_file, NULL
}
};
static boolean get_oth_room(short, short *, short *);
static void opt_erase(int);
static void opt_go(int);
static void opt_show(int);
static void visit_rooms(int);
void
light_up_room(int rn)
{
short i, j;
if (!blind) {
for (i = rooms[rn].top_row;
i <= rooms[rn].bottom_row; i++) {
for (j = rooms[rn].left_col;
j <= rooms[rn].right_col; j++) {
if (dungeon[i][j] & MONSTER) {
object *monster;
if ((monster = object_at(
&level_monsters, i, j)) != NULL) {
dungeon[monster->row][monster->col] &= (~MONSTER);
monster->trail_char =
get_dungeon_char(monster->row, monster->col);
dungeon[monster->row][monster->col] |= MONSTER;
}
}
mvaddch(i, j, get_dungeon_char(i, j));
}
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
}
}
void
light_passage(int row, int col)
{
short i, j, i_end, j_end;
if (blind) {
return;
}
i_end = (row < (DROWS-2)) ? 1 : 0;
j_end = (col < (DCOLS-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 (can_move(row, col, row+i, col+j)) {
mvaddch(row+i, col+j, get_dungeon_char(row+i, col+j));
}
}
}
}
void
darken_room(short rn)
{
short i, j;
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 (blind) {
mvaddch(i, j, ' ');
} else {
if (!(dungeon[i][j] & (OBJECT | STAIRS)) &&
!(detect_monster && (dungeon[i][j] & MONSTER))) {
if (!imitating(i, j)) {
mvaddch(i, j, ' ');
}
if ((dungeon[i][j] & TRAP) && (!(dungeon[i][j] & HIDDEN))) {
mvaddch(i, j, '^');
}
}
}
}
}
}
char
get_dungeon_char(short row, short col)
{
unsigned short mask = dungeon[row][col];
if (mask & MONSTER) {
return(gmc_row_col(row, col));
}
if (mask & OBJECT) {
object *obj;
obj = object_at(&level_objects, row, col);
return(get_mask_char(obj->what_is));
}
if (mask & (TUNNEL | STAIRS | HORWALL | VERTWALL | FLOOR | DOOR)) {
if ((mask & (TUNNEL| STAIRS)) && (!(mask & HIDDEN))) {
return(((mask & STAIRS) ? '%' : '#'));
}
if (mask & HORWALL) {
return('-');
}
if (mask & VERTWALL) {
return('|');
}
if (mask & FLOOR) {
if (mask & TRAP) {
if (!(dungeon[row][col] & HIDDEN)) {
return('^');
}
}
return('.');
}
if (mask & DOOR) {
if (mask & HIDDEN) {
if (((col > 0) && (dungeon[row][col-1] & HORWALL)) ||
((col < (DCOLS-1)) && (dungeon[row][col+1] & HORWALL))) {
return('-');
} else {
return('|');
}
} else {
return('+');
}
}
}
return(' ');
}
char
get_mask_char(unsigned short mask)
{
switch(mask) {
case SCROL:
return('?');
case POTION:
return('!');
case GOLD:
return('*');
case FOOD:
return(':');
case WAND:
return('/');
case ARMOR:
return(']');
case WEAPON:
return(')');
case RING:
return('=');
case AMULET:
return(',');
default:
return('~'); /* unknown, something is wrong */
}
}
void
gr_row_col(short *row, short *col, unsigned short mask)
{
short rn;
short r, c;
do {
r = get_rand(MIN_ROW, DROWS-2);
c = get_rand(0, DCOLS-1);
rn = get_room_number(r, c);
} while ((rn == NO_ROOM) ||
(!(dungeon[r][c] & mask)) ||
(dungeon[r][c] & (~mask)) ||
(!(rooms[rn].is_room & (R_ROOM | R_MAZE))) ||
((r == rogue.row) && (c == rogue.col)));
*row = r;
*col = c;
}
short
gr_room(void)
{
short i;
do {
i = get_rand(0, MAXROOMS-1);
} while (!(rooms[i].is_room & (R_ROOM | R_MAZE)));
return(i);
}
short
party_objects(int rn)
{
short i, j, nf = 0;
object *obj;
short n, N, row, col;
boolean found;
row = col = 0;
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++) {
for (j = found = 0; ((!found) && (j < 250)); j++) {
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);
if ((dungeon[row][col] == FLOOR) || (dungeon[row][col] == TUNNEL)) {
found = 1;
}
}
if (found) {
obj = gr_object();
place_at(obj, row, col);
nf++;
}
}
return(nf);
}
short
get_room_number(int row, int 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);
}
boolean
is_all_connected(void)
{
short i, starting_room;
starting_room = 0;
for (i = 0; i < MAXROOMS; i++) {
rooms_visited[i] = 0;
if (rooms[i].is_room & (R_ROOM | R_MAZE)) {
starting_room = i;
}
}
visit_rooms(starting_room);
for (i = 0; i < MAXROOMS; i++) {
if ((rooms[i].is_room & (R_ROOM | R_MAZE)) && (!rooms_visited[i])) {
return(0);
}
}
return(1);
}
static void
visit_rooms(int rn)
{
short i;
short oth_rn;
rooms_visited[rn] = 1;
for (i = 0; i < 4; i++) {
oth_rn = rooms[rn].doors[i].oth_room;
if ((oth_rn >= 0) && (!rooms_visited[oth_rn])) {
visit_rooms(oth_rn);
}
}
}
void
draw_magic_map(void)
{
short i, j, ch, och;
unsigned short mask = (HORWALL | VERTWALL | DOOR | TUNNEL | TRAP | STAIRS |
MONSTER);
unsigned short s;
for (i = 0; i < DROWS; i++) {
for (j = 0; j < DCOLS; j++) {
s = dungeon[i][j];
if (s & mask) {
if (((ch = mvinch(i, j)) == ' ') ||
((ch >= 'A') && (ch <= 'Z')) || (s & (TRAP | HIDDEN))) {
och = ch;
dungeon[i][j] &= (~HIDDEN);
if (s & HORWALL) {
ch = '-';
} else if (s & VERTWALL) {
ch = '|';
} else if (s & DOOR) {
ch = '+';
} else if (s & TRAP) {
ch = '^';
} else if (s & STAIRS) {
ch = '%';
} else if (s & TUNNEL) {
ch = '#';
} else {
continue;
}
if ((!(s & MONSTER)) || (och == ' ')) {
addch(ch);
}
if (s & MONSTER) {
object *monster;
if ((monster = object_at(
&level_monsters, i, j))
!= NULL) {
monster->trail_char =
ch;
}
}
}
}
}
}
}
void
dr_course(object *monster, boolean entering, short row, short col)
{
short i, j, k, rn;
short r, rr;
monster->row = row;
monster->col = col;
if (mon_sees(monster, rogue.row, rogue.col)) {
monster->trow = NO_ROOM;
return;
}
rn = get_room_number(row, col);
if (entering) { /* entering room */
/* look for door to some other room */
r = get_rand(0, MAXROOMS-1);
for (i = 0; i < MAXROOMS; i++) {
rr = (r + i) % MAXROOMS;
if ((!(rooms[rr].is_room & (R_ROOM | R_MAZE))) || (rr == rn)) {
continue;
}
for (k = 0; k < 4; k++) {
if (rooms[rr].doors[k].oth_room == rn) {
monster->trow = rooms[rr].doors[k].oth_row;
monster->tcol = rooms[rr].doors[k].oth_col;
if ((monster->trow == row) &&
(monster->tcol == col)) {
continue;
}
return;
}
}
}
/* look for door to dead end */
if (rn == NO_ROOM)
clean_up("dr_course: monster not in room");
for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
if ((i != monster->row) && (j != monster->col) &&
(dungeon[i][j] & DOOR)) {
monster->trow = i;
monster->tcol = j;
return;
}
}
}
/* return monster to room that he came from */
for (i = 0; i < MAXROOMS; i++) {
for (j = 0; j < 4; j++) {
if (rooms[i].doors[j].oth_room == rn) {
for (k = 0; k < 4; k++) {
if (rooms[rn].doors[k].oth_room == i) {
monster->trow = rooms[rn].doors[k].oth_row;
monster->tcol = rooms[rn].doors[k].oth_col;
return;
}
}
}
}
}
/* no place to send monster */
monster->trow = NO_ROOM;
} else { /* exiting room */
if (rn == NO_ROOM || !get_oth_room(rn, &row, &col)) {
monster->trow = NO_ROOM;
} else {
monster->trow = row;
monster->tcol = col;
}
}
}
static boolean
get_oth_room(short rn, short *row, short *col)
{
short d = -1;
if (*row == rooms[rn].top_row) {
d = UPWARD/2;
} else if (*row == rooms[rn].bottom_row) {
d = DOWN/2;
} else if (*col == rooms[rn].left_col) {
d = LEFT/2;
} else if (*col == rooms[rn].right_col) {
d = RIGHT/2;
}
if ((d != -1) && (rooms[rn].doors[d].oth_room >= 0)) {
*row = rooms[rn].doors[d].oth_row;
*col = rooms[rn].doors[d].oth_col;
return(1);
}
return(0);
}
void
edit_opts(void)
{
char save[NOPTS+1][DCOLS];
short i, j;
short ch;
boolean done = 0;
char buf[MAX_OPT_LEN + 2];
for (i = 0; i < NOPTS+1; i++) {
for (j = 0; j < DCOLS; j++) {
save[i][j] = mvinch(i, j);
}
if (i < NOPTS) {
opt_show(i);
}
}
opt_go(0);
i = 0;
while (!done) {
refresh();
ch = rgetchar();
CH:
switch(ch) {
case '\033':
done = 1;
break;
case '\012':
case '\015':
if (i == (NOPTS - 1)) {
mvaddstr(NOPTS, 0, press_space);
refresh();
wait_for_ack();
done = 1;
} else {
i++;
opt_go(i);
}
break;
case '-':
if (i > 0) {
opt_go(--i);
} else {
sound_bell();
}
break;
case 't':
case 'T':
case 'f':
case 'F':
if (options[i].is_bool) {
*(options[i].bval) = (((ch == 't') || (ch == 'T')) ? 1 : 0);
opt_show(i);
opt_go(++i);
break;
}
/* FALLTHROUGH */
default:
if (options[i].is_bool) {
sound_bell();
break;
}
j = 0;
if ((ch == '\010') || ((ch >= ' ') && (ch <= '~'))) {
opt_erase(i);
do {
if ((ch >= ' ') && (ch <= '~') && (j < MAX_OPT_LEN)) {
buf[j++] = ch;
buf[j] = '\0';
addch(ch);
} else if ((ch == '\010') && (j > 0)) {
buf[--j] = '\0';
move(i, j + strlen(options[i].prompt));
addch(' ');
move(i, j + strlen(options[i].prompt));
}
refresh();
ch = rgetchar();
} while ((ch != '\012') && (ch != '\015') && (ch != '\033'));
if (j != 0) {
/*
* We rely on the option string being
* allocated to hold MAX_OPT_LEN+2
* bytes. This is arranged in init.c.
*/
(void)strcpy(*(options[i].strval), buf);
}
opt_show(i);
goto CH;
} else {
sound_bell();
}
break;
}
}
for (i = 0; i < NOPTS+1; i++) {
move(i, 0);
for (j = 0; j < DCOLS; j++) {
addch(save[i][j]);
}
}
}
static void
opt_show(int i)
{
const char *s;
const struct option *opt = &options[i];
opt_erase(i);
if (opt->is_bool) {
s = *(opt->bval) ? "True" : "False";
} else {
s = *(opt->strval);
}
addstr(s);
}
static void
opt_erase(int i)
{
const struct option *opt = &options[i];
mvaddstr(i, 0, opt->prompt);
clrtoeol();
}
static void
opt_go(int i)
{
move(i, strlen(options[i].prompt));
}
void
do_shell(void)
{
#ifdef UNIX
const char *sh;
md_ignore_signals();
if (!(sh = md_getenv("SHELL"))) {
sh = "/bin/sh";
}
move(LINES-1, 0);
refresh();
stop_window();
printf("\nCreating new shell...\n");
md_shell(sh);
start_window();
wrefresh(curscr);
md_heed_signals();
#endif
}

View File

@ -1,418 +0,0 @@
/* $NetBSD: save.c,v 1.14 2021/05/02 12:50:46 rillig Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* save.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdio.h>
#include "rogue.h"
static boolean has_been_touched(const struct rogue_time *,
const struct rogue_time *);
static void r_read(FILE *, void *, size_t);
static void r_write(FILE *, const void *, size_t);
static void read_pack(object *, FILE *, boolean);
static void read_string(char *, FILE *, size_t);
static void rw_dungeon(FILE *, boolean);
static void rw_id(struct id *, FILE *, int, boolean);
static void rw_rooms(FILE *, boolean);
static void write_pack(const object *, FILE *);
static void write_string(char *, FILE *);
static short write_failed = 0;
char *save_file = NULL;
void
save_game(void)
{
char fname[64];
if (!get_input_line("file name?", save_file, fname, sizeof(fname),
"game not saved", 0, 1)) {
return;
}
check_message();
messagef(0, "%s", fname);
save_into_file(fname);
}
void
save_into_file(const char *sfile)
{
FILE *fp;
int file_id;
char *name_buffer;
size_t len;
char *hptr;
struct rogue_time rt_buf;
if (sfile[0] == '~') {
if ((hptr = md_getenv("HOME")) != NULL) {
len = strlen(hptr) + strlen(sfile);
name_buffer = md_malloc(len);
if (name_buffer == NULL) {
messagef(0,
"out of memory for save file name");
sfile = error_file;
} else {
(void)strcpy(name_buffer, hptr);
(void)strcat(name_buffer, sfile+1);
sfile = name_buffer;
}
/*
* Note: name_buffer gets leaked. But it's small,
* and in the common case we're about to exit.
*/
}
}
if (((fp = fopen(sfile, "w")) == NULL) ||
((file_id = md_get_file_id(sfile)) == -1)) {
if (fp)
fclose(fp);
messagef(0, "problem accessing the save file");
return;
}
md_ignore_signals();
write_failed = 0;
(void)xxx(1);
r_write(fp, &detect_monster, sizeof(detect_monster));
r_write(fp, &cur_level, sizeof(cur_level));
r_write(fp, &max_level, sizeof(max_level));
write_string(hunger_str, fp);
write_string(login_name, fp);
r_write(fp, &party_room, sizeof(party_room));
write_pack(&level_monsters, fp);
write_pack(&level_objects, fp);
r_write(fp, &file_id, sizeof(file_id));
rw_dungeon(fp, 1);
r_write(fp, &foods, sizeof(foods));
r_write(fp, &rogue, sizeof(fighter));
write_pack(&rogue.pack, fp);
rw_id(id_potions, fp, POTIONS, 1);
rw_id(id_scrolls, fp, SCROLS, 1);
rw_id(id_wands, fp, WANDS, 1);
rw_id(id_rings, fp, RINGS, 1);
r_write(fp, traps, (MAX_TRAPS * sizeof(trap)));
r_write(fp, is_wood, (WANDS * sizeof(boolean)));
r_write(fp, &cur_room, sizeof(cur_room));
rw_rooms(fp, 1);
r_write(fp, &being_held, sizeof(being_held));
r_write(fp, &bear_trap, sizeof(bear_trap));
r_write(fp, &halluc, sizeof(halluc));
r_write(fp, &blind, sizeof(blind));
r_write(fp, &confused, sizeof(confused));
r_write(fp, &levitate, sizeof(levitate));
r_write(fp, &haste_self, sizeof(haste_self));
r_write(fp, &see_invisible, sizeof(see_invisible));
r_write(fp, &detect_monster, sizeof(detect_monster));
r_write(fp, &wizard, sizeof(wizard));
r_write(fp, &score_only, sizeof(score_only));
r_write(fp, &m_moves, sizeof(m_moves));
md_gct(&rt_buf);
rt_buf.second += 10; /* allow for some processing time */
r_write(fp, &rt_buf, sizeof(rt_buf));
fclose(fp);
if (write_failed) {
(void)md_df(sfile); /* delete file */
} else {
clean_up("");
}
}
void
restore(const char *fname)
{
FILE *fp;
struct rogue_time saved_time, mod_time;
char buf[4];
char tbuf[MAX_OPT_LEN];
int new_file_id, saved_file_id;
fp = NULL;
if (((new_file_id = md_get_file_id(fname)) == -1) ||
((fp = fopen(fname, "r")) == NULL)) {
clean_up("cannot open file");
}
if (md_link_count(fname) > 1) {
clean_up("file has link");
}
(void)xxx(1);
r_read(fp, &detect_monster, sizeof(detect_monster));
r_read(fp, &cur_level, sizeof(cur_level));
r_read(fp, &max_level, sizeof(max_level));
read_string(hunger_str, fp, sizeof hunger_str);
(void)strlcpy(tbuf, login_name, sizeof tbuf);
read_string(login_name, fp, sizeof login_name);
if (strcmp(tbuf, login_name)) {
clean_up("you're not the original player");
}
r_read(fp, &party_room, sizeof(party_room));
read_pack(&level_monsters, fp, 0);
read_pack(&level_objects, fp, 0);
r_read(fp, &saved_file_id, sizeof(saved_file_id));
if (new_file_id != saved_file_id) {
clean_up("sorry, saved game is not in the same file");
}
rw_dungeon(fp, 0);
r_read(fp, &foods, sizeof(foods));
r_read(fp, &rogue, sizeof(fighter));
read_pack(&rogue.pack, fp, 1);
rw_id(id_potions, fp, POTIONS, 0);
rw_id(id_scrolls, fp, SCROLS, 0);
rw_id(id_wands, fp, WANDS, 0);
rw_id(id_rings, fp, RINGS, 0);
r_read(fp, traps, (MAX_TRAPS * sizeof(trap)));
r_read(fp, is_wood, (WANDS * sizeof(boolean)));
r_read(fp, &cur_room, sizeof(cur_room));
rw_rooms(fp, 0);
r_read(fp, &being_held, sizeof(being_held));
r_read(fp, &bear_trap, sizeof(bear_trap));
r_read(fp, &halluc, sizeof(halluc));
r_read(fp, &blind, sizeof(blind));
r_read(fp, &confused, sizeof(confused));
r_read(fp, &levitate, sizeof(levitate));
r_read(fp, &haste_self, sizeof(haste_self));
r_read(fp, &see_invisible, sizeof(see_invisible));
r_read(fp, &detect_monster, sizeof(detect_monster));
r_read(fp, &wizard, sizeof(wizard));
r_read(fp, &score_only, sizeof(score_only));
r_read(fp, &m_moves, sizeof(m_moves));
r_read(fp, &saved_time, sizeof(saved_time));
if (fread(buf, 1, 1, fp) > 0) {
clear();
clean_up("extra characters in file");
}
md_gfmt(fname, &mod_time); /* get file modification time */
if (has_been_touched(&saved_time, &mod_time)) {
clear();
clean_up("sorry, file has been touched");
}
if ((!wizard) && !md_df(fname)) {
clean_up("cannot delete file");
}
msg_cleared = 0;
ring_stats(0);
fclose(fp);
}
static void
write_pack(const object *pack, FILE *fp)
{
object t;
while ((pack = pack->next_object) != NULL) {
r_write(fp, pack, sizeof(object));
}
t.ichar = t.what_is = 0;
r_write(fp, &t, sizeof(object));
}
static void
read_pack(object *pack, FILE *fp, boolean is_rogue)
{
object read_obj, *new_obj;
for (;;) {
r_read(fp, &read_obj, sizeof(object));
if (read_obj.ichar == 0) {
pack->next_object = NULL;
break;
}
new_obj = alloc_object();
*new_obj = read_obj;
if (is_rogue) {
if (new_obj->in_use_flags & BEING_WORN) {
do_wear(new_obj);
} else if (new_obj->in_use_flags & BEING_WIELDED) {
do_wield(new_obj);
} else if (new_obj->in_use_flags & (ON_EITHER_HAND)) {
do_put_on(new_obj,
((new_obj->in_use_flags & ON_LEFT_HAND) ? 1 : 0));
}
}
pack->next_object = new_obj;
pack = new_obj;
}
}
static void
rw_dungeon(FILE *fp, boolean rw)
{
short i, j;
char buf[DCOLS];
for (i = 0; i < DROWS; i++) {
if (rw) {
r_write(fp, dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
for (j = 0; j < DCOLS; j++) {
buf[j] = mvinch(i, j);
}
r_write(fp, buf, DCOLS);
} else {
r_read(fp, dungeon[i], (DCOLS * sizeof(dungeon[0][0])));
r_read(fp, buf, DCOLS);
for (j = 0; j < DCOLS; j++) {
mvaddch(i, j, buf[j]);
}
}
}
}
static void
rw_id(struct id id_table[], FILE *fp, int n, boolean wr)
{
int i;
for (i = 0; i < n; i++) {
if (wr) {
r_write(fp, &id_table[i].value, sizeof(short));
r_write(fp, &id_table[i].id_status,
sizeof(unsigned short));
write_string(id_table[i].title, fp);
} else {
r_read(fp, &id_table[i].value, sizeof(short));
r_read(fp, &id_table[i].id_status,
sizeof(unsigned short));
read_string(id_table[i].title, fp, MAX_ID_TITLE_LEN);
}
}
}
static void
write_string(char *s, FILE *fp)
{
short n;
n = strlen(s) + 1;
xxxx(s, n);
r_write(fp, &n, sizeof(short));
r_write(fp, s, n);
}
static void
read_string(char *s, FILE *fp, size_t len)
{
short n;
r_read(fp, &n, sizeof(short));
if (n<=0 || (size_t)(unsigned short)n > len) {
clean_up("read_string: corrupt game file");
}
r_read(fp, s, n);
xxxx(s, n);
/* ensure null termination */
s[n-1] = 0;
}
static void
rw_rooms(FILE *fp, boolean rw)
{
short i;
for (i = 0; i < MAXROOMS; i++) {
rw ? r_write(fp, (rooms + i), sizeof(room)) :
r_read(fp, (rooms + i), sizeof(room));
}
}
static void
r_read(FILE *fp, void *buf, size_t n)
{
if (fread(buf, 1, n, fp) != n) {
clean_up("fread() failed, don't know why");
}
}
static void
r_write(FILE *fp, const void *buf, size_t n)
{
if (!write_failed) {
if (fwrite(buf, 1, n, fp) != n) {
messagef(0, "write() failed, don't know why");
sound_bell();
write_failed = 1;
}
}
}
static boolean
has_been_touched(const struct rogue_time *saved_time,
const struct rogue_time *mod_time)
{
if (saved_time->year < mod_time->year) {
return(1);
} else if (saved_time->year > mod_time->year) {
return(0);
}
if (saved_time->month < mod_time->month) {
return(1);
} else if (saved_time->month > mod_time->month) {
return(0);
}
if (saved_time->day < mod_time->day) {
return(1);
} else if (saved_time->day > mod_time->day) {
return(0);
}
if (saved_time->hour < mod_time->hour) {
return(1);
} else if (saved_time->hour > mod_time->hour) {
return(0);
}
if (saved_time->minute < mod_time->minute) {
return(1);
} else if (saved_time->minute > mod_time->minute) {
return(0);
}
if (saved_time->second < mod_time->second) {
return(1);
}
return(0);
}

View File

@ -1,664 +0,0 @@
/* $NetBSD: score.c,v 1.16 2011/08/26 06:18:17 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* score.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdio.h>
#include "rogue.h"
static void center(short, const char *);
static int get_value(const object *);
static void id_all(void);
static void sell_pack(void);
static void sf_error(void) __dead;
void
killed_by(const object *monster, short other)
{
const char *mechanism = "killed by something unknown (?)";
char mechanism_buf[128];
const char *article;
char message_buf[128];
md_ignore_signals();
if (other != QUIT) {
rogue.gold = ((rogue.gold * 9) / 10);
}
if (other) {
switch(other) {
case HYPOTHERMIA:
mechanism = "died of hypothermia";
break;
case STARVATION:
mechanism = "died of starvation";
break;
case POISON_DART:
mechanism = "killed by a dart";
break;
case QUIT:
mechanism = "quit";
break;
case KFIRE:
mechanism = "killed by fire";
break;
}
} else {
if (is_vowel(m_names[monster->m_char - 'A'][0])) {
article = "an";
} else {
article = "a";
}
snprintf(mechanism_buf, sizeof(mechanism_buf),
"Killed by %s %s",
article, m_names[monster->m_char - 'A']);
mechanism = mechanism_buf;
}
snprintf(message_buf, sizeof(message_buf),
"%s with %ld gold", mechanism, rogue.gold);
if ((!other) && (!no_skull)) {
clear();
mvaddstr(4, 32, "__---------__");
mvaddstr(5, 30, "_~ ~_");
mvaddstr(6, 29, "/ \\");
mvaddstr(7, 28, "~ ~");
mvaddstr(8, 27, "/ \\");
mvaddstr(9, 27, "| XXXX XXXX |");
mvaddstr(10, 27, "| XXXX XXXX |");
mvaddstr(11, 27, "| XXX XXX |");
mvaddstr(12, 28, "\\ @ /");
mvaddstr(13, 29, "--\\ @@@ /--");
mvaddstr(14, 30, "| | @@@ | |");
mvaddstr(15, 30, "| | | |");
mvaddstr(16, 30, "| vvVvvvvvvvVvv |");
mvaddstr(17, 30, "| ^^^^^^^^^^^ |");
mvaddstr(18, 31, "\\_ _/");
mvaddstr(19, 33, "~---------~");
center(21, nick_name);
center(22, message_buf);
} else {
messagef(0, "%s", message_buf);
}
messagef(0, "%s", ""); /* gcc objects to just "" */
put_scores(monster, other);
}
void
win(void)
{
unwield(rogue.weapon); /* disarm and relax */
unwear(rogue.armor);
un_put_on(rogue.left_ring);
un_put_on(rogue.right_ring);
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, "Fighters' Guild. You return home, sell all your");
mvaddstr(19, 11, "treasures at great profit and retire into comfort.");
messagef(0, "%s", ""); /* gcc objects to just "" */
messagef(0, "%s", ""); /* gcc objects to just "" */
id_all();
sell_pack();
put_scores(NULL, WIN);
}
void
quit(boolean from_intrpt)
{
char buf[DCOLS];
short i, orow, ocol;
boolean mc;
orow = ocol = 0;
mc = FALSE;
md_ignore_signals();
if (from_intrpt) {
orow = rogue.row;
ocol = rogue.col;
mc = msg_cleared;
for (i = 0; i < DCOLS; i++) {
buf[i] = mvinch(0, i);
}
}
check_message();
messagef(1, "really quit?");
if (rgetchar() != 'y') {
md_heed_signals();
check_message();
if (from_intrpt) {
for (i = 0; i < DCOLS; i++) {
mvaddch(0, i, buf[i]);
}
msg_cleared = mc;
move(orow, ocol);
refresh();
}
return;
}
if (from_intrpt) {
clean_up(byebye_string);
}
check_message();
killed_by(NULL, QUIT);
}
/*
* The score file on disk is up to ten entries of the form
* score block [80 bytes]
* nickname block [30 bytes]
*
* The score block is to be parsed as follows:
* bytes 0-1 Rank (" 1" to "10")
* bytes 2-4 space padding
* bytes 5-15 Score/gold
* byte 15 up to a ':' Login name
* past the ':' Death mechanism
*
* The nickname block is an alternate name to be printed in place of the
* login name. Both blocks are supposed to contain a null-terminator.
*/
struct score_entry {
long gold;
char username[80];
char death[80];
char nickname[30];
};
#define NUM_SCORE_ENTRIES 10
static void make_score(struct score_entry *, const object *, int);
static
void
pad_spaces(char *str, size_t len)
{
size_t x;
for (x=strlen(str); x<len-1; x++) {
str[x] = ' ';
}
str[len-1] = 0;
}
static
void
unpad_spaces(char *str)
{
size_t x;
for (x=strlen(str); x>0 && str[x-1]==' '; x--);
str[x] = 0;
}
static
int
read_score_entry(struct score_entry *se, FILE *fp)
{
char score_block[80];
char nickname_block[30];
size_t n, x;
n = fread(score_block, 1, sizeof(score_block), fp);
if (n==0) {
/* EOF */
return 0;
}
if (n != sizeof(score_block)) {
sf_error();
}
n = fread(nickname_block, 1, sizeof(nickname_block), fp);
if (n != sizeof(nickname_block)) {
sf_error();
}
xxxx(score_block, sizeof(score_block));
xxxx(nickname_block, sizeof(nickname_block));
/* Ensure null termination */
score_block[sizeof(score_block)-1] = 0;
nickname_block[sizeof(nickname_block)-1] = 0;
/* If there are other nulls in the score block, file is corrupt */
if (strlen(score_block)!=sizeof(score_block)-1) {
sf_error();
}
/* but this is NOT true of the nickname block */
/* quash trailing spaces */
unpad_spaces(score_block);
unpad_spaces(nickname_block);
for (x=5; score_block[x] == ' '; x++);
se->gold = lget_number(score_block+x);
for (x=15; score_block[x] != 0 && score_block[x] != ':'; x++);
if (score_block[x] == 0) {
sf_error();
}
score_block[x++] = 0;
strlcpy(se->username, score_block+15, sizeof(se->username));
strlcpy(se->death, score_block+x, sizeof(se->death));
strlcpy(se->nickname, nickname_block, sizeof(se->nickname));
return 1;
}
static
void
write_score_entry(const struct score_entry *se, int rank, FILE *fp)
{
char score_block[80];
char nickname_block[30];
/* avoid writing crap to score file */
memset(score_block, 0, sizeof(score_block));
memset(nickname_block, 0, sizeof(nickname_block));
snprintf(score_block, sizeof(score_block),
"%2d %6ld %s: %s",
rank+1, se->gold, se->username, se->death);
strlcpy(nickname_block, se->nickname, sizeof(nickname_block));
/* pad blocks out with spaces */
pad_spaces(score_block, sizeof(score_block));
/*pad_spaces(nickname_block, sizeof(nickname_block)); -- wrong! */
xxxx(score_block, sizeof(score_block));
xxxx(nickname_block, sizeof(nickname_block));
fwrite(score_block, 1, sizeof(score_block), fp);
fwrite(nickname_block, 1, sizeof(nickname_block), fp);
}
void
put_scores(const object *monster, short other)
{
short i, rank=-1, found_player = -1, numscores = 0;
struct score_entry scores[NUM_SCORE_ENTRIES];
const char *name;
FILE *fp;
boolean dopause = score_only;
md_lock(1);
setegid(egid);
if ((fp = fopen(_PATH_SCOREFILE, "r+")) == NULL &&
(fp = fopen(_PATH_SCOREFILE, "w+")) == NULL) {
setegid(gid);
messagef(0, "cannot read/write/create score file");
sf_error();
}
setegid(gid);
rewind(fp);
(void)xxx(1);
for (numscores = 0; numscores < NUM_SCORE_ENTRIES; numscores++) {
if (read_score_entry(&scores[numscores], fp) == 0) {
break;
}
}
/* Search the score list. */
for (i=0; i<numscores; i++) {
if (!strcmp(scores[i].username, login_name)) {
/* found our score */
if (rogue.gold < scores[i].gold) {
/* we didn't do as well as last time */
score_only = 1;
} else {
/* we did better; mark entry for removal */
found_player = i;
}
break;
}
}
/* Remove a superseded entry, if any. */
if (found_player != -1) {
numscores--;
for (i = found_player; i < numscores; i++) {
scores[i] = scores[i+1];
}
}
/* If we're going to insert ourselves, do it now */
if (!score_only) {
/* if we aren't better than anyone, add at end. */
rank = numscores;
/* Otherwise, find our slot. */
for (i = 0; i < numscores; i++) {
if (rogue.gold >= scores[i].gold) {
rank = i;
break;
}
}
if (rank < NUM_SCORE_ENTRIES) {
/* Open up a slot */
for (i = numscores; i > rank; i--) {
scores[i] = scores[i-1];
}
numscores++;
/* Put our info in the slot */
make_score(&scores[rank], monster, other);
}
/* Now rewrite the score file */
md_ignore_signals();
rewind(fp);
(void)xxx(1);
for (i = 0; i < numscores; i++) {
write_score_entry(&scores[i], i, fp);
}
}
md_lock(0);
fclose(fp);
/* Display the scores */
clear();
mvaddstr(3, 30, "Top Ten Rogueists");
mvaddstr(8, 0, "Rank Score Name");
for (i = 0; i < numscores; i++) {
if (i == rank) {
standout();
}
if (scores[i].nickname[0]) {
name = scores[i].nickname;
} else {
name = scores[i].username;
}
mvprintw(i+10, 0, "%2d %6ld %s: %s",
i+1, scores[i].gold, name, scores[i].death);
if (i == rank) {
standend();
}
}
refresh();
messagef(0, "%s", ""); /* gcc objects to just "" */
if (dopause) {
messagef(0, "%s", "");
}
clean_up("");
}
static
void
make_score(struct score_entry *se, const object *monster, int other)
{
const char *death = "bolts from the blue (?)";
const char *hasamulet;
char deathbuf[80];
se->gold = rogue.gold;
strlcpy(se->username, login_name, sizeof(se->username));
if (other) {
switch(other) {
case HYPOTHERMIA:
death = "died of hypothermia";
break;
case STARVATION:
death = "died of starvation";
break;
case POISON_DART:
death = "killed by a dart";
break;
case QUIT:
death = "quit";
break;
case WIN:
death = "a total winner";
break;
case KFIRE:
death = "killed by fire";
break;
}
} else {
const char *mn, *article;
mn = m_names[monster->m_char - 'A'];
if (is_vowel(mn[0])) {
article = "an";
} else {
article = "a";
}
snprintf(deathbuf, sizeof(deathbuf),
"killed by %s %s", article, mn);
death = deathbuf;
}
if (other != WIN && has_amulet()) {
hasamulet = " with amulet";
} else {
hasamulet = "";
}
snprintf(se->death, sizeof(se->death), "%s on level %d%s",
death, max_level, hasamulet);
strlcpy(se->nickname, nick_name, sizeof(se->nickname));
}
boolean
is_vowel(short ch)
{
return( (ch == 'a') ||
(ch == 'e') ||
(ch == 'i') ||
(ch == 'o') ||
(ch == 'u') );
}
static void
sell_pack(void)
{
object *obj;
short row = 2, val;
char buf[DCOLS];
obj = rogue.pack.next_object;
clear();
mvaddstr(1, 0, "Value Item");
while (obj) {
if (obj->what_is != FOOD) {
obj->identified = 1;
val = get_value(obj);
rogue.gold += val;
if (row < DROWS) {
get_desc(obj, buf, sizeof(buf));
mvprintw(row++, 0, "%5d %s", val, buf);
}
}
obj = obj->next_object;
}
refresh();
if (rogue.gold > MAX_GOLD) {
rogue.gold = MAX_GOLD;
}
messagef(0, "%s", ""); /* gcc objects to just "" */
}
static int
get_value(const object *obj)
{
short wc;
int val;
val = 0;
wc = obj->which_kind;
switch(obj->what_is) {
case WEAPON:
val = id_weapons[wc].value;
if ((wc == ARROW) || (wc == DAGGER) || (wc == SHURIKEN) ||
(wc == DART)) {
val *= obj->quantity;
}
val += (obj->d_enchant * 85);
val += (obj->hit_enchant * 85);
break;
case ARMOR:
val = id_armors[wc].value;
val += (obj->d_enchant * 75);
if (obj->is_protected) {
val += 200;
}
break;
case WAND:
val = id_wands[wc].value * (obj->class + 1);
break;
case SCROL:
val = id_scrolls[wc].value * obj->quantity;
break;
case POTION:
val = id_potions[wc].value * obj->quantity;
break;
case AMULET:
val = 5000;
break;
case RING:
val = id_rings[wc].value * (obj->class + 1);
break;
}
if (val <= 0) {
val = 10;
}
return(val);
}
static void
id_all(void)
{
short i;
for (i = 0; i < SCROLS; 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;
}
}
void
xxxx(char *buf, short n)
{
short i;
unsigned char c;
for (i = 0; i < n; i++) {
/* It does not matter if accuracy is lost during this assignment */
c = (unsigned char)xxx(0);
buf[i] ^= c;
}
}
long
xxx(boolean st)
{
static long f, s;
long r;
if (st) {
f = 37;
s = 7;
return(0L);
}
r = ((f * s) + 9337) % 8887;
f = s;
s = r;
return(r);
}
static void
center(short row, const char *buf)
{
short margin;
margin = ((DCOLS - strlen(buf)) / 2);
mvaddstr(row, margin, buf);
}
static void
sf_error(void)
{
md_lock(0);
messagef(1, "%s", ""); /* gcc objects to just "" */
clean_up("sorry, score file is out of order");
}

View File

@ -1,528 +0,0 @@
/* $NetBSD: spec_hit.c,v 1.9 2011/05/23 23:01:17 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* special_hit.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include <stdlib.h> /* rand(3) */
#include "random.h"
#include "rogue.h"
static void disappear(object *);
static void drain_life(void);
static void drop_level(void);
static void freeze(object *);
static int get_dir(short, short, short, short);
static boolean gold_at(short, short);
static void steal_gold(object *);
static void steal_item(object *);
static void sting(object *);
static boolean try_to_cough(short, short, object *);
short less_hp = 0;
boolean being_held;
void
special_hit(object *monster)
{
if ((monster->m_flags & CONFUSED) && rand_percent(66)) {
return;
}
if (monster->m_flags & RUSTS) {
rust(monster);
}
if ((monster->m_flags & HOLDS) && !levitate) {
being_held = 1;
}
if (monster->m_flags & FREEZES) {
freeze(monster);
}
if (monster->m_flags & STINGS) {
sting(monster);
}
if (monster->m_flags & DRAINS_LIFE) {
drain_life();
}
if (monster->m_flags & DROPS_LEVEL) {
drop_level();
}
if (monster->m_flags & STEALS_GOLD) {
steal_gold(monster);
} else if (monster->m_flags & STEALS_ITEM) {
steal_item(monster);
}
}
void
rust(object *monster)
{
if ((!rogue.armor) || (get_armor_class(rogue.armor) <= 1) ||
(rogue.armor->which_kind == LEATHER)) {
return;
}
if ((rogue.armor->is_protected) || maintain_armor) {
if (monster && (!(monster->m_flags & RUST_VANISHED))) {
messagef(0, "the rust vanishes instantly");
monster->m_flags |= RUST_VANISHED;
}
} else {
rogue.armor->d_enchant--;
messagef(0, "your armor weakens");
print_stats(STAT_ARMOR);
}
}
void
freeze(object *monster)
{
short freeze_percent = 99;
short i, n;
if (rand_percent(12)) {
return;
}
freeze_percent -= (rogue.str_current+(rogue.str_current / 2));
freeze_percent -= ((rogue.exp + ring_exp) * 4);
freeze_percent -= (get_armor_class(rogue.armor) * 5);
freeze_percent -= (rogue.hp_max / 3);
if (freeze_percent > 10) {
monster->m_flags |= FREEZING_ROGUE;
messagef(1, "you are frozen");
n = get_rand(4, 8);
for (i = 0; i < n; i++) {
mv_mons();
}
if (rand_percent(freeze_percent)) {
for (i = 0; i < 50; i++) {
mv_mons();
}
killed_by(NULL, HYPOTHERMIA);
}
messagef(1, "%s", you_can_move_again);
monster->m_flags &= (~FREEZING_ROGUE);
}
}
void
steal_gold(object *monster)
{
int amount;
if ((rogue.gold <= 0) || rand_percent(10)) {
return;
}
amount = get_rand((cur_level * 10), (cur_level * 30));
if (amount > rogue.gold) {
amount = rogue.gold;
}
rogue.gold -= amount;
messagef(0, "your purse feels lighter");
print_stats(STAT_GOLD);
disappear(monster);
}
void
steal_item(object *monster)
{
object *obj;
short i, n, t = 0;
char desc[80];
boolean has_something = 0;
if (rand_percent(15)) {
return;
}
obj = rogue.pack.next_object;
if (!obj) {
goto DSPR;
}
while (obj) {
if (!(obj->in_use_flags & BEING_USED)) {
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->in_use_flags & BEING_USED)) {
if (!obj) {
obj = rogue.pack.next_object;
} else {
obj = obj->next_object;
}
}
}
if (obj->what_is != WEAPON) {
t = obj->quantity;
obj->quantity = 1;
}
get_desc(obj, desc, sizeof(desc));
messagef(0, "she stole %s", desc);
obj->quantity = ((obj->what_is != WEAPON) ? t : 1);
vanish(obj, 0, &rogue.pack);
DSPR:
disappear(monster);
}
static void
disappear(object *monster)
{
short row, col;
row = monster->row;
col = monster->col;
dungeon[row][col] &= ~MONSTER;
if (rogue_can_see(row, col)) {
mvaddch(row, col, get_dungeon_char(row, col));
}
take_from_pack(monster, &level_monsters);
free_object(monster);
mon_disappeared = 1;
}
void
cough_up(object *monster)
{
object *obj;
short row, col, i, n;
if (cur_level < max_level) {
return;
}
if (monster->m_flags & STEALS_GOLD) {
obj = alloc_object();
obj->what_is = GOLD;
obj->quantity = get_rand((cur_level * 15), (cur_level * 30));
} else {
if (!rand_percent((int)monster->drop_percent)) {
return;
}
obj = gr_object();
}
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_object(obj);
}
static boolean
try_to_cough(short row, short col, object *obj)
{
if ((row < MIN_ROW) ||
(row > (DROWS-2)) || (col < 0) || (col>(DCOLS-1))) {
return(0);
}
if ((!(dungeon[row][col] & (OBJECT | STAIRS | TRAP))) &&
(dungeon[row][col] & (TUNNEL | FLOOR | DOOR))) {
place_at(obj, row, col);
if (((row != rogue.row) || (col != rogue.col)) &&
(!(dungeon[row][col] & MONSTER))) {
mvaddch(row, col, get_dungeon_char(row, col));
}
return(1);
}
return(0);
}
boolean
seek_gold(object *monster)
{
short i, j, rn, s;
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 ((gold_at(i, j)) && !(dungeon[i][j] & MONSTER)) {
monster->m_flags |= CAN_FLIT;
s = mon_can_go(monster, i, j);
monster->m_flags &= (~CAN_FLIT);
if (s) {
move_mon_to(monster, i, j);
monster->m_flags |= ASLEEP;
monster->m_flags &= (~(WAKENS | SEEKS_GOLD));
return(1);
}
monster->m_flags &= (~SEEKS_GOLD);
monster->m_flags |= CAN_FLIT;
mv_1_monster(monster, i, j);
monster->m_flags &= (~CAN_FLIT);
monster->m_flags |= SEEKS_GOLD;
return(1);
}
}
}
return(0);
}
static boolean
gold_at(short row, short col)
{
if (dungeon[row][col] & OBJECT) {
object *obj;
if ((obj = object_at(&level_objects, row, col)) &&
(obj->what_is == GOLD)) {
return(1);
}
}
return(0);
}
void
check_gold_seeker(object *monster)
{
monster->m_flags &= (~SEEKS_GOLD);
}
boolean
check_imitator(object *monster)
{
if (monster->m_flags & IMITATES) {
wake_up(monster);
if (!blind) {
mvaddch(monster->row, monster->col,
get_dungeon_char(monster->row, monster->col));
check_message();
messagef(1, "wait, that's a %s!", mon_name(monster));
}
return(1);
}
return(0);
}
boolean
imitating(short row, short col)
{
if (dungeon[row][col] & MONSTER) {
object *monster;
if ((monster = object_at(&level_monsters, row, col)) != NULL) {
if (monster->m_flags & IMITATES) {
return(1);
}
}
}
return(0);
}
static void
sting(object *monster)
{
short sting_chance = 35;
if ((rogue.str_current <= 3) || sustain_strength) {
return;
}
sting_chance += (6 * (6 - get_armor_class(rogue.armor)));
if ((rogue.exp + ring_exp) > 8) {
sting_chance -= (6 * ((rogue.exp + ring_exp) - 8));
}
if (rand_percent(sting_chance)) {
messagef(0, "the %s's bite has weakened you",
mon_name(monster));
rogue.str_current--;
print_stats(STAT_STRENGTH);
}
}
static void
drop_level(void)
{
int hp;
if (rand_percent(80) || (rogue.exp <= 5)) {
return;
}
rogue.exp_points = level_points[rogue.exp-2] - get_rand(9, 29);
rogue.exp -= 2;
hp = hp_raise();
if ((rogue.hp_current -= hp) <= 0) {
rogue.hp_current = 1;
}
if ((rogue.hp_max -= hp) <= 0) {
rogue.hp_max = 1;
}
add_exp(1, 0);
}
void
drain_life(void)
{
short n;
if (rand_percent(60) || (rogue.hp_max <= 30) || (rogue.hp_current < 10)) {
return;
}
n = get_rand(1, 3); /* 1 Hp, 2 Str, 3 both */
if ((n != 2) || (!sustain_strength)) {
messagef(0, "you feel weaker");
}
if (n != 2) {
rogue.hp_max--;
rogue.hp_current--;
less_hp++;
}
if (n != 1) {
if ((rogue.str_current > 3) && (!sustain_strength)) {
rogue.str_current--;
rogue.str_max -= rand() & 1;
}
}
print_stats((STAT_STRENGTH | STAT_HP));
}
boolean
m_confuse(object *monster)
{
if (!rogue_can_see(monster->row, monster->col)) {
return(0);
}
if (rand_percent(45)) {
monster->m_flags &= (~CONFUSES); /* will not confuse the rogue */
return(0);
}
if (rand_percent(55)) {
monster->m_flags &= (~CONFUSES);
messagef(1, "the gaze of the %s has confused you",
mon_name(monster));
cnfs();
return(1);
}
return(0);
}
boolean
flame_broil(object *monster)
{
short row, col, dir;
if ((!mon_sees(monster, rogue.row, rogue.col)) || (rand() & 1)) {
return(0);
}
row = rogue.row - monster->row;
col = rogue.col - monster->col;
if (row < 0) {
row = -row;
}
if (col < 0) {
col = -col;
}
if (((row != 0) && (col != 0) && (row != col)) ||
((row > 7) || (col > 7))) {
return(0);
}
dir = get_dir(monster->row, monster->col, row, col);
bounce(FIRE, dir, monster->row, monster->col, 0);
return(1);
}
static int
get_dir(short srow, short scol, short drow, short dcol)
{
if (srow == drow) {
if (scol < dcol) {
return(RIGHT);
} else {
return(LEFT);
}
}
if (scol == dcol) {
if (srow < drow) {
return(DOWN);
} else {
return(UPWARD);
}
}
if ((srow > drow) && (scol > dcol)) {
return(UPLEFT);
}
if ((srow < drow) && (scol < dcol)) {
return(DOWNRIGHT);
}
if ((srow < drow) && (scol > dcol)) {
return(DOWNLEFT);
}
/*if ((srow > drow) && (scol < dcol)) {*/
return(UPRIGHT);
/*}*/
}

View File

@ -1,316 +0,0 @@
/* $NetBSD: throw.c,v 1.12 2011/05/23 23:01:17 joerg Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* throw.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
static void flop_weapon(object *, short, short);
static object *get_thrown_at_monster(object *, short, short *, short *);
static boolean throw_at_monster(object *, object *);
void
throw(void)
{
short wch, d;
boolean first_miss = 1;
object *weapon;
short dir, row, col;
object *monster;
while (!is_direction(dir = rgetchar(), &d)) {
sound_bell();
if (first_miss) {
messagef(0, "direction? ");
first_miss = 0;
}
}
check_message();
if (dir == CANCEL) {
return;
}
if ((wch = pack_letter("throw what?", WEAPON)) == CANCEL) {
return;
}
check_message();
if (!(weapon = get_letter_object(wch))) {
messagef(0, "no such item.");
return;
}
if ((weapon->in_use_flags & BEING_USED) && weapon->is_cursed) {
messagef(0, "%s", curse_message);
return;
}
row = rogue.row; col = rogue.col;
if ((weapon->in_use_flags & BEING_WIELDED) && (weapon->quantity <= 1)) {
unwield(rogue.weapon);
} else if (weapon->in_use_flags & BEING_WORN) {
mv_aquatars();
unwear(rogue.armor);
print_stats(STAT_ARMOR);
} else if (weapon->in_use_flags & ON_EITHER_HAND) {
un_put_on(weapon);
}
monster = get_thrown_at_monster(weapon, d, &row, &col);
mvaddch(rogue.row, rogue.col, rogue.fchar);
refresh();
if (rogue_can_see(row, col) && ((row != rogue.row) || (col != rogue.col))){
mvaddch(row, col, get_dungeon_char(row, col));
}
if (monster) {
wake_up(monster);
check_gold_seeker(monster);
if (!throw_at_monster(monster, weapon)) {
flop_weapon(weapon, row, col);
}
} else {
flop_weapon(weapon, row, col);
}
vanish(weapon, 1, &rogue.pack);
}
boolean
throw_at_monster(object *monster, object *weapon)
{
short damage, hit_chance;
short t;
hit_chance = get_hit_chance(weapon);
damage = get_weapon_damage(weapon);
if ((weapon->which_kind == ARROW) &&
(rogue.weapon && (rogue.weapon->which_kind == BOW))) {
damage += get_weapon_damage(rogue.weapon);
damage = ((damage * 2) / 3);
hit_chance += (hit_chance / 3);
} else if ((weapon->in_use_flags & BEING_WIELDED) &&
((weapon->which_kind == DAGGER) ||
(weapon->which_kind == SHURIKEN) ||
(weapon->which_kind == DART))) {
damage = ((damage * 3) / 2);
hit_chance += (hit_chance / 3);
}
t = weapon->quantity;
weapon->quantity = 1;
snprintf(hit_message, HIT_MESSAGE_SIZE, "the %s", name_of(weapon));
weapon->quantity = t;
if (!rand_percent(hit_chance)) {
(void)strlcat(hit_message, "misses ", HIT_MESSAGE_SIZE);
return(0);
}
s_con_mon(monster);
(void)strlcat(hit_message, "hit ", HIT_MESSAGE_SIZE);
(void)mon_damage(monster, damage);
return(1);
}
object *
get_thrown_at_monster(object *obj, short dir, short *row, short *col)
{
short orow, ocol;
short i, ch;
orow = *row; ocol = *col;
ch = get_mask_char(obj->what_is);
for (i = 0; i < 24; i++) {
get_dir_rc(dir, row, col, 0);
if ( (((*col <= 0) || (*col >= DCOLS-1)) ||
(dungeon[*row][*col] == NOTHING)) ||
((dungeon[*row][*col] & (HORWALL | VERTWALL | HIDDEN)) &&
(!(dungeon[*row][*col] & TRAP)))) {
*row = orow;
*col = ocol;
return(0);
}
if ((i != 0) && rogue_can_see(orow, ocol)) {
mvaddch(orow, ocol, get_dungeon_char(orow, ocol));
}
if (rogue_can_see(*row, *col)) {
if (!(dungeon[*row][*col] & MONSTER)) {
mvaddch(*row, *col, ch);
}
refresh();
}
orow = *row; ocol = *col;
if (dungeon[*row][*col] & MONSTER) {
if (!imitating(*row, *col)) {
return(object_at(&level_monsters, *row, *col));
}
}
if (dungeon[*row][*col] & TUNNEL) {
i += 2;
}
}
return(0);
}
void
flop_weapon(object *weapon, short row, short col)
{
object *new_weapon, *monster;
short i = 0;
boolean found = 0;
short mch, dch;
unsigned short mon;
if ((row < 0) || (row >= DROWS) || (col < 0) || (col >= DCOLS))
clean_up("flop_weapon: weapon landed outside of dungeon");
while ((i < 9) && dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER)) {
rand_around(i++, &row, &col);
if ((row > (DROWS-2)) || (row < MIN_ROW) ||
(col > (DCOLS-1)) || (col < 0) || (!dungeon[row][col]) ||
(dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER))) {
continue;
}
found = 1;
break;
}
if (found || (i == 0)) {
new_weapon = alloc_object();
*new_weapon = *weapon;
new_weapon->in_use_flags = NOT_USED;
new_weapon->quantity = 1;
new_weapon->ichar = 'L';
place_at(new_weapon, row, col);
if (rogue_can_see(row, col) &&
((row != rogue.row) || (col != rogue.col))) {
mon = dungeon[row][col] & MONSTER;
dungeon[row][col] &= (~MONSTER);
dch = get_dungeon_char(row, col);
if (mon) {
mch = mvinch(row, col);
if ((monster = object_at(&level_monsters,
row, col)) != NULL) {
monster->trail_char = dch;
}
if ((mch < 'A') || (mch > 'Z')) {
mvaddch(row, col, dch);
}
} else {
mvaddch(row, col, dch);
}
dungeon[row][col] |= mon;
}
} else {
short t;
t = weapon->quantity;
weapon->quantity = 1;
messagef(0, "the %svanishes as it hits the ground",
name_of(weapon));
weapon->quantity = t;
}
}
void
rand_around(short i, short *r, short *c)
{
static char pos[] = "\010\007\001\003\004\005\002\006\0";
static short row, col;
short j;
if (i == 0) {
short x, y, o, t;
row = *r;
col = *c;
o = get_rand(1, 8);
for (j = 0; j < 5; j++) {
x = get_rand(0, 8);
y = (x + o) % 9;
t = pos[x];
pos[x] = pos[y];
pos[y] = t;
}
}
switch((short)pos[i]) {
case 0:
*r = row + 1;
*c = col + 1;
break;
case 1:
*r = row + 1;
*c = col - 1;
break;
case 2:
*r = row - 1;
*c = col + 1;
break;
case 3:
*r = row - 1;
*c = col - 1;
break;
case 4:
*r = row;
*c = col + 1;
break;
case 5:
*r = row + 1;
*c = col;
break;
case 6:
*r = row;
*c = col;
break;
case 7:
*r = row - 1;
*c = col;
break;
case 8:
*r = row;
*c = col - 1;
break;
}
}

View File

@ -1,274 +0,0 @@
/* $NetBSD: trap.c,v 1.10 2009/08/12 08:44:45 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* trap.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
trap traps[MAX_TRAPS];
boolean trap_door = 0;
short bear_trap = 0;
static const char *const trap_strings[TRAPS * 2] = {
"trap door",
"you fell down a trap",
"bear trap",
"you are caught in a bear trap",
"teleport trap",
"teleport",
"poison dart trap",
"a small dart just hit you in the shoulder",
"sleeping gas trap",
"a strange white mist envelops you and you fall asleep",
"rust trap",
"a gush of water hits you on the head"
};
static short
trap_at(int row, int col)
{
short i;
for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
return(traps[i].trap_type);
}
}
return(NO_TRAP);
}
void
trap_player(short row, short col)
{
short t;
if ((t = trap_at(row, col)) == NO_TRAP) {
return;
}
dungeon[row][col] &= (~HIDDEN);
if (rand_percent(rogue.exp + ring_exp)) {
messagef(1, "the trap failed");
return;
}
switch(t) {
case TRAP_DOOR:
trap_door = 1;
new_level_message = trap_strings[(t*2)+1];
break;
case BEAR_TRAP:
messagef(1, "%s", trap_strings[(t*2)+1]);
bear_trap = get_rand(4, 7);
break;
case TELE_TRAP:
mvaddch(rogue.row, rogue.col, '^');
tele();
break;
case DART_TRAP:
messagef(1, "%s", trap_strings[(t*2)+1]);
rogue.hp_current -= get_damage("1d6", 1);
if (rogue.hp_current <= 0) {
rogue.hp_current = 0;
}
if ((!sustain_strength) && rand_percent(40) &&
(rogue.str_current >= 3)) {
rogue.str_current--;
}
print_stats(STAT_HP | STAT_STRENGTH);
if (rogue.hp_current <= 0) {
killed_by((object *)0, POISON_DART);
}
break;
case SLEEPING_GAS_TRAP:
messagef(1, "%s", trap_strings[(t*2)+1]);
take_a_nap();
break;
case RUST_TRAP:
messagef(1, "%s", trap_strings[(t*2)+1]);
rust(NULL);
break;
}
}
void
add_traps(void)
{
short i, n, tries = 0;
short row, col;
if (cur_level <= 2) {
n = 0;
} else if (cur_level <= 7) {
n = get_rand(0, 2);
} else if (cur_level <= 11) {
n = get_rand(1, 2);
} else if (cur_level <= 16) {
n = get_rand(2, 3);
} else if (cur_level <= 21) {
n = get_rand(2, 4);
} else if (cur_level <= (AMULET_LEVEL + 2)) {
n = get_rand(3, 5);
} else {
n = get_rand(5, MAX_TRAPS);
}
for (i = 0; i < n; i++) {
traps[i].trap_type = get_rand(0, (TRAPS - 1));
if ((i == 0) && (party_room != NO_ROOM)) {
do {
row = get_rand((rooms[party_room].top_row+1),
(rooms[party_room].bottom_row-1));
col = get_rand((rooms[party_room].left_col+1),
(rooms[party_room].right_col-1));
tries++;
} while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
(dungeon[row][col] == NOTHING)) && (tries < 15));
if (tries >= 15) {
gr_row_col(&row, &col, (FLOOR | MONSTER));
}
} else {
gr_row_col(&row, &col, (FLOOR | MONSTER));
}
traps[i].trap_row = row;
traps[i].trap_col = col;
dungeon[row][col] |= (TRAP | HIDDEN);
}
}
void
id_trap(void)
{
short dir, row, col, d, t;
messagef(0, "direction? ");
while (!is_direction(dir = rgetchar(), &d)) {
sound_bell();
}
check_message();
if (dir == CANCEL) {
return;
}
row = rogue.row;
col = rogue.col;
get_dir_rc(d, &row, &col, 0);
if ((dungeon[row][col] & TRAP) && (!(dungeon[row][col] & HIDDEN))) {
t = trap_at(row, col);
messagef(0, "%s", trap_strings[t*2]);
} else {
messagef(0, "no trap there");
}
}
void
show_traps(void)
{
short i, j;
for (i = 0; i < DROWS; i++) {
for (j = 0; j < DCOLS; j++) {
if (dungeon[i][j] & TRAP) {
mvaddch(i, j, '^');
}
}
}
}
void
search(short n, boolean is_auto)
{
short s, i, j, row, col, t;
short shown = 0, found = 0;
static boolean reg_search;
for (i = -1; i <= 1; i++) {
for (j = -1; j <= 1; j++) {
row = rogue.row + i;
col = rogue.col + j;
if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
(col < 0) || (col >= DCOLS)) {
continue;
}
if (dungeon[row][col] & HIDDEN) {
found++;
}
}
}
for (s = 0; s < n; s++) {
for (i = -1; i <= 1; i++) {
for (j = -1; j <= 1; j++) {
row = rogue.row + i;
col = rogue.col + j ;
if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
(col < 0) || (col >= DCOLS)) {
continue;
}
if (dungeon[row][col] & HIDDEN) {
if (rand_percent(17 + (rogue.exp + ring_exp))) {
dungeon[row][col] &= (~HIDDEN);
if ((!blind) && ((row != rogue.row) ||
(col != rogue.col))) {
mvaddch(row, col, get_dungeon_char(row, col));
}
shown++;
if (dungeon[row][col] & TRAP) {
t = trap_at(row, col);
messagef(1, "%s",
trap_strings[t*2]);
}
}
}
if (((shown == found) && (found > 0)) || interrupted) {
return;
}
}
}
if ((!is_auto) && (reg_search = !reg_search)) {
(void)reg_move();
}
}
}

View File

@ -1,616 +0,0 @@
/* $NetBSD: use.c,v 1.11 2021/05/02 12:50:46 rillig Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* use.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
short halluc = 0;
short blind = 0;
short confused = 0;
short levitate = 0;
short haste_self = 0;
boolean see_invisible = 0;
short extra_hp = 0;
boolean detect_monster = 0;
boolean con_mon = 0;
static const char strange_feeling[] =
"you have a strange feeling for a moment, then it passes";
static const char *get_ench_color(void);
static void go_blind(void);
static void hold_monster(void);
static void idntfy(void);
static void potion_heal(int);
static void uncurse_all(void);
void
quaff(void)
{
short ch;
object *obj;
ch = pack_letter("quaff what?", POTION);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (obj->what_is != POTION) {
messagef(0, "you can't drink that");
return;
}
switch(obj->which_kind) {
case INCREASE_STRENGTH:
messagef(0, "you feel stronger now, what bulging muscles!");
rogue.str_current++;
if (rogue.str_current > rogue.str_max) {
rogue.str_max = rogue.str_current;
}
break;
case RESTORE_STRENGTH:
rogue.str_current = rogue.str_max;
messagef(0, "this tastes great, you feel warm all over");
break;
case HEALING:
messagef(0, "you begin to feel better");
potion_heal(0);
break;
case EXTRA_HEALING:
messagef(0, "you begin to feel much better");
potion_heal(1);
break;
case POISON:
if (!sustain_strength) {
rogue.str_current -= get_rand(1, 3);
if (rogue.str_current < 1) {
rogue.str_current = 1;
}
}
messagef(0, "you feel very sick now");
if (halluc) {
unhallucinate();
}
break;
case RAISE_LEVEL:
rogue.exp_points = level_points[rogue.exp - 1];
messagef(0, "you suddenly feel much more skillful");
add_exp(1, 1);
break;
case BLINDNESS:
go_blind();
break;
case HALLUCINATION:
messagef(0, "oh wow, everything seems so cosmic");
halluc += get_rand(500, 800);
break;
case DETECT_MONSTER:
show_monsters();
if (!(level_monsters.next_monster)) {
messagef(0, "%s", strange_feeling);
}
break;
case DETECT_OBJECTS:
if (level_objects.next_object) {
if (!blind) {
show_objects();
}
} else {
messagef(0, "%s", strange_feeling);
}
break;
case CONFUSION:
messagef(0, (halluc ? "what a trippy feeling" :
"you feel confused"));
cnfs();
break;
case LEVITATION:
messagef(0, "you start to float in the air");
levitate += get_rand(15, 30);
being_held = bear_trap = 0;
break;
case HASTE_SELF:
messagef(0, "you feel yourself moving much faster");
haste_self += get_rand(11, 21);
if (!(haste_self % 2)) {
haste_self++;
}
break;
case SEE_INVISIBLE:
messagef(0, "hmm, this potion tastes like %sjuice",
fruit);
if (blind) {
unblind();
}
see_invisible = 1;
relight();
break;
}
print_stats((STAT_STRENGTH | STAT_HP));
if (id_potions[obj->which_kind].id_status != CALLED) {
id_potions[obj->which_kind].id_status = IDENTIFIED;
}
vanish(obj, 1, &rogue.pack);
}
void
read_scroll(void)
{
short ch;
object *obj;
ch = pack_letter("read what?", SCROL);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (obj->what_is != SCROL) {
messagef(0, "you can't read that");
return;
}
switch(obj->which_kind) {
case SCARE_MONSTER:
messagef(0, "you hear a maniacal laughter in the distance");
break;
case HOLD_MONSTER:
hold_monster();
break;
case ENCH_WEAPON:
if (rogue.weapon) {
if (rogue.weapon->what_is == WEAPON) {
messagef(0, "your %sglow%s %sfor a moment",
name_of(rogue.weapon),
((rogue.weapon->quantity <= 1) ? "s" : ""),
get_ench_color());
if(rand() & 1)
rogue.weapon->hit_enchant++;
else
rogue.weapon->d_enchant++;
}
rogue.weapon->is_cursed = 0;
} else {
messagef(0, "your hands tingle");
}
break;
case ENCH_ARMOR:
if (rogue.armor) {
messagef(0, "your armor glows %sfor a moment",
get_ench_color());
rogue.armor->d_enchant++;
rogue.armor->is_cursed = 0;
print_stats(STAT_ARMOR);
} else {
messagef(0, "your skin crawls");
}
break;
case IDENTIFY:
messagef(0, "this is a scroll of identify");
obj->identified = 1;
id_scrolls[obj->which_kind].id_status = IDENTIFIED;
idntfy();
break;
case TELEPORT:
tele();
break;
case SLEEP:
messagef(0, "you fall asleep");
take_a_nap();
break;
case PROTECT_ARMOR:
if (rogue.armor) {
messagef(0, "your armor is covered by a shimmering gold shield");
rogue.armor->is_protected = 1;
rogue.armor->is_cursed = 0;
} else {
messagef(0, "your acne seems to have disappeared");
}
break;
case REMOVE_CURSE:
messagef(0, (!halluc) ?
"you feel as though someone is watching over you" :
"you feel in touch with the universal oneness");
uncurse_all();
break;
case CREATE_MONSTER:
create_monster();
break;
case AGGRAVATE_MONSTER:
aggravate();
break;
case MAGIC_MAPPING:
messagef(0, "this scroll seems to have a map on it");
draw_magic_map();
break;
case CON_MON:
con_mon = 1;
messagef(0, "your hands glow %sfor a moment",
get_ench_color());
break;
}
if (id_scrolls[obj->which_kind].id_status != CALLED) {
id_scrolls[obj->which_kind].id_status = IDENTIFIED;
}
vanish(obj, (obj->which_kind != SLEEP), &rogue.pack);
}
/* vanish() does NOT handle a quiver of weapons with more than one
* arrow (or whatever) in the quiver. It will only decrement the count.
*/
void
vanish(object *obj, short rm, object *pack)
{
if (obj->quantity > 1) {
obj->quantity--;
} else {
if (obj->in_use_flags & BEING_WIELDED) {
unwield(obj);
} else if (obj->in_use_flags & BEING_WORN) {
unwear(obj);
} else if (obj->in_use_flags & ON_EITHER_HAND) {
un_put_on(obj);
}
take_from_pack(obj, pack);
free_object(obj);
}
if (rm) {
(void)reg_move();
}
}
static void
potion_heal(int extra)
{
float ratio;
short add;
rogue.hp_current += rogue.exp;
ratio = ((float)rogue.hp_current) / rogue.hp_max;
if (ratio >= 1.00) {
rogue.hp_max += (extra ? 2 : 1);
extra_hp += (extra ? 2 : 1);
rogue.hp_current = rogue.hp_max;
} else if (ratio >= 0.90) {
rogue.hp_max += (extra ? 1 : 0);
extra_hp += (extra ? 1 : 0);
rogue.hp_current = rogue.hp_max;
} else {
if (ratio < 0.33) {
ratio = 0.33;
}
if (extra) {
ratio += ratio;
}
add = (short)(ratio * (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();
} else if (confused) {
confused = (confused / 2) + 1;
}
if (halluc && extra) {
unhallucinate();
} else if (halluc) {
halluc = (halluc / 2) + 1;
}
}
static void
idntfy(void)
{
short ch;
object *obj;
struct id *id_table;
char desc[DCOLS];
AGAIN:
ch = pack_letter("what would you like to identify?", ALL_OBJECTS);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item, try again");
messagef(0, "%s", ""); /* gcc objects to just "" */
check_message();
goto AGAIN;
}
obj->identified = 1;
if (obj->what_is & (SCROL | POTION | WEAPON | ARMOR | WAND | RING)) {
id_table = get_id_table(obj);
id_table[obj->which_kind].id_status = IDENTIFIED;
}
get_desc(obj, desc, sizeof(desc));
messagef(0, "%s", desc);
}
void
eat(void)
{
short ch;
short moves;
object *obj;
ch = pack_letter("eat what?", FOOD);
if (ch == CANCEL) {
return;
}
if (!(obj = get_letter_object(ch))) {
messagef(0, "no such item.");
return;
}
if (obj->what_is != FOOD) {
messagef(0, "you can't eat that");
return;
}
if ((obj->which_kind == FRUIT) || rand_percent(60)) {
moves = get_rand(950, 1150);
if (obj->which_kind == RATION) {
messagef(0, "yum, that tasted good");
} else {
messagef(0, "my, that was a yummy %s", fruit);
}
} else {
moves = get_rand(750, 950);
messagef(0, "yuk, that food tasted awful");
add_exp(2, 1);
}
rogue.moves_left /= 3;
rogue.moves_left += moves;
hunger_str[0] = 0;
print_stats(STAT_HUNGER);
vanish(obj, 1, &rogue.pack);
}
static void
hold_monster(void)
{
short i, j;
short mcount = 0;
object *monster;
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 > (DROWS-2)) || (col < 0) ||
(col > (DCOLS-1))) {
continue;
}
if (dungeon[row][col] & MONSTER) {
monster = object_at(&level_monsters, row, col);
monster->m_flags |= ASLEEP;
monster->m_flags &= (~WAKENS);
mcount++;
}
}
}
if (mcount == 0) {
messagef(0, "you feel a strange sense of loss");
} else if (mcount == 1) {
messagef(0, "the monster freezes");
} else {
messagef(0, "the monsters around you freeze");
}
}
void
tele(void)
{
mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
if (cur_room >= 0) {
darken_room(cur_room);
}
put_player(get_room_number(rogue.row, rogue.col));
being_held = 0;
bear_trap = 0;
}
void
hallucinate(void)
{
object *obj, *monster;
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(gr_obj_char());
}
obj = obj->next_object;
}
monster = level_monsters.next_monster;
while (monster) {
ch = mvinch(monster->row, monster->col);
if ((ch >= 'A') && (ch <= 'Z')) {
addch(get_rand('A', 'Z'));
}
monster = monster->next_monster;
}
}
void
unhallucinate(void)
{
halluc = 0;
relight();
messagef(1, "everything looks SO boring now");
}
void
unblind(void)
{
blind = 0;
messagef(1, "the veil of darkness lifts");
relight();
if (halluc) {
hallucinate();
}
if (detect_monster) {
show_monsters();
}
}
void
relight(void)
{
if (cur_room == PASSAGE) {
light_passage(rogue.row, rogue.col);
} else {
light_up_room(cur_room);
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
}
void
take_a_nap(void)
{
short i;
i = get_rand(2, 5);
md_sleep(1);
while (i--) {
mv_mons();
}
md_sleep(1);
messagef(0, "%s", you_can_move_again);
}
static void
go_blind(void)
{
short i, j;
if (!blind) {
messagef(0, "a cloak of darkness falls around you");
}
blind += get_rand(500, 800);
if (detect_monster) {
object *monster;
monster = level_monsters.next_monster;
while (monster) {
mvaddch(monster->row, monster->col, monster->trail_char);
monster = monster->next_monster;
}
}
if (cur_room >= 0) {
for (i = rooms[cur_room].top_row + 1;
i < rooms[cur_room].bottom_row; i++) {
for (j = rooms[cur_room].left_col + 1;
j < rooms[cur_room].right_col; j++) {
mvaddch(i, j, ' ');
}
}
}
mvaddch(rogue.row, rogue.col, rogue.fchar);
}
static const char *
get_ench_color(void)
{
if (halluc) {
return(id_potions[get_rand(0, POTIONS-1)].title);
} else if (con_mon) {
return("red ");
}
return("blue ");
}
void
cnfs(void)
{
confused += get_rand(12, 22);
}
void
unconfuse(void)
{
confused = 0;
messagef(1, "you feel less %s now", (halluc ? "trippy" : "confused"));
}
static void
uncurse_all(void)
{
object *obj;
obj = rogue.pack.next_object;
while (obj) {
obj->is_cursed = 0;
obj = obj->next_object;
}
}

View File

@ -1,400 +0,0 @@
/* $NetBSD: zap.c,v 1.9 2008/01/14 03:50:03 dholland Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* zap.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "random.h"
#include "rogue.h"
static object *get_zapped_monster(short, short *, short *);
static void tele_away(object *);
static void wdrain_life(object *);
static void zap_monster(object *, unsigned short);
boolean wizard = 0;
void
zapp(void)
{
short wch;
boolean first_miss = 1;
object *wand;
short dir, d, row, col;
object *monster;
while (!is_direction(dir = rgetchar(), &d)) {
sound_bell();
if (first_miss) {
messagef(0, "direction? ");
first_miss = 0;
}
}
check_message();
if (dir == CANCEL) {
return;
}
if ((wch = pack_letter("zap with what?", WAND)) == CANCEL) {
return;
}
check_message();
if (!(wand = get_letter_object(wch))) {
messagef(0, "no such item.");
return;
}
if (wand->what_is != WAND) {
messagef(0, "you can't zap with that");
return;
}
if (wand->class <= 0) {
messagef(0, "nothing happens");
} else {
wand->class--;
row = rogue.row; col = rogue.col;
if ((wand->which_kind == COLD) || (wand->which_kind == FIRE)) {
bounce((short)wand->which_kind, d, row, col, 0);
} else {
monster = get_zapped_monster(d, &row, &col);
if (wand->which_kind == DRAIN_LIFE) {
wdrain_life(monster);
} else if (monster) {
wake_up(monster);
s_con_mon(monster);
zap_monster(monster, wand->which_kind);
relight();
}
}
}
(void)reg_move();
}
static object *
get_zapped_monster(short dir, short *row, short *col)
{
short orow, ocol;
for (;;) {
orow = *row; ocol = *col;
get_dir_rc(dir, row, col, 0);
if (((*row == orow) && (*col == ocol)) ||
(dungeon[*row][*col] & (HORWALL | VERTWALL)) ||
(dungeon[*row][*col] == NOTHING)) {
return(0);
}
if (dungeon[*row][*col] & MONSTER) {
if (!imitating(*row, *col)) {
return(object_at(&level_monsters, *row, *col));
}
}
}
}
static void
zap_monster(object *monster, unsigned short kind)
{
short row, col;
object *nm;
short tc;
row = monster->row;
col = monster->col;
switch(kind) {
case SLOW_MONSTER:
if (monster->m_flags & HASTED) {
monster->m_flags &= (~HASTED);
} else {
monster->slowed_toggle = 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 TELE_AWAY:
tele_away(monster);
break;
case INVISIBILITY:
monster->m_flags |= INVISIBLE;
break;
case POLYMORPH:
if (monster->m_flags & HOLDS) {
being_held = 0;
}
nm = monster->next_monster;
tc = monster->trail_char;
(void)gr_monster(monster, get_rand(0, MONSTERS-1));
monster->row = row;
monster->col = col;
monster->next_monster = nm;
monster->trail_char = tc;
if (!(monster->m_flags & IMITATES)) {
wake_up(monster);
}
break;
case MAGIC_MISSILE:
if(monster != NULL)
rogue_hit(monster, 1);
break;
case CANCELLATION:
if (monster->m_flags & HOLDS) {
being_held = 0;
}
if (monster->m_flags & STEALS_ITEM) {
monster->drop_percent = 0;
}
monster->m_flags &= (~(FLIES | FLITS | SPECIAL_HIT | INVISIBLE |
FLAMES | IMITATES | CONFUSES | SEEKS_GOLD | HOLDS));
break;
case DO_NOTHING:
messagef(0, "nothing happens");
break;
}
}
static void
tele_away(object *monster)
{
short row, col;
if (monster->m_flags & HOLDS) {
being_held = 0;
}
gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
mvaddch(monster->row, monster->col, monster->trail_char);
dungeon[monster->row][monster->col] &= ~MONSTER;
monster->row = row; monster->col = col;
dungeon[row][col] |= MONSTER;
monster->trail_char = mvinch(row, col);
if (detect_monster || rogue_can_see(row, col)) {
mvaddch(row, col, gmc(monster));
}
}
void
wizardize(void)
{
char buf[100];
if (wizard) {
wizard = 0;
messagef(0, "not wizard anymore");
} else {
if (get_input_line("wizard's password:", "", buf, sizeof(buf),
"", 0, 0)) {
(void)xxx(1);
xxxx(buf, strlen(buf));
if (!strncmp(buf, "\247\104\126\272\115\243\027", 7)) {
wizard = 1;
score_only = 1;
messagef(0, "Welcome, mighty wizard!");
} else {
messagef(0, "sorry");
}
}
}
}
static void
wdrain_life(object *monster)
{
short hp;
object *lmon, *nm;
hp = rogue.hp_current / 3;
rogue.hp_current = (rogue.hp_current + 1) / 2;
if (cur_room >= 0) {
lmon = level_monsters.next_monster;
while (lmon) {
nm = lmon->next_monster;
if (get_room_number(lmon->row, lmon->col) == cur_room) {
wake_up(lmon);
(void)mon_damage(lmon, hp);
}
lmon = nm;
}
} else {
if (monster) {
wake_up(monster);
(void)mon_damage(monster, hp);
}
}
print_stats(STAT_HP);
relight();
}
void
bounce(short ball, short dir, short row, short col, short r)
{
short orow, ocol;
const char *s;
short i, ch, new_dir = -1, damage;
static short btime;
if (++r == 1) {
btime = get_rand(3, 6);
} else if (r > btime) {
return;
}
if (ball == FIRE) {
s = "fire";
} else {
s = "ice";
}
if (r > 1) {
messagef(0, "the %s bounces", s);
}
orow = row;
ocol = col;
do {
ch = mvinch(orow, ocol);
standout();
mvaddch(orow, ocol, ch);
get_dir_rc(dir, &orow, &ocol, 1);
} while (!( (ocol <= 0) ||
(ocol >= DCOLS-1) ||
(dungeon[orow][ocol] == NOTHING) ||
(dungeon[orow][ocol] & MONSTER) ||
(dungeon[orow][ocol] & (HORWALL | VERTWALL)) ||
((orow == rogue.row) && (ocol == rogue.col))));
standend();
refresh();
do {
orow = row;
ocol = col;
ch = mvinch(row, col);
mvaddch(row, col, ch);
get_dir_rc(dir, &row, &col, 1);
} while (!( (col <= 0) ||
(col >= DCOLS-1) ||
(dungeon[row][col] == NOTHING) ||
(dungeon[row][col] & MONSTER) ||
(dungeon[row][col] & (HORWALL | VERTWALL)) ||
((row == rogue.row) && (col == rogue.col))));
if (dungeon[row][col] & MONSTER) {
object *monster;
monster = object_at(&level_monsters, row, col);
wake_up(monster);
if (rand_percent(33)) {
messagef(0, "the %s misses the %s", s,
mon_name(monster));
goto ND;
}
if (ball == FIRE) {
if (!(monster->m_flags & RUSTS)) {
if (monster->m_flags & FREEZES) {
damage = monster->hp_to_kill;
} else if (monster->m_flags & FLAMES) {
damage = (monster->hp_to_kill / 10) + 1;
} else {
damage = get_rand((rogue.hp_current / 3), rogue.hp_max);
}
} else {
damage = (monster->hp_to_kill / 2) + 1;
}
messagef(0, "the %s hits the %s", s,
mon_name(monster));
(void)mon_damage(monster, damage);
} else {
damage = -1;
if (!(monster->m_flags & FREEZES)) {
if (rand_percent(33)) {
messagef(0, "the monster is frozen");
monster->m_flags |= (ASLEEP | NAPPING);
monster->nap_length = get_rand(3, 6);
} else {
damage = rogue.hp_current / 4;
}
} else {
damage = -2;
}
if (damage != -1) {
messagef(0, "the %s hits the %s", s,
mon_name(monster));
(void)mon_damage(monster, damage);
}
}
} else if ((row == rogue.row) && (col == rogue.col)) {
if (rand_percent(10 + (3 * get_armor_class(rogue.armor)))) {
messagef(0, "the %s misses", s);
goto ND;
} else {
damage = get_rand(3, (3 * rogue.exp));
if (ball == FIRE) {
damage = (damage * 3) / 2;
damage -= get_armor_class(rogue.armor);
}
rogue_damage(damage, NULL,
((ball == FIRE) ? KFIRE : HYPOTHERMIA));
messagef(0, "the %s hits", s);
}
} else {
short nrow, ncol;
ND: for (i = 0; i < 10; i++) {
dir = get_rand(0, DIRS-1);
nrow = orow;
ncol = ocol;
get_dir_rc(dir, &nrow, &ncol, 1);
if (((ncol >= 0) && (ncol <= DCOLS-1)) &&
(dungeon[nrow][ncol] != NOTHING) &&
(!(dungeon[nrow][ncol] & (VERTWALL | HORWALL)))) {
new_dir = dir;
break;
}
}
if (new_dir != -1) {
bounce(ball, new_dir, orow, ocol, r);
}
}
}