home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part82
< prev
next >
Wrap
Internet Message Format
|
1993-02-06
|
59KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i090: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part82/108
Message-ID: <4453@master.CNA.TEK.COM>
Date: 5 Feb 93 19:21:33 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1937
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1641
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 90
Archive-name: nethack31/Part82
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 82 (of 108)."
# Contents: dat/Rogue.des src/u_init.c src/worm.c
# Wrapped by billr@saab on Wed Jan 27 16:09:19 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dat/Rogue.des' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dat/Rogue.des'\"
else
echo shar: Extracting \"'dat/Rogue.des'\" \(16887 characters\)
sed "s/^X//" >'dat/Rogue.des' <<'END_OF_FILE'
X# SCCS Id: @(#)Rogue.des 3.1 92/04/27
X# Copyright (c) 1992 by Dean Luick
X# NetHack may be freely redistributed. See license for details.
X#
X# The "start" level for the quest.
X#
X# Here you meet your (besieged) class leader, Master of Thieves
X# and receive your quest assignment.
X#
XMAZE: "R-start",' '
XFLAGS: noteleport, hardfloor, nommap
XGEOMETRY:center,center
XMAP
X# 1 2 3 4 5 6 7
X#123456789012345678901234567890123456789012345678901234567890123456789012345
X---------------------------------.------------------------------------------
X|.....|.||..........|....|......|.|.........|.......+............---.......|
X|.....|..+..........+....---....S.|...-------.-----.|............+.+.......|
X|.....+.||........---......|....|.|...|.....|.|...|.---.....------.--------|
X|-----|.-------|..|........------.-----.....|.--..|...-------..............|
X|.....|........------+------..........+.....|..------.........------.-----..
X|.....|.------...............-----.}}.--------.|....-------.---....|.+...--|
X|..-+--.|....|-----.--------.|...|.....+.....|.|....|.....+.+......|.--....|
X|..|....|....|....+.|......|.|...-----.|.....|.--...|.....|.|......|..|....|
X|..|.----------...|.+....-----...|...|.----..|..|.---....--.---S-----.|----|
X|..|.|........|...------.|.S.....|...|....-----.+.|......|..|.......|.|....|
X|---.-------..|...|....|.|.|.....|...----.|...|.|---.....|.|-.......|.---..|
X...........|..|...|....---.----S----..|...|...+.|..-------.---+-....|...--+|
X|---------.---------...|......|....S..|.---...|.|..|...........----.---....|
X|........|.........|...+.------....|---.---...|.--+-.----.----....|.+...--+|
X|........|.---+---.|----.--........|......-----......|..|..|.--+-.|.-S-.|..|
X|........|.|.....|........----------.----.......---.--..|-.|....|.-----.|..|
X|----....+.|.....----+---............|..|--------.+.|...SS.|....|.......|..|
X|...--+-----.....|......|.------------............---...||.------+--+----..|
X|..........S.....|......|.|..........S............|.....||...|.....|....|..|
X-------------------------.--------------------------------------------------
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'l', 'N'
X# Dungeon Description
X#REGION:(00,00,75,20),lit,"ordinary"
X# The down stairs is at one of the 4 "exits". The others are mimics,
X# mimicing stairwells.
XRANDOM_PLACES: (33,0), (0,12), (25,20), (75,05)
XSTAIR:place[0],down
XMONSTER:'m',"giant mimic", place[1], m_feature "staircase down"
XMONSTER:'m',"large mimic", place[2], m_feature "staircase down"
XMONSTER:'m',"small mimic", place[3], m_feature "staircase down"
X# Portal arrival point
XBRANCH:(19,09,19,09),(0,0,0,0)
X# Doors (secret)
X#DOOR:locked|closed|open,(xx,yy)
XDOOR: locked, (32, 2)
XDOOR: locked, (63, 9)
XDOOR: locked, (27,10)
XDOOR: locked, (31,12)
XDOOR: locked, (35,13)
XDOOR: locked, (69,15)
XDOOR: locked, (56,17)
XDOOR: locked, (57,17)
XDOOR: locked, (11,19)
XDOOR: locked, (37,19)
X# Doors (regular)
XDOOR: closed, (52, 1)
XDOOR: closed, ( 9, 2)
XDOOR: closed, (20, 2)
XDOOR: closed, (65, 2)
XDOOR: closed, (67, 2)
XDOOR: closed, ( 6, 3)
XDOOR: closed, (21, 5)
XDOOR: closed, (38, 5)
XDOOR: closed, (69, 6)
XDOOR: closed, ( 4, 7)
XDOOR: closed, (39, 7)
XDOOR: closed, (58, 7)
XDOOR: closed, (60, 7)
XDOOR: closed, (18, 8)
XDOOR: closed, (20, 9)
XDOOR: closed, (48,10)
XDOOR: closed, (46,12)
XDOOR: closed, (62,12)
XDOOR: closed, (74,12)
XDOOR: closed, (23,14)
XDOOR: closed, (23,14)
XDOOR: closed, (50,14)
XDOOR: closed, (68,14)
XDOOR: closed, (74,14)
XDOOR: closed, (14,15)
XDOOR: closed, (63,15)
XDOOR: closed, ( 9,17)
XDOOR: closed, (21,17)
XDOOR: closed, (50,17)
XDOOR: closed, ( 6,18)
XDOOR: closed, (65,18)
XDOOR: closed, (68,18)
X# Master of Thieves
XMONSTER:'@',"Master of Thieves",(36,11)
X# The treasure of Master of Thieves
XOBJECT:'(',"chest",(36,11)
X# thug guards, room #1
XMONSTER:'@',"thug",(28,10)
XMONSTER:'@',"thug",(29,11)
XMONSTER:'@',"thug",(30,09)
XMONSTER:'@',"thug",(31,07)
X# thug guards, room #2
XMONSTER:'@',"thug",(31,13)
XMONSTER:'@',"thug",(33,14)
XMONSTER:'@',"thug",(30,15)
X#thug guards, room #3
XMONSTER:'@',"thug",(35,09)
XMONSTER:'@',"thug",(36,13)
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,20)
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X#
X# Monsters to get in the way.
X#
X# West exit
XMONSTER: 'l',"leprechaun",(01,12),hostile
XMONSTER: 'n',"water nymph",(02,12),hostile
X# North exit
XMONSTER: 'n',"water nymph",(33,01),hostile
XMONSTER: 'l',"leprechaun",(33,02),hostile
X# East exit
XMONSTER: 'n',"water nymph",(74,05),hostile
XMONSTER: 'l',"leprechaun",(74,04),hostile
X# South exit
XMONSTER: 'l',"leprechaun",(25,19),hostile
XMONSTER: 'n',"water nymph",(25,18),hostile
X# Wandering the streets. What I'd really like for this is a random
X# location, but make sure we're on a given type, e.g. street (if they
X# existed, of course).
XMONSTER: 'n',"water nymph",(07,05),hostile
XMONSTER: 'l',"leprechaun",(28,06),hostile
XMONSTER: 'n',"water nymph",(38,07),hostile
XMONSTER: 'l',"leprechaun",(45,01),hostile
XMONSTER: 'n',"water nymph",(59,07),hostile
XMONSTER: 'l',"leprechaun",(62,14),hostile
XMONSTER: 'n',"water nymph",(71,14),hostile
XMONSTER: 'l',"leprechaun",(39,13),hostile
XMONSTER: 'n',"water nymph",(18,14),hostile
XMONSTER: ':',"chameleon",(19,08),hostile
XMONSTER: ':',"chameleon",(22,08),hostile
XMONSTER: ':',"chameleon",(16,08),hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
X
X#
X# The "locate" level for the quest.
X#
X# Here you have to find the entrance to the Assassins' Guild to go
X# further towards your assigned quest.
X#
X
XMAZE: "R-locate",' '
XGEOMETRY:center,center
XMAP
X# 1 2 3 4 5 6 7
X#123456789012345678901234567890123456789012345678901234567890123456789012345
X ---------------------------------------------------- --------
X ---.................................................- --......
X ---...--------........------........................--- ---....
X ---.....- --.......- ---..................---- --.--
X ---.....---- ------- --..................-- --..|
X ---...----- ----.----.....----.....--- --..||
X----..---- -----..--- |...--- |.......--- --...|
X|...--- ----....--- |.--- |.........-- --...||
X|...- ----.....--- ---- |..........---....|
X|...---- ----......--- | |...|.......-....||
X|......----- ---.........- | -----...|............|
X|..........----- ----...........--- -------......||...........||
X|..............-----................--- |............|||..........|
X|------...............................--- |...........|| |.........||
X|.....|..............------.............-----..........|| ||........|
X|.....|.............-- ---.........................|| |.......||
X|.....|.............- ---.....................--| ||......|
X|------------.......---- --.................---- |.....||
X|...........|..........--------..............----- ||....|
X|...........|............................----- |....|
X------------------------------------------ ------
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'l', 'N'
X# Dungeon Description
XREGION:(00,00,75,20),lit,"ordinary"
X# Doors
X#DOOR:locked|closed|open,(xx,yy)
X# Stairs
XSTAIR:random,up
XSTAIR:random,down
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,20)
X# Objects
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X# Random monsters.
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',random,random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
X
X#
X# The "goal" level for the quest.
X#
X# Here you meet The Master Assassin your nemesis monster. You have to
X# defeat The Master Assassin in combat to gain the artifact you have
X# been assigned to retrieve.
X#
XMAZE: "R-goal", ' '
XFLAGS: noteleport
XGEOMETRY:center,center
XMAP
X# 1 2 3 4 5 6 7
X#123456789012345678901234567890123456789012345678901234567890123456789012345
X----- -------.......................................|-----------------|
X|...| -----.....|.......................................|.................|
X|...----...|.....|.......................................|....---------....|
X|.---......---..--.................................------------.......|....|
X|...............|..................................|..|...|...----........-|
X|.....-----....--.................................|-..--..-|.....---------|
X|------...|....|.................................|-........-|....|........|
X|.........---------.............................|-....}}....-|...|...|....|
X|....|.....|......|............................|-.....}}.....-|..--.------|
X|-----.....--.....|...........................|-...}}}}}}}}...-|....|.....--
X|...........--....------------...............|-....}}}}}}}}....-|..........|
X|............--........|...|.|..............--.....}}.}}........------------
X|.............|........|...|.|..............|......}}}}}}}}......|...|.....|
X|--.---.---.---.---.---|...|.------------...--........}}.}}.....--..---....|
X|.---.---.---.---.---..-----.|....|.....|....|-....}}}}}}}}....---..|.|--..|
X|...|.......|..........|...---....---...S.....|-...}}}}}}}}...-|.|..|...|..|
X|...|..|....|..........|............|..--..----|-.....}}.....-|..----...----
X|...|---....----.......|----- ......|...---| |-....}}....-|...|..-----..|
X-----.....---.....--.---....--...--------..| |-........-|....|.........|
X |.............|..........|.............S... |S-------|.....|..-----..|
X ---------------------------------------- ...... ---------- ----
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: '@', 'g', 'n'
X# Dungeon Description
XREGION:(00,00,75,20),lit,"ordinary"
X# Stairs
XSTAIR:random,up
X# Doors
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,20)
X# One trap to keep the gnomes at bay.
XTRAP:"spiked pit",(37,07)
X# Objects
XOBJECT:'(',"skeleton key",(38,10),blessed,0,"The Master Key of Thievery"
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X# Random monsters.
XMONSTER:'@',"Master Assassin",(38,10),hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',"leprechaun",random,hostile
XMONSTER:'l',random,random,hostile
XMONSTER:'l',random,random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',"guardian naga",random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER:'N',random,random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
XMONSTER: ':',"chameleon",random,hostile
X
X#
X# The "fill" level for the quest.
X#
X# This level is used to fill out any levels not occupied by specific
X# levels as defined above.
X#
XLEVEL: "R-filla"
X# Random Monsters
XRANDOM_MONSTERS: 'l', 'N', 'n', ':'
X#
XROOM: "ordinary" , random, random, random, random
XSTAIR: random, up
XOBJECT: random,random,random
XMONSTER: 'l', "leprechaun", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XOBJECT: random,random,random
XMONSTER: 'l', "leprechaun", random, hostile
XMONSTER: 'N', "guardian naga", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XOBJECT: random,random,random
XMONSTER: 'n', "water nymph", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XSTAIR: random, down
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', random, random, hostile
XMONSTER: 'N', "guardian naga", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', "leprechaun", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', "leprechaun", random, hostile
XMONSTER: 'n', "water nymph", random, hostile
X
XRANDOM_CORRIDORS
X
X#
X# currently a & b are the same.
X#
XLEVEL: "R-fillb"
X# Random Monsters
XRANDOM_MONSTERS: 'l', 'N', 'n', ':'
X#
XROOM: "ordinary" , random, random, random, random
XSTAIR: random, up
XOBJECT: random,random,random
XMONSTER: 'l', "leprechaun", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XOBJECT: random,random,random
XMONSTER: 'l', "leprechaun", random, hostile
XMONSTER: 'N', "guardian naga", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XOBJECT: random,random,random
XMONSTER: 'n', "water nymph", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XSTAIR: random, down
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', random, random, hostile
XMONSTER: 'N', "guardian naga", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', "leprechaun", random, hostile
X
XROOM: "ordinary" , random, random, random, random
XOBJECT: random, random, random
XTRAP: random, random
XTRAP: random, random
XMONSTER: 'l', "leprechaun", random, hostile
XMONSTER: 'n', "water nymph", random, hostile
X
XRANDOM_CORRIDORS
END_OF_FILE
if test 16887 -ne `wc -c <'dat/Rogue.des'`; then
echo shar: \"'dat/Rogue.des'\" unpacked with wrong size!
fi
# end of 'dat/Rogue.des'
fi
if test -f 'src/u_init.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/u_init.c'\"
else
echo shar: Extracting \"'src/u_init.c'\" \(18225 characters\)
sed "s/^X//" >'src/u_init.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)u_init.c 3.1 92/11/13 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
Xstruct trobj {
X unsigned short int trotyp;
X schar trspe;
X char trclass;
X Bitfield(trquan,6);
X Bitfield(trknown,1);
X Bitfield(trbless,2);
X};
X
Xstatic void FDECL(ini_inv, (struct trobj *));
Xstatic void FDECL(knows_object,(int));
Xstatic void FDECL(knows_class,(CHAR_P));
Xstatic int FDECL(role_index,(CHAR_P));
X
X#define UNDEF_TYP 0
X#define UNDEF_SPE '\177'
X#define UNDEF_BLESS 2
X
X/* all roles must all have distinct first letter */
Xconst char *roles[] = { /* also used in options.c and winxxx.c */
X /* roles[2] and [6] are changed for females */
X /* in all cases, the corresponding male and female */
X /* roles must start with the same letter */
X "Archeologist", "Barbarian", "Caveman", "Elf", "Healer", "Knight",
X "Priest", "Rogue", "Samurai",
X#ifdef TOURIST
X "Tourist",
X#endif
X "Valkyrie", "Wizard", 0
X};
X
Xstatic struct trobj Cave_man[] = {
X#define C_ARROWS 2
X { CLUB, 1, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { BOW, 1, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { ARROW, 0, WEAPON_CLASS, 25, 1, UNDEF_BLESS }, /* quan is variable */
X { LEATHER_ARMOR, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Barbarian[] = {
X#define B_MAJOR 0 /* two-handed sword or battle-axe */
X#define B_MINOR 1 /* matched with axe or short sword */
X { TWO_HANDED_SWORD, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { AXE, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { RING_MAIL, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { FOOD_RATION, 0, FOOD_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Knight[] = {
X { LONG_SWORD, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { SPEAR, 2, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { RING_MAIL, 1, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { HELMET, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { SMALL_SHIELD, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { LEATHER_GLOVES, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Elf[] = {
X#define E_ARROWS 2
X#define E_ARMOR 3
X { ELVEN_SHORT_SWORD, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { ELVEN_BOW, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { ELVEN_ARROW, 0, WEAPON_CLASS, 25, 1, UNDEF_BLESS },
X { UNDEF_TYP, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { LEMBAS_WAFER, 0, FOOD_CLASS, 2, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Valkyrie[] = {
X { LONG_SWORD, 1, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { DAGGER, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { SMALL_SHIELD, 3, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { FOOD_RATION, 0, FOOD_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Healer[] = {
X { SCALPEL, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { LEATHER_GLOVES, 1, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { STETHOSCOPE, 0, TOOL_CLASS, 1, 1, 0 },
X { POT_HEALING, 0, POTION_CLASS, 4, 1, UNDEF_BLESS },
X { POT_EXTRA_HEALING, 0, POTION_CLASS, 4, 1, UNDEF_BLESS },
X { WAN_SLEEP, UNDEF_SPE, WAND_CLASS, 1, 1, UNDEF_BLESS },
X /* always blessed, so it's guaranteed readable */
X { SPE_HEALING, 0, SPBOOK_CLASS, 1, 1, 1 },
X { SPE_EXTRA_HEALING, 0, SPBOOK_CLASS, 1, 1, 1 },
X { APPLE, 0, FOOD_CLASS, 5, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Archeologist[] = {
X /* if adventure has a name... idea from tan@uvm-gen */
X { BULLWHIP, 2, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { LEATHER_JACKET, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { FEDORA, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { FOOD_RATION, 0, FOOD_CLASS, 3, 1, 0 },
X { PICK_AXE, UNDEF_SPE, TOOL_CLASS, 1, 1, UNDEF_BLESS },
X { TINNING_KIT, 0, TOOL_CLASS, 1, 1, UNDEF_BLESS },
X { SACK, 0, TOOL_CLASS, 1, 0, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Tinopener[] = {
X { TIN_OPENER, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Magicmarker[] = {
X { MAGIC_MARKER, UNDEF_SPE, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Lamp[] = {
X { OIL_LAMP, 1, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
X#ifdef TOURIST
X# ifdef WALKIES
Xstatic struct trobj Leash[] = {
X { LEASH, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X# endif
X
Xstatic struct trobj Towel[] = {
X { TOWEL, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X#endif
X
X#ifdef EXPLORE_MODE
Xstatic struct trobj Wishing[] = {
X { WAN_WISHING, 3, WAND_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X#endif
X
Xstatic struct trobj Instrument[] = {
X { WOODEN_FLUTE, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Blindfold[] = {
X { BLINDFOLD, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
X#ifdef TOURIST
Xstatic struct trobj Tourist[] = {
X#define T_DARTS 0
X { DART, 2, WEAPON_CLASS, 25, 1, UNDEF_BLESS }, /* quan is variable */
X { UNDEF_TYP, UNDEF_SPE, FOOD_CLASS, 10, 1, 0 },
X { POT_EXTRA_HEALING, 0, POTION_CLASS, 2, 1, UNDEF_BLESS },
X { SCR_MAGIC_MAPPING, 0, SCROLL_CLASS, 4, 1, UNDEF_BLESS },
X { HAWAIIAN_SHIRT, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { EXPENSIVE_CAMERA, 0, TOOL_CLASS, 1, 1, 0 },
X { CREDIT_CARD, 0, TOOL_CLASS, 1, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X#endif
X
Xstatic struct trobj Rogue[] = {
X#define R_DAGGERS 1
X { SHORT_SWORD, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { DAGGER, 0, WEAPON_CLASS, 10, 1, 0 }, /* quan is variable */
X { LEATHER_ARMOR, 1, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { POT_SICKNESS, 0, POTION_CLASS, 1, 1, 0 },
X { LOCK_PICK, 9, TOOL_CLASS, 1, 1, 0 },
X { SACK, 0, TOOL_CLASS, 1, 0, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Wizard[] = {
X#define W_MULTSTART 2
X#define W_MULTEND 6
X { ATHAME, 1, WEAPON_CLASS, 1, 1, 1 }, /* for dealing with ghosts */
X { CLOAK_OF_MAGIC_RESISTANCE, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { UNDEF_TYP, UNDEF_SPE, WAND_CLASS, 1, 1, UNDEF_BLESS },
X { UNDEF_TYP, UNDEF_SPE, RING_CLASS, 2, 1, UNDEF_BLESS },
X { UNDEF_TYP, UNDEF_SPE, POTION_CLASS, 3, 1, UNDEF_BLESS },
X { UNDEF_TYP, UNDEF_SPE, SCROLL_CLASS, 3, 1, UNDEF_BLESS },
X { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, 1, UNDEF_BLESS },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Samurai[] = {
X#define S_ARROWS 3
X { KATANA, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { SHORT_SWORD, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS }, /* wakizashi */
X { YUMI, 0, WEAPON_CLASS, 1, 1, UNDEF_BLESS },
X { YA, 0, WEAPON_CLASS, 25, 1, UNDEF_BLESS }, /* variable quan */
X { SPLINT_MAIL, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { FORTUNE_COOKIE, 0, FOOD_CLASS, 3, 1, 0 },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic struct trobj Priest[] = {
X { MACE, 1, WEAPON_CLASS, 1, 1, 1 },
X { CHAIN_MAIL, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { SMALL_SHIELD, 0, ARMOR_CLASS, 1, 1, UNDEF_BLESS },
X { POT_WATER, 0, POTION_CLASS, 4, 1, 1 }, /* holy water */
X { CLOVE_OF_GARLIC, 0, FOOD_CLASS, 1, 1, 0 },
X { SPRIG_OF_WOLFSBANE, 0, FOOD_CLASS, 1, 1, 0 },
X { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 2, 1, UNDEF_BLESS },
X { 0, 0, 0, 0, 0, 0 }
X};
X
Xstatic void
Xknows_object(obj)
Xregister int obj;
X{
X makeknown(obj);
X objects[obj].oc_descr_idx = 0; /* not a "discovery" */
X}
X
X/* Know ordinary (non-magical) objects of a certain class,
X * like all gems except the loadstone and luckstone.
X */
Xstatic void
Xknows_class(sym)
Xregister char sym;
X{
X register int ct;
X for (ct = 1; ct <= NROFOBJECTS; ct++)
X if (objects[ct].oc_class == sym && !objects[ct].oc_magic)
X knows_object(ct);
X}
X
Xstatic int
Xrole_index(pc)
Xchar pc;
X{
X register const char *cp;
X
X if ((cp = index(pl_classes, pc)) != 0)
X return(cp - pl_classes);
X return(-1);
X}
X
Xvoid
Xu_init()
X{
X register int i;
X char pc;
X
X pc = pl_character[0];
X if(pc == '\0') {
X /* should be unnecessary now */
X exit_nhwindows(NULL);
X terminate(0);
X }
X i = role_index(pc);
X
X (void) strncpy(pl_character, roles[i], PL_CSIZ-1);
X pl_character[PL_CSIZ-1] = 0;
X flags.beginner = 1;
X
X /* zero u, including pointer values --
X * necessary when aborting from a failed restore */
X (void) memset((genericptr_t)&u, 0, sizeof(u));
X for (i = 0; i < LAST_PROP+1; i++) u.uprops[i].p_tofn = 0;
X u.ustuck = (struct monst *)0;
X
X#if 0 /* documentation of more zero values as desirable */
X u.uluck = u.moreluck = 0;
X# ifdef TOURIST
X uarmu = 0;
X# endif
X uarm = uarmc = uarmh = uarms = uarmg = uarmf = 0;
X uwep = uball = uchain = uleft = uright = 0;
X u.ublessed = 0; /* not worthy yet */
X u.ugangr = 0; /* gods not angry */
X# ifdef ELBERETH
X u.uevent.uhand_of_elbereth = 0;
X# endif
X u.uevent.uheard_tune = 0;
X u.uevent.uopened_dbridge = 0;
X u.uevent.udemigod = 0; /* not a demi-god yet... */
X u.udg_cnt = 0;
X# ifdef POLYSELF
X u.mh = u.mhmax = u.mtimedone = 0;
X# endif
X u.uz.dnum = u.uz0.dnum = 0;
X u.utotype = 0;
X#endif /* 0 */
X u.uz.dlevel = u.uz0.dlevel = 1;
X u.utolev = u.uz;
X
X u.usym = S_HUMAN;
X u.umoved = FALSE;
X u.ugrave_arise = -1;
X
X u.ulevel = 0; /* set up some of the initial attributes */
X u.uhp = u.uhpmax = newhp();
X adjabil(0,1);
X u.ulevel = 1;
X
X init_uhunger();
X u.uen = u.uenmax = 1;
X for (i = 0; i <= MAXSPELL; i++) spl_book[i].sp_id = NO_SPELL;
X u.ublesscnt = 300; /* no prayers just yet */
X#ifdef POLYSELF
X u.umonnum = -1;
X u.ulycn = -1;
X set_uasmon();
X#endif
X
X /*
X * For now, everyone starts out with a night vision range of 1 and
X * their xray range disabled.
X */
X u.nv_range = 1;
X u.xray_range = -1;
X
X
X switch(pc) {
X /* pc will always be in uppercase by this point */
X case 'A':
X u.umonster = PM_ARCHEOLOGIST;
X ini_inv(Archeologist);
X if(!rn2(10)) ini_inv(Tinopener);
X else if(!rn2(4)) ini_inv(Lamp);
X else if(!rn2(10)) ini_inv(Magicmarker);
X knows_class(GEM_CLASS);
X knows_object(SACK);
X /* We can't set trknown for it, then it'd be "uncursed"
X * sack...
X */
X break;
X case 'B':
X u.umonster = PM_BARBARIAN;
X if (rn2(100) >= 50) { /* see Elf comment */
X Barbarian[B_MAJOR].trotyp = BATTLE_AXE;
X Barbarian[B_MINOR].trotyp = SHORT_SWORD;
X }
X ini_inv(Barbarian);
X if(!rn2(6)) ini_inv(Lamp);
X knows_class(WEAPON_CLASS);
X knows_class(ARMOR_CLASS);
X break;
X case 'C':
X u.umonster = PM_CAVEMAN;
X Cave_man[C_ARROWS].trquan = rn1(30, 13);
X ini_inv(Cave_man);
X break;
X case 'E':
X u.umonster = PM_ELF;
X Elf[E_ARROWS].trquan = rn1(20, 16);
X Elf[E_ARMOR].trotyp = ((rn2(100) >= 50)
X ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
X /* rn2(100) > 50 necessary because some random number
X * generators are bad enough to seriously skew the
X * results if we use rn2(2)... --KAA
X */
X
X /*
X * Elves are people of music and song, or they are warriors.
X * Warriors get mithril coats; non-warriors MAY get an
X * instrument. We use a kludge to get only non-magic
X * instruments.
X */
X if (Elf[E_ARMOR].trotyp == ELVEN_CLOAK) {
X if (!rn2(5)) {
X static int trotyp[] = {
X WOODEN_FLUTE, TOOLED_HORN, WOODEN_HARP,
X BELL, BUGLE, LEATHER_DRUM
X };
X
X Instrument[0].trotyp = trotyp[rn2(SIZE(trotyp))];
X#ifdef DEBUG
X debugpline("Elf got instrument %d",
X Instrument[0].trotyp);
X#endif
X ini_inv(Instrument);
X }
X }
X ini_inv(Elf);
X if(!rn2(5)) ini_inv(Blindfold);
X else if(!rn2(6)) ini_inv(Lamp);
X knows_object(ELVEN_SHORT_SWORD);
X knows_object(ELVEN_ARROW);
X knows_object(ELVEN_BOW);
X knows_object(ELVEN_SPEAR);
X knows_object(ELVEN_DAGGER);
X knows_object(ELVEN_BROADSWORD);
X knows_object(ELVEN_MITHRIL_COAT);
X knows_object(ELVEN_LEATHER_HELM);
X knows_object(ELVEN_SHIELD);
X knows_object(ELVEN_BOOTS);
X knows_object(ELVEN_CLOAK);
X break;
X case 'H':
X u.umonster = PM_HEALER;
X u.ugold = u.ugold0 = rn1(1000, 1001);
X ini_inv(Healer);
X if(!rn2(25)) ini_inv(Lamp);
X break;
X case 'K':
X u.umonster = PM_KNIGHT;
X ini_inv(Knight);
X knows_class(WEAPON_CLASS);
X knows_class(ARMOR_CLASS);
X /* give knights chess-like mobility
X * -- idea from wooledge@skybridge.scl.cwru.edu */
X Jumping |= FROMOUTSIDE;
X break;
X case 'P':
X u.umonster = PM_PRIEST;
X u.uen = u.uenmax += rn2(4);
X ini_inv(Priest);
X if(!rn2(10)) ini_inv(Magicmarker);
X else if(!rn2(10)) ini_inv(Lamp);
X knows_object(POT_WATER);
X break;
X case 'R':
X u.umonster = PM_ROGUE;
X Rogue[R_DAGGERS].trquan = rn1(10, 6);
X u.ugold = u.ugold0 = 0;
X ini_inv(Rogue);
X if(!rn2(5)) ini_inv(Blindfold);
X knows_object(SACK);
X break;
X case 'S':
X u.umonster = PM_SAMURAI;
X Samurai[S_ARROWS].trquan = rn1(20, 26);
X ini_inv(Samurai);
X if(!rn2(5)) ini_inv(Blindfold);
X knows_class(WEAPON_CLASS);
X knows_class(ARMOR_CLASS);
X break;
X#ifdef TOURIST
X case 'T':
X u.umonster = PM_TOURIST;
X Tourist[T_DARTS].trquan = rn1(20, 21);
X u.ugold = u.ugold0 = rnd(1000);
X ini_inv(Tourist);
X if(!rn2(25)) ini_inv(Tinopener);
X#ifdef WALKIES
X else if(!rn2(25)) ini_inv(Leash);
X#endif
X else if(!rn2(25)) ini_inv(Towel);
X else if(!rn2(25)) ini_inv(Magicmarker);
X break;
X#endif
X case 'V':
X u.umonster = PM_VALKYRIE;
X flags.female = TRUE;
X ini_inv(Valkyrie);
X if(!rn2(6)) ini_inv(Lamp);
X knows_class(WEAPON_CLASS);
X knows_class(ARMOR_CLASS);
X break;
X case 'W':
X u.umonster = PM_WIZARD;
X u.uen = u.uenmax += rn2(4);
X ini_inv(Wizard);
X if(!rn2(5)) ini_inv(Magicmarker);
X if(!rn2(5)) ini_inv(Blindfold);
X break;
X
X default: /* impossible */
X break;
X }
X#ifdef EXPLORE_MODE
X if (discover)
X ini_inv(Wishing);
X#endif
X find_ac(); /* get initial ac value */
X init_attr(75); /* init attribute values */
X max_rank_sz(); /* set max str size for class ranks */
X/*
X * Do we really need this?
X */
X for(i = 0; i < A_MAX; i++)
X if(!rn2(20)) {
X register int xd = rn2(7) - 2; /* biased variation */
X (void) adjattrib(i, xd, TRUE);
X if (ABASE(i) < AMAX(i)) AMAX(i) = ABASE(i);
X }
X
X /* make sure you can carry all you have - especially for Tourists */
X while(inv_weight() > 0 && ACURR(A_STR) < 118)
X (void) adjattrib(A_STR, 1, TRUE);
X
X u.ualignbase[0] = u.ualignbase[1] = u.ualign.type;
X}
X
Xstatic void
Xini_inv(trop)
Xregister struct trobj *trop;
X{
X struct obj *obj;
X while(trop->trclass) {
X boolean undefined = (trop->trotyp == UNDEF_TYP);
X
X if (!undefined)
X obj = mksobj((int)trop->trotyp, TRUE, FALSE);
X else obj = mkobj(trop->trclass,FALSE);
X
X /* For random objects, do not create certain overly powerful
X * items: wand of wishing, ring of levitation, or the
X * polymorph/polymorph control combination. Specific objects,
X * i.e. the discovery wishing, are still OK.
X * Also, don't get a couple of really useless items. (Note:
X * punishment isn't "useless". Some players who start out with
X * one will immediately read it and use the iron ball as a
X * weapon.)
X */
X if (undefined) {
X#ifdef POLYSELF
X static unsigned NEARDATA nocreate = STRANGE_OBJECT;
X static unsigned NEARDATA nocreate2 = STRANGE_OBJECT;
X#endif
X static unsigned NEARDATA nocreate3 = STRANGE_OBJECT;
X
X while(obj->otyp == WAN_WISHING
X#ifdef POLYSELF
X || obj->otyp == nocreate
X || obj->otyp == nocreate2
X#endif
X || obj->otyp == nocreate3
X#ifdef ELBERETH
X || obj->otyp == RIN_LEVITATION
X#endif
X /* 'useless' items */
X || obj->otyp == POT_HALLUCINATION
X || obj->otyp == SCR_AMNESIA
X || obj->otyp == SCR_FIRE
X || obj->otyp == RIN_AGGRAVATE_MONSTER
X || obj->otyp == RIN_HUNGER
X || obj->otyp == WAN_NOTHING
X /* powerful spells are either useless to
X low level players or unbalancing */
X || (obj->oclass == SPBOOK_CLASS &&
X objects[obj->otyp].oc_level > 3)
X ) {
X dealloc_obj(obj);
X obj = mkobj(trop->trclass, FALSE);
X }
X
X /* Don't start with +0 or negative rings */
X if(objects[obj->otyp].oc_charged && obj->spe <= 0)
X obj->spe = rne(3);
X
X /* Heavily relies on the fact that 1) we create wands
X * before rings, 2) that we create rings before
X * spellbooks, and that 3) not more than 1 object of a
X * particular symbol is to be prohibited. (For more
X * objects, we need more nocreate variables...)
X */
X#ifdef POLYSELF
X switch (obj->otyp) {
X case WAN_POLYMORPH:
X case RIN_POLYMORPH:
X nocreate = RIN_POLYMORPH_CONTROL;
X break;
X case RIN_POLYMORPH_CONTROL:
X nocreate = RIN_POLYMORPH;
X nocreate2 = SPE_POLYMORPH;
X }
X#endif /* POLYSELF */
X /* Don't have 2 of the same ring */
X if (obj->oclass == RING_CLASS)
X nocreate3 = obj->otyp;
X }
X
X obj->bknown = trop->trknown;
X if(objects[obj->otyp].oc_uses_known) obj->known = trop->trknown;
X /* not obj->dknown = 1; - let him look at it at least once */
X obj->cursed = 0;
X if(obj->oclass == WEAPON_CLASS || obj->oclass == TOOL_CLASS) {
X obj->quan = (long) trop->trquan;
X trop->trquan = 1;
X }
X if(obj->oclass == FOOD_CLASS && undefined) {
X obj->known = 1;
X /* needed for tins and eggs; harmless otherwise */
X obj->bknown = 1;
X }
X /*
X * The below lines not needed because they don't correspond
X * to any actual inventory; nobody gets random tools.
X else if(obj->oclass == TOOL_CLASS && undefined) {
X obj->bknown = (obj->otyp != BAG_OF_TRICKS
X && obj->otyp != SACK
X && obj->otyp != CHEST
X && obj->otyp != LARGE_BOX
X && obj->otyp != ICE_BOX);
X }
X */
X if(trop->trspe != UNDEF_SPE)
X obj->spe = trop->trspe;
X if(trop->trbless != UNDEF_BLESS)
X obj->blessed = trop->trbless;
X
X /* defined after setting otyp+quan + blessedness */
X obj->owt = weight(obj);
X obj = addinv(obj);
X
X /* Make the type known if necessary */
X if (OBJ_DESCR(objects[obj->otyp]) && obj->known)
X makeknown(obj->otyp);
X
X if(obj->oclass == ARMOR_CLASS){
X if (is_shield(obj) && !uarms)
X setworn(obj, W_ARMS);
X else if (is_helmet(obj) && !uarmh)
X setworn(obj, W_ARMH);
X else if (is_gloves(obj) && !uarmg)
X setworn(obj, W_ARMG);
X#ifdef TOURIST
X else if (obj->otyp == HAWAIIAN_SHIRT && !uarmu)
X setworn(obj, W_ARMU);
X#endif
X else if (is_cloak(obj) && !uarmc)
X setworn(obj, W_ARMC);
X else if (is_boots(obj) && !uarmf)
X setworn(obj, W_ARMF);
X else if (!uarm)
X setworn(obj, W_ARM);
X }
X /* below changed by GAN 01/09/87 to allow wielding of
X * pick-axe or can-opener if there is no weapon
X */
X if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
X obj->otyp == TIN_OPENER)
X if(!uwep) setuwep(obj);
X#if !defined(PYRAMID_BUG) && !defined(MAC)
X if(--trop->trquan) continue; /* make a similar object */
X#else
X if(trop->trquan) { /* check if zero first */
X --trop->trquan;
X if(trop->trquan)
X continue; /* make a similar object */
X }
X#endif
X trop++;
X }
X}
X
Xvoid
Xplnamesuffix() {
X register char *p;
X if ((p = rindex(plname, '-')) != 0) {
X *p = 0;
X pl_character[0] = p[1];
X pl_character[1] = 0;
X if(!plname[0]) {
X askname();
X plnamesuffix();
X }
X }
X}
X
X/*u_init.c*/
END_OF_FILE
if test 18225 -ne `wc -c <'src/u_init.c'`; then
echo shar: \"'src/u_init.c'\" unpacked with wrong size!
fi
# end of 'src/u_init.c'
fi
if test -f 'src/worm.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/worm.c'\"
else
echo shar: Extracting \"'src/worm.c'\" \(18662 characters\)
sed "s/^X//" >'src/worm.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)worm.c 3.1 91/12/30 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "lev.h"
X
X#define newseg() (struct wseg *) alloc(sizeof(struct wseg))
X#define dealloc_seg(wseg) free((genericptr_t) (wseg))
X
X/* worm segment structure */
Xstruct wseg {
X struct wseg *nseg;
X xchar wx, wy; /* the segment's position */
X};
X
Xstatic void FDECL(toss_wsegs, (struct wseg *,BOOLEAN_P));
Xstatic void FDECL(shrink_worm, (int));
Xstatic void FDECL(random_dir, (XCHAR_P,XCHAR_P,xchar *,xchar *));
Xstatic struct wseg *FDECL(create_worm_tail, (int));
X
X/* Description of long worm implementation.
X *
X * Each monst struct of the head of a tailed worm has a wormno set to
X * 1 <= wormno < MAX_NUM_WORMS
X * If wormno == 0 this does not mean that the monster is not a worm,
X * it just means that the monster does not have a long worm tail.
X *
X * The actual segments of a worm are not full blown monst structs.
X * They are small wseg structs, and their position in the levels.monsters[][]
X * array is held by the monst struct of the head of the worm. This makes
X * things like probing and hit point bookkeeping much easier.
X *
X * The segments of the long worms on a level are kept as an array of
X * singly threaded linked lists. The wormno variable is used as an index
X * for these segment arrays.
X *
X * wtails: The first (starting struct) of a linked list. This points
X * to the tail (last) segment of the worm.
X *
X * wheads: The last (end) of a linked list of segments. This points to
X * the segment that is at the same position as the real monster
X * (the head). Note that the segment that wheads[wormno] points
X * to, is not displayed. It is simply there to keep track of
X * where the head came from, so that worm movement and display are
X * simplified later.
X * Keeping the head segment of the worm at the end of the list
X * of tail segments is an endless source of confusion, but it is
X * necessary.
X * From now on, we will use "start" and "end" to refer to the
X * linked list and "head" and "tail" to refer to the worm.
X *
X * One final worm array is:
X *
X * wgrowtime: This tells us when to add another segment to the worm.
X *
X * When a worm is moved, we add a new segment at the head, and delete the
X * segment at the tail (unless we want it to grow). This new head segment is
X * located in the same square as the actual head of the worm. If we want
X * to grow the worm, we don't delete the tail segment, and we give the worm
X * extra hit points, which possibly go into its maximum.
X *
X * Non-moving worms (worm_nomove) are assumed to be surrounded by their own
X * tail, and, thus, shrink instead of grow (as their tails keep going while
X * their heads are stopped short). In this case, we delete the last tail
X * segment, and remove hit points from the worm.
X */
X
Xstruct wseg *wheads[MAX_NUM_WORMS] = DUMMY, *wtails[MAX_NUM_WORMS] = DUMMY;
Xlong wgrowtime[MAX_NUM_WORMS] = DUMMY;
X
X/*
X * get_wormno()
X *
X * Find an unused worm tail slot and return the index. A zero means that
X * there are no slots available. This means that the worm head can exist,
X * it just cannot ever grow a tail.
X *
X * It, also, means that there is an optimisation to made. The [0] positions
X * of the arrays are never used. Meaning, we really *could* have one more
X * tailed worm on the level, or use a smaller array (using wormno - 1).
X *
X * Implementation is left to the interested hacker.
X */
Xint
Xget_wormno()
X{
X register int new_wormno = 1;
X
X while (new_wormno < MAX_NUM_WORMS) {
X if (!wheads[new_wormno])
X return new_wormno; /* found an empty wtails[] slot at new_wormno */
X new_wormno++;
X }
X
X return(0); /* level infested with worms */
X}
X
X/*
X * initworm()
X *
X * Use if (mon->wormno = get_wormno()) before calling this function!
X *
X * Initialize the worm entry. This will set up the worm grow time, and
X * create and initialize the dummy segment for wheads[] and wtails[].
X *
X * If the worm has no tail (ie get_wormno() fails) then this function need
X * not be called.
X */
Xvoid
Xinitworm(worm, wseg_count)
X struct monst *worm;
X int wseg_count;
X{
X register struct wseg *seg, *new_tail = create_worm_tail(wseg_count);
X register int wnum = worm->wormno;
X
X/* if (!wnum) return; /* bullet proofing */
X
X if (new_tail) {
X wtails[wnum] = new_tail;
X for (seg = new_tail; seg->nseg; seg = seg->nseg);
X wheads[wnum] = seg;
X } else {
X wtails[wnum] = wheads[wnum] = seg = newseg();
X seg->nseg = (struct wseg *) 0;
X seg->wx = worm->mx;
X seg->wy = worm->my;
X }
X wgrowtime[wnum] = 0L;
X}
X
X
X/*
X * toss_wsegs()
X *
X * Get rid of all worm segments on and following the given pointer curr.
X * The display may or may not need to be updated as we free the segments.
X */
Xstatic
Xvoid
Xtoss_wsegs(curr, display_update)
X register struct wseg *curr;
X register boolean display_update;
X{
X register struct wseg *seg;
X
X while (curr) {
X seg = curr->nseg;
X
X /* remove from level.monsters[][] */
X
X /* need to check curr->wx for genocided while migrating_mon */
X if (curr->wx) {
X remove_monster(curr->wx, curr->wy);
X
X /* update screen before deallocation */
X if (display_update) newsym(curr->wx,curr->wy);
X }
X
X /* free memory used by the segment */
X dealloc_seg(curr);
X curr = seg;
X }
X}
X
X
X/*
X * shrink_worm()
X *
X * Remove the tail segment of the worm (the starting segment of the list).
X */
Xstatic
Xvoid
Xshrink_worm(wnum)
X int wnum; /* worm number */
X{
X struct wseg *seg;
X
X if (wtails[wnum] == wheads[wnum]) return; /* no tail */
X
X seg = wtails[wnum];
X wtails[wnum] = seg->nseg;
X seg->nseg = (struct wseg *) 0;
X toss_wsegs(seg, TRUE);
X}
X
X/*
X * worm_move()
X *
X * Check for mon->wormno before calling this function!
X *
X * Move the worm. Maybe grow.
X */
Xvoid
Xworm_move(worm)
X struct monst *worm;
X{
X register struct wseg *seg, *new_seg; /* new segment */
X register int wnum = worm->wormno; /* worm number */
X
X
X/* if (!wnum) return; /* bullet proofing */
X
X /*
X * Place a segment at the old worm head. The head has already moved.
X */
X seg = wheads[wnum];
X place_worm_seg(worm, seg->wx, seg->wy);
X newsym(seg->wx,seg->wy); /* display the new segment */
X
X /*
X * Create a new dummy segment head and place it at the end of the list.
X */
X new_seg = newseg();
X new_seg->wx = worm->mx;
X new_seg->wy = worm->my;
X new_seg->nseg = (struct wseg *) 0;
X seg->nseg = new_seg; /* attach it to the end of the list */
X wheads[wnum] = new_seg; /* move the end pointer */
X
X
X if (wgrowtime[wnum] <= moves) {
X if (!wgrowtime[wnum])
X wgrowtime[wnum] = moves + rnd(5);
X else
X wgrowtime[wnum] += rn1(15, 3);
X worm->mhp += 3;
X if (worm->mhp > MHPMAX) worm->mhp = MHPMAX;
X if (worm->mhp > worm->mhpmax) worm->mhpmax = worm->mhp;
X } else
X /* The worm doesn't grow, so the last segment goes away. */
X shrink_worm(wnum);
X}
X
X/*
X * worm_nomove()
X *
X * Check for mon->wormno before calling this function!
X *
X * The worm don't move so it should shrink.
X */
Xvoid
Xworm_nomove(worm)
X register struct monst *worm;
X{
X shrink_worm((int) worm->wormno); /* shrink */
X
X if (worm->mhp > 3)
X worm->mhp -= 3; /* mhpmax not changed ! */
X else
X worm->mhp = 1;
X}
X
X/*
X * wormgone()
X *
X * Check for mon->wormno before calling this function!
X *
X * Kill a worm tail.
X */
Xvoid
Xwormgone(worm)
X register struct monst *worm;
X{
X register int wnum = worm->wormno;
X
X/* if (!wnum) return; /* bullet proofing */
X
X worm->wormno = 0;
X
X /* This will also remove the real monster (ie 'w') from the its
X * position in level.monsters[][].
X */
X toss_wsegs(wtails[wnum], TRUE);
X
X wheads[wnum] = wtails[wnum] = (struct wseg *) 0;
X}
X
X/*
X * wormhitu()
X *
X * Check for mon->wormno before calling this function!
X *
X * If the hero is near any part of the worm, the worm will try to attack.
X */
Xvoid
Xwormhitu(worm)
X register struct monst *worm;
X{
X register int wnum = worm->wormno;
X register struct wseg *seg;
X
X/* if (!wnum) return; /* bullet proofing */
X
X/* This does not work right now because mattacku() thinks that the head is
X * out of range of the player. We might try to kludge, and bring the head
X * within range for a tiny moment, but this needs a bit more looking at
X * before we decide to do this.
X */
X for (seg = wtails[wnum]; seg; seg = seg->nseg)
X if (distu(seg->wx, seg->wy) < 3)
X (void) mattacku(worm);
X}
X
X/* cutworm()
X *
X * Check for mon->wormno before calling this function!
X *
X * When hitting a worm (worm) at position x, y, with a weapon (weap),
X * there is a chance that the worm will be cut in half, and a chance
X * that both halves will survive.
X */
Xvoid
Xcutworm(worm, x, y, weap)
X struct monst *worm;
X xchar x,y;
X struct obj *weap;
X{
X register struct wseg *curr, *new_tail;
X register struct monst *new_worm;
X int wnum = worm->wormno;
X int cut_chance, new_wnum;
X
X/* if (!wnum) return; /* bullet proofing */
X
X if (x == worm->mx && y == worm->my) return; /* hit on head */
X
X /* cutting goes best with a bladed weapon */
X cut_chance = rnd(20); /* Normally 1-16 does not cut */
X /* Normally 17-20 does */
X
X if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */
X cut_chance += 10; /* 7-20 does */
X
X if (cut_chance < 17) return; /* not good enough */
X
X /* Find the segment that was attacked. */
X curr = wtails[wnum];
X
X while ( (curr->wx != x) || (curr->wy != y) ) {
X curr = curr->nseg;
X if (!curr) {
X impossible("cut_worm: no segment at (%d,%d)", (int) x, (int) y);
X return;
X }
X }
X
X /* If this is the tail segment, then the worm just loses it. */
X if (curr == wtails[wnum]) {
X shrink_worm(wnum);
X return;
X }
X
X /*
X * Split the worm. The tail for the new worm is the old worm's tail.
X * The tail for the old worm is the segment that follows "curr",
X * and "curr" becomes the dummy segment under the new head.
X */
X new_tail = wtails[wnum];
X wtails[wnum] = curr->nseg;
X curr->nseg = (struct wseg *) 0; /* split the worm */
X
X /*
X * At this point, the old worm is correct. Any new worm will have
X * it's head at "curr" and its tail at "new_tail".
X */
X
X /* Sometimes the tail end dies. */
X if (rn2(3) || !(new_wnum = get_wormno())) {
X You("cut part of the tail off of %s.", mon_nam(worm));
X toss_wsegs(new_tail, TRUE);
X worm->mhp /= 2;
X return;
X }
X
X /* Create the second worm. */
X new_worm = newmonst(0);
X *new_worm = *worm; /* make a copy of the old worm */
X new_worm->m_id = flags.ident++; /* make sure it has a unique id */
X new_worm->wormno = new_wnum; /* affix new worm number */
X
X if (worm->mtame)
X new_worm->mtame = (rn2(max(2 + u.uluck, 2)) ? worm->mtame : 0);
X else
X if (worm->mpeaceful)
X new_worm->mpeaceful = (rn2(max(2 + u.uluck, 2)) ? 1 : 0);
X set_malign(new_worm);
X
X new_worm->mxlth = new_worm->mnamelth = 0;
X
X /* Devalue the monster level of both halves of the worm. */
X worm->m_lev = ((unsigned)worm->m_lev <= 3) ?
X (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3);
X new_worm->m_lev = worm->m_lev;
X
X /* Calculate the mhp on the new_worm for the (lower) monster level. */
X new_worm->mhpmax = new_worm->mhp = d((int)new_worm->m_lev, 8);
X
X /* Calculate the mhp on the old worm for the (lower) monster level. */
X if (worm->m_lev > 3) {
X worm->mhpmax = d((int)worm->m_lev, 8);
X if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax;
X }
X
X /* Add new monster to mon chain. */
X new_worm->nmon = fmon;
X fmon = new_worm;
X
X /* Initialize the new worm. */
X place_monster(new_worm, x, y); /* put worm in level.monsters[][] */
X newsym(x, y); /* make sure new worm shows up */
X
X wtails[new_wnum] = new_tail; /* We've got all the info right now */
X wheads[new_wnum] = curr; /* so we can do this faster than */
X wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */
X
X /* Place the new monster at all the segment locations. */
X place_wsegs(new_worm);
X
X You("cut %s in half.", mon_nam(worm));
X}
X
X
X/*
X * see_wsegs()
X *
X * Refresh all of the segments of the given worm. This is only called
X * from see_monster() in display.c or when a monster goes minvis. It
X * is located here for modularity.
X */
Xvoid
Xsee_wsegs(worm)
X struct monst *worm;
X{
X struct wseg *curr = wtails[worm->wormno];
X
X/* if (!mtmp->wormno) return; /* bullet proofing */
X
X while (curr != wheads[worm->wormno]) {
X newsym(curr->wx,curr->wy);
X curr = curr->nseg;
X }
X}
X
X
X/*
X * save_worm()
X *
X * Save the worm information for later use. The count is the number
X * of segments, including the dummy. Called from save.c.
X */
Xvoid
Xsave_worm(fd, mode)
X int fd, mode;
X{
X int i;
X int count;
X struct wseg *curr, *temp;
X
X for (i = 1; i < MAX_NUM_WORMS; i++) {
X for (count = 0, curr = wtails[i]; curr; curr = curr->nseg) count++;
X
X /* Save number of segments */
X bwrite(fd, (genericptr_t) &count, sizeof(int));
X
X /* Save segment locations of the monster. */
X if (count) {
X for (curr = wtails[i]; curr; curr = curr->nseg) {
X bwrite(fd, (genericptr_t) &(curr->wx), sizeof(xchar));
X bwrite(fd, (genericptr_t) &(curr->wy), sizeof(xchar));
X }
X }
X }
X bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
X
X if (mode & FREE_SAVE) {
X /* Free the segments only. savemonchn() will take care of the
X * monsters. */
X for (i = 1; i < MAX_NUM_WORMS; i++) {
X if (!(curr = wtails[i])) continue;
X
X while (curr) {
X temp = curr->nseg;
X dealloc_seg(curr); /* free the segment */
X curr = temp;
X }
X wheads[i] = wtails[i] = (struct wseg *) 0;
X }
X }
X
X}
X
X/*
X * rest_worm()
X *
X * Restore the worm information from the save file. Called from restore.c
X */
Xvoid
Xrest_worm(fd)
X int fd;
X{
X int i, j, count;
X struct wseg *curr, *temp;
X
X for (i = 1; i < MAX_NUM_WORMS; i++) {
X mread(fd, (genericptr_t) &count, sizeof(int));
X if (!count) continue; /* none */
X
X /* Get the segments. */
X for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
X temp = newseg();
X temp->nseg = (struct wseg *) 0;
X mread(fd, (genericptr_t) &(temp->wx), sizeof(xchar));
X mread(fd, (genericptr_t) &(temp->wy), sizeof(xchar));
X if (curr)
X curr->nseg = temp;
X else
X wtails[i] = temp;
X curr = temp;
X }
X wheads[i] = curr;
X }
X mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
X}
X
X/*
X * place_wsegs()
X *
X * Place the segments of the given worm. Called from restore.c
X */
Xvoid
Xplace_wsegs(worm)
X struct monst *worm;
X{
X struct wseg *curr = wtails[worm->wormno];
X
X/* if (!mtmp->wormno) return; /* bullet proofing */
X
X while (curr != wheads[worm->wormno]) {
X place_worm_seg(worm,curr->wx,curr->wy);
X curr = curr->nseg;
X }
X}
X
X/*
X * remove_worm()
X *
X * This function is equivalent to the remove_monster #define in
X * rm.h, only it will take the worm *and* tail out of the levels array.
X * It does not get rid of (dealloc) the worm tail structures, and it does
X * not remove the mon from the fmon chain.
X */
Xvoid
Xremove_worm(worm)
X register struct monst *worm;
X{
X register struct wseg *curr = wtails[worm->wormno];
X
X/* if (!mtmp->wormno) return; /* bullet proofing */
X
X while (curr) {
X remove_monster(curr->wx, curr->wy);
X newsym(curr->wx, curr->wy);
X curr = curr->nseg;
X }
X}
X
X/*
X * place_worm_tail_randomly()
X *
X * Place a worm tail somewhere on a level behind the head.
X * This routine essentially reverses the order of the wsegs from head
X * to tail while placing them.
X * x, and y are most likely the worm->mx, and worm->my, but don't *need* to
X * be, if somehow the head is disjoint from the tail.
X */
Xvoid
Xplace_worm_tail_randomly(worm, x, y)
X struct monst *worm;
X xchar x, y;
X{
X int wnum = worm->wormno;
X struct wseg *curr = wtails[wnum];
X struct wseg *new_tail;
X register xchar ox = x, oy = y;
X
X/* if (!wnum) return; /* bullet proofing */
X
X if (wnum && (!wtails[wnum] || !wheads[wnum]) ) {
X impossible("place_worm_tail_randomly: wormno is set without a tail!");
X return;
X }
X
X wheads[wnum] = new_tail = curr;
X curr = curr->nseg;
X new_tail->nseg = (struct wseg *) 0;
X new_tail->wx = x;
X new_tail->wy = y;
X
X while(curr) {
X xchar nx, ny;
X char tryct = 0;
X
X /* pick a random direction from x, y and search for goodpos() */
X
X do {
X random_dir(ox, oy, &nx, &ny);
X } while (!goodpos(nx, ny, worm, worm->data) && (tryct++ < 50));
X
X if (tryct < 50) {
X place_worm_seg(worm, nx, ny);
X curr->wx = ox = nx;
X curr->wy = oy = ny;
X wtails[wnum] = curr;
X curr = curr->nseg;
X wtails[wnum]->nseg = new_tail;
X new_tail = wtails[wnum];
X newsym(nx, ny);
X } else { /* Oops. Truncate because there was */
X toss_wsegs(curr, FALSE); /* no place for the rest of it */
X curr = (struct wseg *) 0;
X }
X }
X}
X
X/*
X * Given a coordinate x, y.
X * return in *nx, *ny, the coordinates of one of the <= 8 squares adjoining.
X *
X * This function, and the loop it serves, could be eliminated by coding
X * enexto() with a search radius.
X */
Xstatic
Xvoid
Xrandom_dir(x, y, nx, ny)
X register xchar x, y;
X register xchar *nx, *ny;
X{
X *nx = x;
X *ny = y;
X
X *nx += (x > 1 ? /* extreme left ? */
X (x < COLNO ? /* extreme right ? */
X (rn2(3) - 1) /* neither so +1, 0, or -1 */
X : -rn2(2)) /* 0, or -1 */
X : rn2(2)); /* 0, or 1 */
X
X *ny += (*nx == x ? /* same kind of thing with y */
X (y > 1 ?
X (y < ROWNO ?
X (rn2(2) ?
X 1
X : -1)
X : -1)
X : 1)
X : (y > 1 ?
X (y < ROWNO ?
X (rn2(3) - 1)
X : -rn2(2))
X : rn2(2)));
X}
X
X/* count_wsegs()
X *
X * returns
X * the number of visible segments that a worm has.
X */
X
Xint
Xcount_wsegs(mtmp)
X struct monst *mtmp;
X{
X register int i=0;
X register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
X
X/* if (!mtmp->wormno) return 0; /* bullet proofing */
X
X while (curr) {
X i++;
X curr = curr->nseg;
X }
X
X return i;
X}
X
X/* create_worm_tail()
X *
X * will create a worm tail chain of (num_segs + 1) and return a pointer to it.
X */
Xstatic
Xstruct wseg *
Xcreate_worm_tail(num_segs)
X int num_segs;
X{
X register int i=0;
X register struct wseg *new_tail, *curr;
X
X if (!num_segs) return (struct wseg *)0;
X
X new_tail = curr = newseg();
X curr->nseg = (struct wseg *)0;
X curr->wx = 0;
X curr->wy = 0;
X
X while (i < num_segs) {
X curr->nseg = newseg();
X curr = curr->nseg;
X curr->nseg = (struct wseg *)0;
X curr->wx = 0;
X curr->wy = 0;
X i++;
X }
X
X return (new_tail);
X}
X
X/*worm.c*/
END_OF_FILE
if test 18662 -ne `wc -c <'src/worm.c'`; then
echo shar: \"'src/worm.c'\" unpacked with wrong size!
fi
# end of 'src/worm.c'
fi
echo shar: End of archive 82 \(of 108\).
cp /dev/null ark82isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0