home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume14
/
umoria4
/
part14
< prev
next >
Wrap
Internet Message Format
|
1992-08-31
|
57KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v14i046: umoria4 - single player dungeon simulation (ver. 5.5), Part14/39
Message-ID: <3404@master.CNA.TEK.COM>
Date: 20 Aug 92 18:04:40 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2327
Approved: billr@saab.CNA.TEK.COM
Submitted-by: grabiner@math.harvard.edu (David Grabiner)
Posting-number: Volume 14, Issue 46
Archive-name: umoria4/Part14
Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
#! /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 14 (of 39)."
# Contents: source/generate.c source/recall.c
# Wrapped by billr@saab on Thu Aug 20 09:11:29 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'source/generate.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/generate.c'\"
else
echo shar: Extracting \"'source/generate.c'\" \(35484 characters\)
sed "s/^X//" >'source/generate.c' <<'END_OF_FILE'
X/* source/generate.c: initialize/create a dungeon or town level
X
X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X#include "externs.h"
X
X#if defined(USG) && !defined(VMS) && !defined(MAC)
X#if !defined(ATARIST_MWC) && !defined(AMIGA)
X#if !defined(__TURBOC__)
X#include <memory.h>
X#else
X#ifndef ATARIST_TC
X#include <mem.h>
X#endif
X#endif
X#endif
X#endif
X
X#if defined(MAC)
X#include <string.h>
X#endif
X
X#ifdef ATARIST_TC
X#include <string.h>
X#endif
X
Xtypedef struct coords {
X int x, y;
X} coords;
X
X#if defined(LINT_ARGS)
Xstatic void correct_dir(int *, int * , int, int, int, int);
Xstatic void rand_dir(int *,int *);
Xstatic void blank_cave(void);
Xstatic void fill_cave(int);
Xstatic void place_boundary(void);
Xstatic void place_streamer(int, int);
Xstatic void place_open_door(int, int);
Xstatic void place_broken_door(int, int);
Xstatic void place_closed_door(int, int);
Xstatic void place_locked_door(int, int);
Xstatic void place_stuck_door(int, int);
Xstatic void place_secret_door(int, int);
Xstatic void place_door(int, int);
Xstatic void place_up_stairs(int, int);
Xstatic void place_down_stairs(int, int);
Xstatic void place_stairs(int, int, int);
Xstatic void vault_trap(int, int, int, int, int);
Xstatic void vault_monster(int, int, int);
Xstatic void build_room(int, int);
Xstatic void build_type1(int, int);
Xstatic void build_type2(int, int);
Xstatic void build_type3(int, int);
Xstatic void build_tunnel(int, int, int, int);
Xstatic int next_to(int, int);
Xstatic void try_door(int, int);
Xstatic void new_spot(int16 *, int16 *);
Xstatic void cave_gen(void);
Xstatic void build_store(int, int, int);
Xstatic void tlink(void);
Xstatic void mlink(void);
Xstatic void town_gen(void);
X#endif
X
Xstatic coords doorstk[100];
Xstatic int doorindex;
X
X
X/* Always picks a correct direction */
Xstatic void correct_dir(rdir, cdir, y1, x1, y2, x2)
Xint *rdir, *cdir;
Xregister int y1, x1, y2, x2;
X{
X if (y1 < y2)
X *rdir = 1;
X else if (y1 == y2)
X *rdir = 0;
X else
X *rdir = -1;
X if (x1 < x2)
X *cdir = 1;
X else if (x1 == x2)
X *cdir = 0;
X else
X *cdir = -1;
X if ((*rdir != 0) && (*cdir != 0))
X {
X if (randint (2) == 1)
X *rdir = 0;
X else
X *cdir = 0;
X }
X}
X
X
X/* Chance of wandering direction */
Xstatic void rand_dir(rdir, cdir)
Xint *rdir, *cdir;
X{
X register int tmp;
X
X tmp = randint(4);
X if (tmp < 3)
X {
X *cdir = 0;
X *rdir = -3 + (tmp << 1); /* tmp=1 -> *rdir=-1; tmp=2 -> *rdir=1 */
X }
X else
X {
X *rdir = 0;
X *cdir = -7 + (tmp << 1); /* tmp=3 -> *cdir=-1; tmp=4 -> *cdir=1 */
X }
X}
X
X
X/* Blanks out entire cave -RAK- */
Xstatic void blank_cave()
X{
X#ifndef USG
X bzero ((char *)&cave[0][0], sizeof (cave));
X#else
X#ifdef MAC
X /* On the mac, cave is a pointer, so sizeof(cave) = 4! */
X (void)memset((char *)&cave[0][0], 0,
X (long) sizeof(cave_type) * MAX_HEIGHT * MAX_WIDTH);
X#else
X (void)memset((char *)&cave[0][0], 0, sizeof (cave));
X#endif
X#endif
X}
X
X
X/* Fills in empty spots with desired rock -RAK- */
X/* Note: 9 is a temporary value. */
Xstatic void fill_cave(fval)
Xregister int fval;
X{
X register int i, j;
X register cave_type *c_ptr;
X
X /* no need to check the border of the cave */
X
X for (i = cur_height - 2; i > 0; i--)
X {
X c_ptr = &cave[i][1];
X for (j = cur_width - 2; j > 0; j--)
X {
X if ((c_ptr->fval == NULL_WALL) || (c_ptr->fval == TMP1_WALL) ||
X (c_ptr->fval == TMP2_WALL))
X c_ptr->fval = fval;
X c_ptr++;
X }
X }
X}
X
X#ifdef DEBUG
X#include <assert.h>
X#endif
X
X/* Places indestructible rock around edges of dungeon -RAK- */
Xstatic void place_boundary()
X{
X register int i;
X register cave_type *top_ptr, *bottom_ptr;
X cave_type (*left_ptr)[MAX_WIDTH];
X cave_type (*right_ptr)[MAX_WIDTH];
X
X /* put permanent wall on leftmost row and rightmost row */
X left_ptr = (cave_type (*)[MAX_WIDTH]) &cave[0][0];
X right_ptr = (cave_type (*)[MAX_WIDTH]) &cave[0][cur_width - 1];
X
X for (i = 0; i < cur_height; i++)
X {
X#ifdef DEBUG
X assert ((cave_type *)left_ptr == &cave[i][0]);
X assert ((cave_type *)right_ptr == &cave[i][cur_width-1]);
X#endif
X
X ((cave_type *)left_ptr)->fval = BOUNDARY_WALL;
X left_ptr++;
X ((cave_type *)right_ptr)->fval = BOUNDARY_WALL;
X right_ptr++;
X }
X
X /* put permanent wall on top row and bottom row */
X top_ptr = &cave[0][0];
X bottom_ptr = &cave[cur_height - 1][0];
X
X for (i = 0; i < cur_width; i++)
X {
X#ifdef DEBUG
X assert (top_ptr == &cave[0][i]);
X assert (bottom_ptr == &cave[cur_height - 1][i]);
X#endif
X
X top_ptr->fval = BOUNDARY_WALL;
X top_ptr++;
X bottom_ptr->fval = BOUNDARY_WALL;
X bottom_ptr++;
X }
X}
X
X
X/* Places "streamers" of rock through dungeon -RAK- */
Xstatic void place_streamer(fval, treas_chance)
Xint fval;
Xint treas_chance;
X{
X register int i, tx, ty;
X int y, x, t1, t2, dir;
X register cave_type *c_ptr;
X
X /* Choose starting point and direction */
X y = (cur_height / 2) + 11 - randint(23);
X x = (cur_width / 2) + 16 - randint(33);
X
X dir = randint(8); /* Number 1-4, 6-9 */
X if (dir > 4)
X dir = dir + 1;
X
X /* Place streamer into dungeon */
X t1 = 2*DUN_STR_RNG + 1; /* Constants */
X t2 = DUN_STR_RNG + 1;
X do
X {
X for (i = 0; i < DUN_STR_DEN; i++)
X {
X ty = y + randint(t1) - t2;
X tx = x + randint(t1) - t2;
X if (in_bounds(ty, tx))
X {
X c_ptr = &cave[ty][tx];
X if (c_ptr->fval == GRANITE_WALL)
X {
X c_ptr->fval = fval;
X if (randint(treas_chance) == 1)
X place_gold(ty, tx);
X }
X }
X }
X }
X while (mmove(dir, &y, &x));
X}
X
X
Xstatic void place_open_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR);
X cave_ptr->fval = CORR_FLOOR;
X}
X
X
Xstatic void place_broken_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR);
X cave_ptr->fval = CORR_FLOOR;
X t_list[cur_pos].p1 = 1;
X}
X
X
Xstatic void place_closed_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
X cave_ptr->fval = BLOCKED_FLOOR;
X}
X
X
Xstatic void place_locked_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
X cave_ptr->fval = BLOCKED_FLOOR;
X t_list[cur_pos].p1 = randint(10) + 10;
X}
X
X
Xstatic void place_stuck_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR);
X cave_ptr->fval = BLOCKED_FLOOR;
X t_list[cur_pos].p1 = -randint(10) - 10;
X}
X
X
Xstatic void place_secret_door(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cur_pos = popt();
X cave_ptr = &cave[y][x];
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_SECRET_DOOR);
X cave_ptr->fval = BLOCKED_FLOOR;
X}
X
X
Xstatic void place_door(y, x)
Xint y, x;
X{
X register int tmp;
X
X tmp = randint(3);
X if (tmp == 1)
X {
X if (randint(4) == 1)
X place_broken_door(y, x);
X else
X place_open_door(y, x);
X }
X else if (tmp == 2)
X {
X tmp = randint(12);
X if (tmp > 3)
X place_closed_door(y, x);
X else if (tmp == 3)
X place_stuck_door(y, x);
X else
X place_locked_door(y, x);
X }
X else
X place_secret_door(y, x);
X}
X
X
X/* Place an up staircase at given y, x -RAK- */
Xstatic void place_up_stairs(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cave_ptr = &cave[y][x];
X if (cave_ptr->tptr != 0)
X (void) delete_object(y, x);
X cur_pos = popt();
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_UP_STAIR);
X}
X
X
X/* Place a down staircase at given y, x -RAK- */
Xstatic void place_down_stairs(y, x)
Xint y, x;
X{
X register int cur_pos;
X register cave_type *cave_ptr;
X
X cave_ptr = &cave[y][x];
X if (cave_ptr->tptr != 0)
X (void) delete_object(y, x);
X cur_pos = popt();
X cave_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR);
X}
X
X
X/* Places a staircase 1=up, 2=down -RAK- */
Xstatic void place_stairs(typ, num, walls)
Xint typ, num, walls;
X{
X register cave_type *cave_ptr;
X int i, j, flag;
X register int y1, x1, y2, x2;
X
X for (i = 0; i < num; i++)
X {
X flag = FALSE;
X do
X {
X j = 0;
X do
X {
X /* Note: don't let y1/x1 be zero, and don't let y2/x2 be equal
X to cur_height-1/cur_width-1, these values are always
X BOUNDARY_ROCK. */
X y1 = randint(cur_height - 14);
X x1 = randint(cur_width - 14);
X y2 = y1 + 12;
X x2 = x1 + 12;
X do
X {
X do
X {
X cave_ptr = &cave[y1][x1];
X if (cave_ptr->fval <= MAX_OPEN_SPACE
X && (cave_ptr->tptr == 0)
X && (next_to_walls(y1, x1) >= walls))
X {
X flag = TRUE;
X if (typ == 1)
X place_up_stairs(y1, x1);
X else
X place_down_stairs(y1, x1);
X }
X x1++;
X }
X while ((x1 != x2) && (!flag));
X x1 = x2 - 12;
X y1++;
X }
X while ((y1 != y2) && (!flag));
X j++;
X }
X while ((!flag) && (j <= 30));
X walls--;
X }
X while (!flag);
X }
X}
X
X
X/* Place a trap with a given displacement of point -RAK- */
Xstatic void vault_trap(y, x, yd, xd, num)
Xint y, x, yd, xd, num;
X{
X register int count, y1, x1;
X int i, flag;
X register cave_type *c_ptr;
X
X for (i = 0; i < num; i++)
X {
X flag = FALSE;
X count = 0;
X do
X {
X y1 = y - yd - 1 + randint(2*yd+1);
X x1 = x - xd - 1 + randint(2*xd+1);
X c_ptr = &cave[y1][x1];
X if ((c_ptr->fval != NULL_WALL) && (c_ptr->fval <= MAX_CAVE_FLOOR)
X && (c_ptr->tptr == 0))
X {
X place_trap(y1, x1, randint(MAX_TRAP)-1);
X flag = TRUE;
X }
X count++;
X }
X while ((!flag) && (count <= 5));
X }
X}
X
X
X/* Place a trap with a given displacement of point -RAK- */
Xstatic void vault_monster(y, x, num)
Xint y, x, num;
X{
X register int i;
X int y1, x1;
X
X for (i = 0; i < num; i++)
X {
X y1 = y;
X x1 = x;
X (void) summon_monster(&y1, &x1, TRUE);
X }
X}
X
X
X/* Builds a room at a row, column coordinate -RAK- */
Xstatic void build_room(yval, xval)
Xint yval, xval;
X{
X register int i, j, y_depth, x_right;
X int y_height, x_left;
X int8u floor;
X register cave_type *c_ptr, *d_ptr;
X
X if (dun_level <= randint(25))
X floor = LIGHT_FLOOR; /* Floor with light */
X else
X floor = DARK_FLOOR; /* Dark floor */
X
X y_height = yval - randint(4);
X y_depth = yval + randint(3);
X x_left = xval - randint(11);
X x_right = xval + randint(11);
X
X /* the x dim of rooms tends to be much larger than the y dim, so don't
X bother rewriting the y loop */
X
X for (i = y_height; i <= y_depth; i++)
X {
X c_ptr = &cave[i][x_left];
X for (j = x_left; j <= x_right; j++)
X {
X c_ptr->fval = floor;
X c_ptr->lr = TRUE;
X c_ptr++;
X }
X }
X
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X c_ptr = &cave[i][x_left-1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr = &cave[i][x_right+1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X
X c_ptr = &cave[y_height - 1][x_left];
X d_ptr = &cave[y_depth + 1][x_left];
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr++;
X d_ptr->fval = GRANITE_WALL;
X d_ptr->lr = TRUE;
X d_ptr++;
X }
X}
X
X
X/* Builds a room at a row, column coordinate -RAK- */
X/* Type 1 unusual rooms are several overlapping rectangular ones */
Xstatic void build_type1(yval, xval)
Xint yval, xval;
X{
X int y_height, y_depth;
X int x_left, x_right, limit;
X register int i0, i, j;
X int8u floor;
X register cave_type *c_ptr, *d_ptr;
X
X if (dun_level <= randint(25))
X floor = LIGHT_FLOOR; /* Floor with light */
X else
X floor = DARK_FLOOR; /* Dark floor */
X limit = 1 + randint(2);
X for (i0 = 0; i0 < limit; i0++)
X {
X y_height = yval - randint(4);
X y_depth = yval + randint(3);
X x_left = xval - randint(11);
X x_right = xval + randint(11);
X
X /* the x dim of rooms tends to be much larger than the y dim, so don't
X bother rewriting the y loop */
X
X for (i = y_height; i <= y_depth; i++)
X {
X c_ptr = &cave[i][x_left];
X for (j = x_left; j <= x_right; j++)
X {
X c_ptr->fval = floor;
X c_ptr->lr = TRUE;
X c_ptr++;
X }
X }
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X c_ptr = &cave[i][x_left-1];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X c_ptr = &cave[i][x_right+1];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X }
X c_ptr = &cave[y_height - 1][x_left];
X d_ptr = &cave[y_depth + 1][x_left];
X for (i = x_left; i <= x_right; i++)
X {
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X c_ptr++;
X if (d_ptr->fval != floor)
X {
X d_ptr->fval = GRANITE_WALL;
X d_ptr->lr = TRUE;
X }
X d_ptr++;
X }
X }
X}
X
X
X/* Builds an unusual room at a row, column coordinate -RAK- */
X/* Type 2 unusual rooms all have an inner room: */
X/* 1 - Just an inner room with one door */
X/* 2 - An inner room within an inner room */
X/* 3 - An inner room with pillar(s) */
X/* 4 - Inner room has a maze */
X/* 5 - A set of four inner rooms */
Xstatic void build_type2(yval, xval)
Xint yval, xval;
X{
X register int i, j, y_height, x_left;
X int y_depth, x_right, tmp;
X int8u floor;
X register cave_type *c_ptr, *d_ptr;
X
X if (dun_level <= randint(25))
X floor = LIGHT_FLOOR; /* Floor with light */
X else
X floor = DARK_FLOOR; /* Dark floor */
X y_height = yval - 4;
X y_depth = yval + 4;
X x_left = xval - 11;
X x_right = xval + 11;
X
X /* the x dim of rooms tends to be much larger than the y dim, so don't
X bother rewriting the y loop */
X
X for (i = y_height; i <= y_depth; i++)
X {
X c_ptr = &cave[i][x_left];
X for (j = x_left; j <= x_right; j++)
X {
X c_ptr->fval = floor;
X c_ptr->lr = TRUE;
X c_ptr++;
X }
X }
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X c_ptr = &cave[i][x_left-1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr = &cave[i][x_right+1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X c_ptr = &cave[y_height - 1][x_left];
X d_ptr = &cave[y_depth + 1][x_left];
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr++;
X d_ptr->fval = GRANITE_WALL;
X d_ptr->lr = TRUE;
X d_ptr++;
X }
X /* The inner room */
X y_height = y_height + 2;
X y_depth = y_depth - 2;
X x_left = x_left + 2;
X x_right = x_right - 2;
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X cave[i][x_left-1].fval = TMP1_WALL;
X cave[i][x_right+1].fval = TMP1_WALL;
X }
X c_ptr = &cave[y_height-1][x_left];
X d_ptr = &cave[y_depth+1][x_left];
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X d_ptr->fval = TMP1_WALL;
X d_ptr++;
X }
X /* Inner room variations */
X switch(randint(5))
X {
X case 1: /* Just an inner room. */
X tmp = randint(4);
X if (tmp < 3) { /* Place a door */
X if (tmp == 1) place_secret_door(y_height-1, xval);
X else place_secret_door(y_depth+1, xval);
X } else {
X if (tmp == 3) place_secret_door(yval, x_left-1);
X else place_secret_door(yval, x_right+1);
X }
X vault_monster(yval, xval, 1);
X break;
X
X case 2: /* Treasure Vault */
X tmp = randint(4);
X if (tmp < 3) { /* Place a door */
X if (tmp == 1) place_secret_door(y_height-1, xval);
X else place_secret_door(y_depth+1, xval);
X } else {
X if (tmp == 3) place_secret_door(yval, x_left-1);
X else place_secret_door(yval, x_right+1);
X }
X
X for (i = yval-1; i <= yval+1; i++)
X {
X cave[i][xval-1].fval = TMP1_WALL;
X cave[i][xval+1].fval = TMP1_WALL;
X }
X cave[yval-1][xval].fval = TMP1_WALL;
X cave[yval+1][xval].fval = TMP1_WALL;
X
X tmp = randint(4); /* Place a door */
X if (tmp < 3)
X place_locked_door(yval-3+(tmp<<1), xval); /* 1 -> yval-1; 2 -> yval+1*/
X else
X place_locked_door(yval, xval-7+(tmp<<1));
X
X /* Place an object in the treasure vault */
X tmp = randint(10);
X if (tmp > 2)
X place_object(yval, xval);
X else if (tmp == 2)
X place_down_stairs(yval, xval);
X else
X place_up_stairs(yval, xval);
X
X /* Guard the treasure well */
X vault_monster(yval, xval, 2+randint(3));
X /* If the monsters don't get 'em. */
X vault_trap(yval, xval, 4, 10, 2+randint(3));
X break;
X
X case 3: /* Inner pillar(s). */
X tmp = randint(4);
X if (tmp < 3) { /* Place a door */
X if (tmp == 1) place_secret_door(y_height-1, xval);
X else place_secret_door(y_depth+1, xval);
X } else {
X if (tmp == 3) place_secret_door(yval, x_left-1);
X else place_secret_door(yval, x_right+1);
X }
X
X for (i = yval-1; i <= yval+1; i++)
X {
X c_ptr = &cave[i][xval-1];
X for (j = xval-1; j <= xval+1; j++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X }
X }
X if (randint(2) == 1)
X {
X tmp = randint(2);
X for (i = yval-1; i <= yval+1; i++)
X {
X c_ptr = &cave[i][xval-5-tmp];
X for (j = xval-5-tmp; j <= xval-3-tmp; j++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X }
X }
X for (i = yval-1; i <= yval+1; i++)
X {
X c_ptr = &cave[i][xval+3+tmp];
X for (j = xval+3+tmp; j <= xval+5+tmp; j++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X }
X }
X }
X
X if (randint(3) == 1) /* Inner rooms */
X {
X c_ptr = &cave[yval-1][xval-5];
X d_ptr = &cave[yval+1][xval-5];
X for (i = xval-5; i <= xval+5; i++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X d_ptr->fval = TMP1_WALL;
X d_ptr++;
X }
X cave[yval][xval-5].fval = TMP1_WALL;
X cave[yval][xval+5].fval = TMP1_WALL;
X place_secret_door(yval-3+(randint(2)<<1), xval-3);
X place_secret_door(yval-3+(randint(2)<<1), xval+3);
X if (randint(3) == 1) place_object(yval, xval-2);
X if (randint(3) == 1) place_object(yval, xval+2);
X vault_monster(yval, xval-2, randint(2));
X vault_monster(yval, xval+2, randint(2));
X }
X break;
X
X case 4: /* Maze inside. */
X tmp = randint(4);
X if (tmp < 3) { /* Place a door */
X if (tmp == 1) place_secret_door(y_height-1, xval);
X else place_secret_door(y_depth+1, xval);
X } else {
X if (tmp == 3) place_secret_door(yval, x_left-1);
X else place_secret_door(yval, x_right+1);
X }
X
X for (i = y_height; i <= y_depth; i++)
X for (j = x_left; j <= x_right; j++)
X if (0x1 & (j+i))
X cave[i][j].fval = TMP1_WALL;
X
X /* Monsters just love mazes. */
X vault_monster(yval, xval-5, randint(3));
X vault_monster(yval, xval+5, randint(3));
X /* Traps make them entertaining. */
X vault_trap(yval, xval-3, 2, 8, randint(3));
X vault_trap(yval, xval+3, 2, 8, randint(3));
X /* Mazes should have some treasure too.. */
X for (i = 0; i < 3; i++)
X random_object(yval, xval, 1);
X break;
X
X case 5: /* Four small rooms. */
X for (i = y_height; i <= y_depth; i++)
X cave[i][xval].fval = TMP1_WALL;
X
X c_ptr = &cave[yval][x_left];
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X }
X
X if (randint(2) == 1)
X {
X i = randint(10);
X place_secret_door(y_height-1, xval-i);
X place_secret_door(y_height-1, xval+i);
X place_secret_door(y_depth+1, xval-i);
X place_secret_door(y_depth+1, xval+i);
X }
X else
X {
X i = randint(3);
X place_secret_door(yval+i, x_left-1);
X place_secret_door(yval-i, x_left-1);
X place_secret_door(yval+i, x_right+1);
X place_secret_door(yval-i, x_right+1);
X }
X
X /* Treasure in each one. */
X random_object(yval, xval, 2+randint(2));
X /* Gotta have some monsters. */
X vault_monster(yval+2, xval-4, randint(2));
X vault_monster(yval+2, xval+4, randint(2));
X vault_monster(yval-2, xval-4, randint(2));
X vault_monster(yval-2, xval+4, randint(2));
X break;
X }
X}
X
X
X/* Builds a room at a row, column coordinate -RAK- */
X/* Type 3 unusual rooms are cross shaped */
Xstatic void build_type3(yval, xval)
Xint yval, xval;
X{
X int y_height, y_depth;
X int x_left, x_right;
X register int tmp, i, j;
X int8u floor;
X register cave_type *c_ptr;
X
X if (dun_level <= randint(25))
X floor = LIGHT_FLOOR; /* Floor with light */
X else
X floor = DARK_FLOOR; /* Dark floor */
X tmp = 2 + randint(2);
X y_height = yval - tmp;
X y_depth = yval + tmp;
X x_left = xval - 1;
X x_right = xval + 1;
X for (i = y_height; i <= y_depth; i++)
X for (j = x_left; j <= x_right; j++)
X {
X c_ptr = &cave[i][j];
X c_ptr->fval = floor;
X c_ptr->lr = TRUE;
X }
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X c_ptr = &cave[i][x_left-1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr = &cave[i][x_right+1];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr = &cave[y_height-1][i];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X c_ptr = &cave[y_depth+1][i];
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X tmp = 2 + randint(9);
X y_height = yval - 1;
X y_depth = yval + 1;
X x_left = xval - tmp;
X x_right = xval + tmp;
X for (i = y_height; i <= y_depth; i++)
X for (j = x_left; j <= x_right; j++)
X {
X c_ptr = &cave[i][j];
X c_ptr->fval = floor;
X c_ptr->lr = TRUE;
X }
X for (i = (y_height - 1); i <= (y_depth + 1); i++)
X {
X c_ptr = &cave[i][x_left-1];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X c_ptr = &cave[i][x_right+1];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X }
X for (i = x_left; i <= x_right; i++)
X {
X c_ptr = &cave[y_height-1][i];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X c_ptr = &cave[y_depth+1][i];
X if (c_ptr->fval != floor)
X {
X c_ptr->fval = GRANITE_WALL;
X c_ptr->lr = TRUE;
X }
X }
X /* Special features. */
X switch(randint(4))
X {
X case 1: /* Large middle pillar */
X for (i = yval-1; i <= yval+1; i++)
X {
X c_ptr = &cave[i][xval-1];
X for (j = xval-1; j <= xval+1; j++)
X {
X c_ptr->fval = TMP1_WALL;
X c_ptr++;
X }
X }
X break;
X
X case 2: /* Inner treasure vault */
X for (i = yval-1; i <= yval+1; i++)
X {
X cave[i][xval-1].fval = TMP1_WALL;
X cave[i][xval+1].fval = TMP1_WALL;
X }
X cave[yval-1][xval].fval = TMP1_WALL;
X cave[yval+1][xval].fval = TMP1_WALL;
X
X tmp = randint(4); /* Place a door */
X if (tmp < 3)
X place_secret_door(yval-3+(tmp<<1), xval);
X else
X place_secret_door(yval, xval-7+(tmp<<1));
X
X /* Place a treasure in the vault */
X place_object(yval, xval);
X /* Let's guard the treasure well. */
X vault_monster(yval, xval, 2+randint(2));
X /* Traps naturally */
X vault_trap(yval, xval, 4, 4, 1+randint(3));
X break;
X
X case 3:
X if (randint(3) == 1)
X {
X cave[yval-1][xval-2].fval = TMP1_WALL;
X cave[yval+1][xval-2].fval = TMP1_WALL;
X cave[yval-1][xval+2].fval = TMP1_WALL;
X cave[yval+1][xval+2].fval = TMP1_WALL;
X cave[yval-2][xval-1].fval = TMP1_WALL;
X cave[yval-2][xval+1].fval = TMP1_WALL;
X cave[yval+2][xval-1].fval = TMP1_WALL;
X cave[yval+2][xval+1].fval = TMP1_WALL;
X if (randint(3) == 1)
X {
X place_secret_door(yval, xval-2);
X place_secret_door(yval, xval+2);
X place_secret_door(yval-2, xval);
X place_secret_door(yval+2, xval);
X }
X }
X else if (randint(3) == 1)
X {
X cave[yval][xval].fval = TMP1_WALL;
X cave[yval-1][xval].fval = TMP1_WALL;
X cave[yval+1][xval].fval = TMP1_WALL;
X cave[yval][xval-1].fval = TMP1_WALL;
X cave[yval][xval+1].fval = TMP1_WALL;
X }
X else if (randint(3) == 1)
X cave[yval][xval].fval = TMP1_WALL;
X break;
X
X case 4:
X break;
X }
X}
X
X
X/* Constructs a tunnel between two points */
Xstatic void build_tunnel(row1, col1, row2, col2)
Xint row1, col1, row2, col2;
X{
X register int tmp_row, tmp_col, i, j;
X register cave_type *c_ptr;
X cave_type *d_ptr;
X coords tunstk[1000], wallstk[1000];
X coords *tun_ptr;
X int row_dir, col_dir, tunindex, wallindex;
X int stop_flag, door_flag, main_loop_count;
X int start_row, start_col;
X
X /* Main procedure for Tunnel */
X /* Note: 9 is a temporary value */
X stop_flag = FALSE;
X door_flag = FALSE;
X tunindex = 0;
X wallindex = 0;
X main_loop_count = 0;
X start_row = row1;
X start_col = col1;
X correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
X
X do
X {
X /* prevent infinite loops, just in case */
X main_loop_count++;
X if (main_loop_count > 2000)
X stop_flag = TRUE;
X
X if (randint(100) > DUN_TUN_CHG)
X {
X if (randint(DUN_TUN_RND) == 1)
X rand_dir(&row_dir, &col_dir);
X else
X correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
X }
X tmp_row = row1 + row_dir;
X tmp_col = col1 + col_dir;
X while (!in_bounds(tmp_row, tmp_col))
X {
X if (randint(DUN_TUN_RND) == 1)
X rand_dir(&row_dir, &col_dir);
X else
X correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
X tmp_row = row1 + row_dir;
X tmp_col = col1 + col_dir;
X }
X c_ptr = &cave[tmp_row][tmp_col];
X if (c_ptr->fval == NULL_WALL)
X {
X row1 = tmp_row;
X col1 = tmp_col;
X if (tunindex < 1000)
X {
X tunstk[tunindex].y = row1;
X tunstk[tunindex].x = col1;
X tunindex++;
X }
X door_flag = FALSE;
X }
X else if (c_ptr->fval == TMP2_WALL)
X /* do nothing */
X ;
X else if (c_ptr->fval == GRANITE_WALL)
X {
X row1 = tmp_row;
X col1 = tmp_col;
X if (wallindex < 1000)
X {
X wallstk[wallindex].y = row1;
X wallstk[wallindex].x = col1;
X wallindex++;
X }
X for (i = row1-1; i <= row1+1; i++)
X for (j = col1-1; j <= col1+1; j++)
X if (in_bounds(i, j))
X {
X d_ptr = &cave[i][j];
X /* values 11 and 12 are impossible here, place_streamer
X is never run before build_tunnel */
X if (d_ptr->fval == GRANITE_WALL)
X d_ptr->fval = TMP2_WALL;
X }
X }
X else if (c_ptr->fval == CORR_FLOOR || c_ptr->fval == BLOCKED_FLOOR)
X {
X row1 = tmp_row;
X col1 = tmp_col;
X if (!door_flag)
X {
X if (doorindex < 100)
X {
X doorstk[doorindex].y = row1;
X doorstk[doorindex].x = col1;
X doorindex++;
X }
X door_flag = TRUE;
X }
X if (randint(100) > DUN_TUN_CON)
X {
X /* make sure that tunnel has gone a reasonable distance
X before stopping it, this helps prevent isolated rooms */
X tmp_row = row1 - start_row;
X if (tmp_row < 0) tmp_row = -tmp_row;
X tmp_col = col1 - start_col;
X if (tmp_col < 0) tmp_col = -tmp_col;
X if (tmp_row > 10 || tmp_col > 10)
X stop_flag = TRUE;
X }
X }
X else /* c_ptr->fval != NULL, TMP2, GRANITE, CORR */
X {
X row1 = tmp_row;
X col1 = tmp_col;
X }
X }
X while (((row1 != row2) || (col1 != col2)) && (!stop_flag));
X
X tun_ptr = &tunstk[0];
X for (i = 0; i < tunindex; i++)
X {
X d_ptr = &cave[tun_ptr->y][tun_ptr->x];
X d_ptr->fval = CORR_FLOOR;
X tun_ptr++;
X }
X for (i = 0; i < wallindex; i++)
X {
X c_ptr = &cave[wallstk[i].y][wallstk[i].x];
X if (c_ptr->fval == TMP2_WALL)
X {
X if (randint(100) < DUN_TUN_PEN)
X place_door(wallstk[i].y, wallstk[i].x);
X else
X {
X /* these have to be doorways to rooms */
X c_ptr->fval = CORR_FLOOR;
X }
X }
X }
X}
X
X
Xstatic int next_to(y, x)
Xregister int y, x;
X{
X register int next;
X
X if (next_to_corr(y, x) > 2)
X if ((cave[y-1][x].fval >= MIN_CAVE_WALL)
X && (cave[y+1][x].fval >= MIN_CAVE_WALL))
X next = TRUE;
X else if ((cave[y][x-1].fval >= MIN_CAVE_WALL)
X && (cave[y][x+1].fval >= MIN_CAVE_WALL))
X next = TRUE;
X else
X next = FALSE;
X else
X next = FALSE;
X return(next);
X}
X
X/* Places door at y, x position if at least 2 walls found */
Xstatic void try_door(y, x)
Xregister int y, x;
X{
X if ((cave[y][x].fval == CORR_FLOOR) && (randint(100) > DUN_TUN_JCT)
X && next_to(y, x))
X place_door(y, x);
X}
X
X
X/* Returns random co-ordinates -RAK- */
Xstatic void new_spot(y, x)
Xint16 *y, *x;
X{
X register int i, j;
X register cave_type *c_ptr;
X
X do
X {
X i = randint(cur_height - 2);
X j = randint(cur_width - 2);
X c_ptr = &cave[i][j];
X }
X while (c_ptr->fval >= MIN_CLOSED_SPACE || (c_ptr->cptr != 0)
X || (c_ptr->tptr != 0));
X *y = i;
X *x = j;
X}
X
X
X/* Cave logic flow for generation of new dungeon */
Xstatic void cave_gen()
X{
X struct spot_type
X {
X int endx;
X int endy;
X };
X int room_map[20][20];
X register int i, j, k;
X int y1, x1, y2, x2, pick1, pick2, tmp;
X int row_rooms, col_rooms, alloc_level;
X int16 yloc[400], xloc[400];
X
X row_rooms = 2*(cur_height/SCREEN_HEIGHT);
X col_rooms = 2*(cur_width /SCREEN_WIDTH);
X for (i = 0; i < row_rooms; i++)
X for (j = 0; j < col_rooms; j++)
X room_map[i][j] = FALSE;
X k = randnor(DUN_ROO_MEA, 2);
X for (i = 0; i < k; i++)
X room_map[randint(row_rooms)-1][randint(col_rooms)-1] = TRUE;
X k = 0;
X for (i = 0; i < row_rooms; i++)
X for (j = 0; j < col_rooms; j++)
X if (room_map[i][j] == TRUE)
X {
X yloc[k] = i * (SCREEN_HEIGHT >> 1) + QUART_HEIGHT;
X xloc[k] = j * (SCREEN_WIDTH >> 1) + QUART_WIDTH;
X if (dun_level > randint(DUN_UNUSUAL))
X {
X tmp = randint(3);
X if (tmp == 1) build_type1(yloc[k], xloc[k]);
X else if (tmp == 2) build_type2(yloc[k], xloc[k]);
X else build_type3(yloc[k], xloc[k]);
X }
X else
X build_room(yloc[k], xloc[k]);
X k++;
X#ifdef MAC
X SystemTask ();
X#endif
X }
X for (i = 0; i < k; i++)
X {
X pick1 = randint(k) - 1;
X pick2 = randint(k) - 1;
X y1 = yloc[pick1];
X x1 = xloc[pick1];
X yloc[pick1] = yloc[pick2];
X xloc[pick1] = xloc[pick2];
X yloc[pick2] = y1;
X xloc[pick2] = x1;
X }
X doorindex = 0;
X /* move zero entry to k, so that can call build_tunnel all k times */
X yloc[k] = yloc[0];
X xloc[k] = xloc[0];
X for (i = 0; i < k; i++)
X {
X y1 = yloc[i];
X x1 = xloc[i];
X y2 = yloc[i+1];
X x2 = xloc[i+1];
X build_tunnel(y2, x2, y1, x1);
X }
X#ifdef MAC
X SystemTask ();
X#endif
X fill_cave(GRANITE_WALL);
X for (i = 0; i < DUN_STR_MAG; i++)
X place_streamer(MAGMA_WALL, DUN_STR_MC);
X for (i = 0; i < DUN_STR_QUA; i++)
X place_streamer(QUARTZ_WALL, DUN_STR_QC);
X place_boundary();
X /* Place intersection doors */
X for (i = 0; i < doorindex; i++)
X {
X try_door(doorstk[i].y, doorstk[i].x-1);
X try_door(doorstk[i].y, doorstk[i].x+1);
X try_door(doorstk[i].y-1, doorstk[i].x);
X try_door(doorstk[i].y+1, doorstk[i].x);
X }
X#ifdef MAC
X SystemTask ();
X#endif
X alloc_level = (dun_level/3);
X if (alloc_level < 2)
X alloc_level = 2;
X else if (alloc_level > 10)
X alloc_level = 10;
X place_stairs(2, randint(2)+2, 3);
X place_stairs(1, randint(2), 3);
X /* Set up the character co-ords, used by alloc_monster, place_win_monster */
X new_spot(&char_row, &char_col);
X alloc_monster((randint(8)+MIN_MALLOC_LEVEL+alloc_level), 0, TRUE);
X alloc_object(set_corr, 3, randint(alloc_level));
X alloc_object(set_room, 5, randnor(TREAS_ROOM_ALLOC, 3));
X alloc_object(set_floor, 5, randnor(TREAS_ANY_ALLOC, 3));
X alloc_object(set_floor, 4, randnor(TREAS_GOLD_ALLOC, 3));
X alloc_object(set_floor, 1, randint(alloc_level));
X if (dun_level >= WIN_MON_APPEAR) place_win_monster();
X}
X
X
X/* Builds a store at a row, column coordinate */
Xstatic void build_store(store_num, y, x)
Xint store_num, y, x;
X{
X int yval, y_height, y_depth;
X int xval, x_left, x_right;
X register int i, j;
X int cur_pos, tmp;
X register cave_type *c_ptr;
X
X yval = y*10 + 5;
X xval = x*16 + 16;
X y_height = yval - randint(3);
X y_depth = yval + randint(4);
X x_left = xval - randint(6);
X x_right = xval + randint(6);
X for (i = y_height; i <= y_depth; i++)
X for (j = x_left; j <= x_right; j++)
X cave[i][j].fval = BOUNDARY_WALL;
X tmp = randint(4);
X if (tmp < 3)
X {
X i = randint(y_depth-y_height) + y_height - 1;
X if (tmp == 1) j = x_left;
X else j = x_right;
X }
X else
X {
X j = randint(x_right-x_left) + x_left - 1;
X if (tmp == 3) i = y_depth;
X else i = y_height;
X }
X c_ptr = &cave[i][j];
X c_ptr->fval = CORR_FLOOR;
X cur_pos = popt();
X c_ptr->tptr = cur_pos;
X invcopy(&t_list[cur_pos], OBJ_STORE_DOOR + store_num);
X}
X
X
X/* Link all free space in treasure list together */
Xstatic void tlink()
X{
X register int i;
X
X for (i = 0; i < MAX_TALLOC; i++)
X invcopy(&t_list[i], OBJ_NOTHING);
X tcptr = MIN_TRIX;
X}
X
X
X/* Link all free space in monster list together */
Xstatic void mlink()
X{
X register int i;
X
X for (i = 0; i < MAX_MALLOC; i++)
X m_list[i] = blank_monster;
X mfptr = MIN_MONIX;
X}
X
X
X/* Town logic flow for generation of new town */
Xstatic void town_gen()
X{
X register int i, j, l, m;
X register cave_type *c_ptr;
X int rooms[6], k;
X
X set_seed(town_seed);
X for (i = 0; i < 6; i++)
X rooms[i] = i;
X l = 6;
X for (i = 0; i < 2; i++)
X for (j = 0; j < 3; j++)
X {
X k = randint(l) - 1;
X build_store(rooms[k], i, j);
X for (m = k; m < l-1; m++)
X rooms[m] = rooms[m+1];
X l--;
X }
X fill_cave(DARK_FLOOR);
X /* make stairs before reset_seed, so that they don't move around */
X place_boundary();
X place_stairs(2, 1, 0);
X reset_seed();
X /* Set up the character co-ords, used by alloc_monster below */
X new_spot(&char_row, &char_col);
X if (0x1 & (turn / 5000))
X { /* Night */
X for (i = 0; i < cur_height; i++)
X {
X c_ptr = &cave[i][0];
X for (j = 0; j < cur_width; j++)
X {
X if (c_ptr->fval != DARK_FLOOR)
X c_ptr->pl = TRUE;
X c_ptr++;
X }
X#ifdef MAC
X SystemTask ();
X#endif
X }
X alloc_monster(MIN_MALLOC_TN, 3, TRUE);
X }
X else
X { /* Day */
X for (i = 0; i < cur_height; i++)
X {
X c_ptr = &cave[i][0];
X for (j = 0; j < cur_width; j++)
X {
X c_ptr->pl = TRUE;
X c_ptr++;
X }
X#ifdef MAC
X SystemTask ();
X#endif
X }
X alloc_monster(MIN_MALLOC_TD, 3, TRUE);
X }
X store_maint();
X}
X
X
X/* Generates a random dungeon level -RAK- */
Xvoid generate_cave()
X{
X panel_row_min = 0;
X panel_row_max = 0;
X panel_col_min = 0;
X panel_col_max = 0;
X char_row = -1;
X char_col = -1;
X
X#ifdef MAC
X macbeginwait ();
X#endif
X
X tlink();
X mlink();
X blank_cave();
X
X if (dun_level == 0)
X {
X cur_height = SCREEN_HEIGHT;
X cur_width = SCREEN_WIDTH;
X max_panel_rows = (cur_height/SCREEN_HEIGHT)*2 - 2;
X max_panel_cols = (cur_width /SCREEN_WIDTH )*2 - 2;
X panel_row = max_panel_rows;
X panel_col = max_panel_cols;
X town_gen();
X }
X else
X {
X cur_height = MAX_HEIGHT;
X cur_width = MAX_WIDTH;
X max_panel_rows = (cur_height/SCREEN_HEIGHT)*2 - 2;
X max_panel_cols = (cur_width /SCREEN_WIDTH )*2 - 2;
X panel_row = max_panel_rows;
X panel_col = max_panel_cols;
X cave_gen();
X }
X#ifdef MAC
X macendwait ();
X#endif
X}
END_OF_FILE
if test 35484 -ne `wc -c <'source/generate.c'`; then
echo shar: \"'source/generate.c'\" unpacked with wrong size!
fi
# end of 'source/generate.c'
fi
if test -f 'source/recall.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/recall.c'\"
else
echo shar: Extracting \"'source/recall.c'\" \(17032 characters\)
sed "s/^X//" >'source/recall.c' <<'END_OF_FILE'
X/* source/recall.c: print out monster memory info -CJS-
X
X Copyright (c) 1989-92 James E. Wilson, Christopher J. Stuart
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#ifdef __TURBOC__
X#include <stdio.h>
X#endif /* __TURBOC__ */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X#include "externs.h"
X
X#if defined(LINT_ARGS)
Xstatic void roff(char *);
X#else
Xstatic void roff();
X#endif
X
Xstatic char *desc_atype[] = {
X "do something undefined",
X "attack",
X "weaken",
X "confuse",
X "terrify",
X "shoot flames",
X "shoot acid",
X "freeze",
X "shoot lightning",
X "corrode",
X "blind",
X "paralyse",
X "steal money",
X "steal things",
X "poison",
X "reduce dexterity",
X "reduce constitution",
X "drain intelligence",
X "drain wisdom",
X "lower experience",
X "call for help",
X "disenchant",
X "eat your food",
X "absorb light",
X "absorb charges" };
Xstatic char *desc_amethod[] = {
X "make an undefined advance",
X "hit",
X "bite",
X "claw",
X "sting",
X "touch",
X "kick",
X "gaze",
X "breathe",
X "spit",
X "wail",
X "embrace",
X "crawl on you",
X "release spores",
X "beg",
X "slime you",
X "crush",
X "trample",
X "drool",
X "insult" };
Xstatic char *desc_howmuch[] = {
X " not at all",
X " a bit",
X "",
X " quite",
X " very",
X " most",
X " highly",
X " extremely" };
X
Xstatic char *desc_move[] = {
X "move invisibly",
X "open doors",
X "pass through walls",
X "kill weaker creatures",
X "pick up objects",
X "breed explosively" };
Xstatic char *desc_spell[] = {
X "teleport short distances",
X "teleport long distances",
X "teleport its prey",
X "cause light wounds",
X "cause serious wounds",
X "paralyse its prey",
X "induce blindness",
X "confuse",
X "terrify",
X "summon a monster",
X "summon the undead",
X "slow its prey",
X "drain mana",
X "unknown 1",
X "unknown 2" };
Xstatic char *desc_breath[] = {
X "lightning",
X "poison gases",
X "acid",
X "frost",
X "fire" };
Xstatic char *desc_weakness[] = {
X "frost",
X "fire",
X "poison",
X "acid",
X "bright light",
X "rock remover" };
X
Xstatic vtype roffbuf; /* Line buffer. */
Xstatic char *roffp; /* Pointer into line buffer. */
Xstatic int roffpline; /* Place to print line now being loaded. */
X
X#define plural(c, ss, sp) ((c) == 1 ? ss : sp)
X
X/* Number of kills needed for information. */
X
X/* the higher the level of the monster, the fewer the kills you need */
X#define knowarmor(l,d) ((d) > 304 / (4 + (l)))
X/* the higher the level of the monster, the fewer the attacks you need,
X the more damage an attack does, the more attacks you need */
X#define knowdamage(l,a,d) ((4 + (l))*(a) > 80 * (d))
X
X/* Do we know anything about this monster? */
Xint bool_roff_recall(mon_num)
Xint mon_num;
X{
X register recall_type *mp;
X register int i;
X
X if (wizard)
X return TRUE;
X mp = &c_recall[mon_num];
X if (mp->r_cmove || mp->r_cdefense || mp->r_kills || mp->r_spells
X || mp->r_deaths)
X return TRUE;
X for (i = 0; i < 4; i++)
X if (mp->r_attacks[i])
X return TRUE;
X return FALSE;
X}
X
X/* Print out what we have discovered about this monster. */
Xint roff_recall(mon_num)
Xint mon_num;
X{
X char *p, *q;
X int8u *pu;
X vtype temp;
X register recall_type *mp;
X register creature_type *cp;
X register int i, k;
X register int32u j;
X int32 templong;
X int mspeed;
X int32u rcmove, rspells;
X int16u rcdefense;
X recall_type save_mem;
X#ifdef ATARIST_MWC
X int32u holder;
X int32u holder2;
X#endif
X
X mp = &c_recall[mon_num];
X cp = &c_list[mon_num];
X if (wizard)
X {
X save_mem = *mp;
X mp->r_kills = MAX_SHORT;
X mp->r_wake = mp->r_ignore = MAX_UCHAR;
X#ifdef ATARIST_MWC
X j = (((cp->cmove & (holder = CM_4D2_OBJ)) != 0) * 8) +
X (((cp->cmove & (holder = CM_2D2_OBJ)) != 0) * 4) +
X (((cp->cmove & (holder = CM_1D2_OBJ)) != 0) * 2) +
X ((cp->cmove & (holder = CM_90_RANDOM)) != 0) +
X ((cp->cmove & (holder = CM_60_RANDOM)) != 0);
X holder = CM_TREASURE;
X mp->r_cmove = (cp->cmove & ~holder) | (j << CM_TR_SHIFT);
X#else
X j = (((cp->cmove & CM_4D2_OBJ) != 0) * 8) +
X (((cp->cmove & CM_2D2_OBJ) != 0) * 4) +
X (((cp->cmove & CM_1D2_OBJ) != 0) * 2) +
X ((cp->cmove & CM_90_RANDOM) != 0) +
X ((cp->cmove & CM_60_RANDOM) != 0);
X mp->r_cmove = (cp->cmove & ~CM_TREASURE) | (j << CM_TR_SHIFT);
X#endif
X mp->r_cdefense = cp->cdefense;
X mp->r_spells = cp->spells | CS_FREQ;
X j = 0;
X pu = cp->damage;
X while (*pu != 0 && j < 4)
X {
X /* Turbo C needs a 16 bit int for the array index. */
X mp->r_attacks[(int)j] = MAX_UCHAR;
X j++;
X pu++;
X }
X /* A little hack to enable the display of info for Quylthulgs. */
X if (mp->r_cmove & CM_ONLY_MAGIC)
X mp->r_attacks[0] = MAX_UCHAR;
X }
X roffpline = 0;
X roffp = roffbuf;
X#ifdef ATARIST_MWC
X holder = ~CS_FREQ;
X rspells = mp->r_spells & cp->spells & holder;
X /* the CM_WIN property is always known, set it if a win monster */
X holder = CM_WIN;
X rcmove = mp->r_cmove | (holder & cp->cmove);
X#else
X rspells = mp->r_spells & cp->spells & ~CS_FREQ;
X /* the CM_WIN property is always known, set it if a win monster */
X rcmove = mp->r_cmove | (CM_WIN & cp->cmove);
X#endif
X rcdefense = mp->r_cdefense & cp->cdefense;
X (void) sprintf(temp, "The %s:\n", cp->name);
X roff(temp);
X /* Conflict history. */
X if(mp->r_deaths)
X {
X (void) sprintf(temp,
X "%d of the contributors to your monster memory %s",
X mp->r_deaths, plural(mp->r_deaths, "has", "have") );
X roff(temp);
X roff(" been killed by this creature, and ");
X if (mp->r_kills == 0)
X roff("it is not ever known to have been defeated.");
X else
X {
X (void) sprintf(temp,
X "at least %d of the beasts %s been exterminated.",
X mp->r_kills, plural(mp->r_kills, "has", "have") );
X roff(temp);
X }
X }
X else if (mp->r_kills)
X {
X (void) sprintf(temp, "At least %d of these creatures %s",
X mp->r_kills, plural(mp->r_kills, "has", "have") );
X roff(temp);
X roff(" been killed by contributors to your monster memory.");
X }
X else
X roff("No known battles to the death are recalled.");
X /* Immediately obvious. */
X k = FALSE;
X if (cp->level == 0)
X {
X roff(" It lives in the town");
X k = TRUE;
X }
X else if (mp->r_kills)
X {
X /* The Balrog is a level 100 monster, but appears at 50 feet. */
X i = cp->level;
X if (i > WIN_MON_APPEAR)
X i = WIN_MON_APPEAR;
X (void) sprintf(temp, " It is normally found at depths of %d feet",
X i * 50);
X roff(temp);
X k = TRUE;
X }
X /* the c_list speed value is 10 greater, so that it can be a int8u */
X mspeed = cp->speed - 10;
X if (rcmove & CM_ALL_MV_FLAGS)
X {
X if (k)
X roff(", and");
X else
X {
X roff(" It");
X k = TRUE;
X }
X roff(" moves");
X if (rcmove & CM_RANDOM_MOVE)
X {
X /* Turbo C needs a 16 bit int for the array index. */
X roff(desc_howmuch[(int)((rcmove & CM_RANDOM_MOVE) >> 3)]);
X roff(" erratically");
X }
X if (mspeed == 1)
X roff(" at normal speed");
X else
X {
X if (rcmove & CM_RANDOM_MOVE)
X roff(", and");
X if (mspeed <= 0)
X {
X if (mspeed == -1)
X roff(" very");
X else if (mspeed < -1)
X roff(" incredibly");
X roff(" slowly");
X }
X else
X {
X if (mspeed == 3)
X roff(" very");
X else if (mspeed > 3)
X roff(" unbelievably");
X roff(" quickly");
X }
X }
X }
X if (rcmove & CM_ATTACK_ONLY)
X {
X if(k)
X roff(", but");
X else
X {
X roff(" It");
X k = TRUE;
X }
X roff(" does not deign to chase intruders");
X }
X if (rcmove & CM_ONLY_MAGIC)
X {
X if (k)
X roff (", but");
X else
X {
X roff (" It");
X k = TRUE;
X }
X roff (" always moves and attacks by using magic");
X }
X if(k)
X roff(".");
X /* Kill it once to know experience, and quality (evil, undead, monsterous).
X The quality of being a dragon is obvious. */
X if (mp->r_kills)
X {
X roff(" A kill of this");
X if (cp->cdefense & CD_ANIMAL)
X roff(" natural");
X if (cp->cdefense & CD_EVIL)
X roff(" evil");
X if (cp->cdefense & CD_UNDEAD)
X roff(" undead");
X
X /* calculate the integer exp part, can be larger than 64K when first
X level character looks at Balrog info, so must store in long */
X templong = (long)cp->mexp * cp->level / py.misc.lev;
X /* calculate the fractional exp part scaled by 100,
X must use long arithmetic to avoid overflow */
X j = (((long)cp->mexp * cp->level % py.misc.lev) * (long)1000 /
X py.misc.lev+5) / 10;
X
X (void) sprintf(temp, " creature is worth %ld.%02ld point%s", templong,
X j, (templong == 1 && j == 0 ? "" : "s"));
X roff(temp);
X
X if (py.misc.lev / 10 == 1) p = "th";
X else
X {
X i = py.misc.lev % 10;
X if (i == 1) p = "st";
X else if (i == 2) p = "nd";
X else if (i == 3) p = "rd";
X else p = "th";
X }
X i = py.misc.lev;
X if (i == 8 || i == 11 || i == 18) q = "n";
X else q = "";
X (void) sprintf(temp, " for a%s %d%s level character.", q, i, p);
X roff(temp);
X }
X /* Spells known, if have been used against us. */
X k = TRUE;
X j = rspells;
X#ifdef ATARIST_MWC
X holder = CS_BREATHE;
X holder2 = CS_BR_LIGHT;
X for (i = 0; j & holder; i++)
X#else
X for (i = 0; j & CS_BREATHE; i++)
X#endif
X {
X#ifdef ATARIST_MWC
X if (j & (holder2 << i))
X#else
X if (j & (CS_BR_LIGHT << i))
X#endif
X {
X#ifdef ATARIST_MWC
X j &= ~(holder2 << i);
X#else
X j &= ~(CS_BR_LIGHT << i);
X#endif
X if (k)
X {
X roff(" It can breathe ");
X k = FALSE;
X }
X#ifdef ATARIST_MWC
X else if (j & holder)
X#else
X else if (j & CS_BREATHE)
X#endif
X roff(", ");
X else
X roff(" and ");
X roff(desc_breath[i]);
X }
X }
X k = TRUE;
X#ifdef ATARIST_MWC
X holder = CS_SPELLS;
X for (i = 0; j & holder; i++)
X#else
X for (i = 0; j & CS_SPELLS; i++)
X#endif
X {
X if (j & (CS_TEL_SHORT << i))
X {
X j &= ~(CS_TEL_SHORT << i);
X if (k)
X {
X#ifdef ATARIST_MWC
X holder2 = CS_BREATHE;
X if (rspells & holder2)
X#else
X if (rspells & CS_BREATHE)
X#endif
X roff(", and is also");
X else
X roff(" It is");
X roff(" magical, casting spells which ");
X k = FALSE;
X }
X#ifdef ATARIST_MWC
X else if (j & holder)
X#else
X else if (j & CS_SPELLS)
X#endif
X roff(", ");
X else
X roff(" or ");
X roff(desc_spell[i]);
X }
X }
X#ifdef ATARIST_MWC
X holder = CS_BREATHE|CS_SPELLS;
X if (rspells & holder)
X#else
X if (rspells & (CS_BREATHE|CS_SPELLS))
X#endif
X {
X if ((mp->r_spells & CS_FREQ) > 5)
X { /* Could offset by level */
X (void) sprintf(temp, "; 1 time in %ld", cp->spells & CS_FREQ);
X roff(temp);
X }
X roff(".");
X }
X /* Do we know how hard they are to kill? Armor class, hit die. */
X if (knowarmor(cp->level, mp->r_kills))
X {
X (void) sprintf(temp, " It has an armor rating of %d", cp->ac);
X roff(temp);
X (void) sprintf(temp, " and a%s life rating of %dd%d.",
X ((cp->cdefense & CD_MAX_HP) ? " maximized" : ""),
X cp->hd[0], cp->hd[1]);
X roff(temp);
X }
X /* Do we know how clever they are? Special abilities. */
X k = TRUE;
X j = rcmove;
X#ifdef ATARIST_MWC
X holder = CM_SPECIAL;
X holder2 = CM_INVISIBLE;
X for (i = 0; j & holder; i++)
X#else
X for (i = 0; j & CM_SPECIAL; i++)
X#endif
X {
X#ifdef ATARIST_MWC
X if (j & (holder2 << i))
X#else
X if (j & (CM_INVISIBLE << i))
X#endif
X {
X#ifdef ATARIST_MWC
X j &= ~(holder2 << i);
X#else
X j &= ~(CM_INVISIBLE << i);
X#endif
X if (k)
X {
X roff(" It can ");
X k = FALSE;
X }
X#ifdef ATARIST_MWC
X else if (j & holder)
X#else
X else if (j & CM_SPECIAL)
X#endif
X roff(", ");
X else
X roff(" and ");
X roff(desc_move[i]);
X }
X }
X if (!k)
X roff(".");
X /* Do we know its special weaknesses? Most cdefense flags. */
X k = TRUE;
X j = rcdefense;
X for (i = 0; j & CD_WEAKNESS; i++)
X {
X if (j & (CD_FROST << i))
X {
X j &= ~(CD_FROST << i);
X if (k)
X {
X roff(" It is susceptible to ");
X k = FALSE;
X }
X else if (j & CD_WEAKNESS)
X roff(", ");
X else
X roff(" and ");
X roff(desc_weakness[i]);
X }
X }
X if (!k)
X roff(".");
X if (rcdefense & CD_INFRA)
X roff(" It is warm blooded");
X if (rcdefense & CD_NO_SLEEP)
X {
X if (rcdefense & CD_INFRA)
X roff(", and");
X else
X roff(" It");
X roff(" cannot be charmed or slept");
X }
X if (rcdefense & (CD_NO_SLEEP|CD_INFRA))
X roff(".");
X /* Do we know how aware it is? */
X if (((mp->r_wake * mp->r_wake) > cp->sleep) || mp->r_ignore == MAX_UCHAR ||
X (cp->sleep == 0 && mp->r_kills >= 10))
X {
X roff(" It ");
X if(cp->sleep > 200)
X roff("prefers to ignore");
X else if(cp->sleep > 95)
X roff("pays very little attention to");
X else if(cp->sleep > 75)
X roff("pays little attention to");
X else if(cp->sleep > 45)
X roff("tends to overlook");
X else if(cp->sleep > 25)
X roff("takes quite a while to see");
X else if(cp->sleep > 10)
X roff("takes a while to see");
X else if(cp->sleep > 5)
X roff("is fairly observant of");
X else if(cp->sleep > 3)
X roff("is observant of");
X else if(cp->sleep > 1)
X roff("is very observant of");
X else if(cp->sleep != 0)
X roff("is vigilant for");
X else
X roff("is ever vigilant for");
X (void) sprintf(temp, " intruders, which it may notice from %d feet.",
X 10 * cp->aaf);
X roff(temp);
X }
X /* Do we know what it might carry? */
X#ifdef ATARIST_MWC
X holder = CM_CARRY_OBJ|CM_CARRY_BOLD;
X if (rcmove & holder)
X#else
X if (rcmove & (CM_CARRY_OBJ|CM_CARRY_GOLD))
X#endif
X {
X roff(" It may");
X#ifdef ATARIST_MWC
X j = (rcmove & (holder = CM_TREASURE)) >> CM_TR_SHIFT;
X#else
X j = (rcmove & CM_TREASURE) >> CM_TR_SHIFT;
X#endif
X if (j == 1)
X {
X#ifdef ATARIST_MWC
X if ((cp->cmove & (holder = CM_TREASURE)) == CM_60_RANDOM)
X#else
X if ((cp->cmove & CM_TREASURE) == CM_60_RANDOM)
X#endif
X roff(" sometimes");
X else
X roff(" often");
X }
X#ifdef ATARIST_MWC
X else if ((j == 2) && ((cp->cmove & (holder = CM_TREASURE)) ==
X#else
X else if ((j == 2) && ((cp->cmove & CM_TREASURE) ==
X#endif
X (CM_60_RANDOM|CM_90_RANDOM)))
X roff (" often");
X roff(" carry");
X p = " objects";
X if (j == 1)
X p = " an object";
X else if (j == 2)
X roff(" one or two");
X else
X {
X (void) sprintf(temp, " up to %ld", j);
X roff(temp);
X }
X#ifdef ATARIST_MWC
X if (rcmove & (holder = CM_CARRY_OBJ))
X#else
X if (rcmove & CM_CARRY_OBJ)
X#endif
X {
X roff(p);
X#ifdef ATARIST_MWC
X if (rcmove & (holder = CM_CARRY_GOLD))
X#else
X if (rcmove & CM_CARRY_GOLD)
X#endif
X {
X roff(" or treasure");
X if (j > 1)
X roff("s");
X }
X roff(".");
X }
X else if (j != 1)
X roff(" treasures.");
X else
X roff(" treasure.");
X }
X
X /* We know about attacks it has used on us, and maybe the damage they do. */
X /* k is the total number of known attacks, used for punctuation */
X k = 0;
X for (j = 0; j < 4; j++)
X /* Turbo C needs a 16 bit int for the array index. */
X if (mp->r_attacks[(int)j])
X k++;
X pu = cp->damage;
X /* j counts the attacks as printed, used for punctuation */
X j = 0;
X for (i = 0; *pu != 0 && i < 4; pu++, i++)
X {
X int att_type, att_how, d1, d2;
X
X /* don't print out unknown attacks */
X if (!mp->r_attacks[i])
X continue;
X
X att_type = monster_attacks[*pu].attack_type;
X att_how = monster_attacks[*pu].attack_desc;
X d1 = monster_attacks[*pu].attack_dice;
X d2 = monster_attacks[*pu].attack_sides;
X
X j++;
X if (j == 1)
X roff(" It can ");
X else if (j == k)
X roff(", and ");
X else
X roff(", ");
X
X if (att_how > 19)
X att_how = 0;
X roff(desc_amethod[att_how]);
X if (att_type != 1 || d1 > 0 && d2 > 0)
X {
X roff(" to ");
X if (att_type > 24)
X att_type = 0;
X roff(desc_atype[att_type]);
X if (d1 && d2)
X {
X if (knowdamage(cp->level, mp->r_attacks[i], d1*d2))
X {
X if (att_type == 19) /* Loss of experience */
X roff(" by");
X else
X roff(" with damage");
X (void) sprintf(temp, " %dd%d", d1, d2 );
X roff(temp);
X }
X }
X }
X }
X if (j)
X roff(".");
X else if (k > 0 && mp->r_attacks[0] >= 10)
X roff(" It has no physical attacks.");
X else
X roff(" Nothing is known about its attack.");
X /* Always know the win creature. */
X#ifdef ATARIST_MWC
X if (cp->cmove & (holder = CM_WIN))
X#else
X if (cp->cmove & CM_WIN)
X#endif
X roff(" Killing one of these wins the game!");
X roff("\n");
X prt("--pause--", roffpline, 0);
X if (wizard)
X *mp = save_mem;
X return inkey();
X}
X
X/* Print out strings, filling up lines as we go. */
Xstatic void roff(p)
Xregister char *p;
X{
X register char *q, *r;
X
X while (*p)
X {
X *roffp = *p;
X if (*p == '\n' || roffp >= roffbuf + sizeof(roffbuf)-1)
X {
X q = roffp;
X if (*p != '\n')
X while (*q != ' ')
X q--;
X *q = 0;
X prt(roffbuf, roffpline, 0);
X roffpline++;
X r = roffbuf;
X while (q < roffp)
X {
X q++;
X *r = *q;
X r++;
X }
X roffp = r;
X }
X else
X roffp++;
X p++;
X }
X}
END_OF_FILE
if test 17032 -ne `wc -c <'source/recall.c'`; then
echo shar: \"'source/recall.c'\" unpacked with wrong size!
fi
# end of 'source/recall.c'
fi
echo shar: End of archive 14 \(of 39\).
cp /dev/null ark14isdone
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 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 39 archives.
echo "Now run "bldfiles.sh" to build split files"
rm -f 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