too proprietary
This commit is contained in:
parent
745c653366
commit
a75414eb17
@ -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.
|
@ -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
|
443
wip/rogue/hit.c
443
wip/rogue/hit.c
@ -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;
|
||||
}
|
||||
}
|
365
wip/rogue/init.c
365
wip/rogue/init.c
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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]);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
646
wip/rogue/move.c
646
wip/rogue/move.c
@ -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));
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
565
wip/rogue/pack.c
565
wip/rogue/pack.c
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
186
wip/rogue/play.c
186
wip/rogue/play.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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))
|
332
wip/rogue/ring.c
332
wip/rogue/ring.c
@ -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();
|
||||
}
|
||||
}
|
@ -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.
|
@ -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;
|
664
wip/rogue/room.c
664
wip/rogue/room.c
@ -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
|
||||
}
|
418
wip/rogue/save.c
418
wip/rogue/save.c
@ -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);
|
||||
}
|
@ -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");
|
||||
}
|
@ -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);
|
||||
/*}*/
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
274
wip/rogue/trap.c
274
wip/rogue/trap.c
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
616
wip/rogue/use.c
616
wip/rogue/use.c
@ -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;
|
||||
}
|
||||
}
|
400
wip/rogue/zap.c
400
wip/rogue/zap.c
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user