/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Timothy C. Stoehr.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* level.c
*
* This source herein may be modified and/or distributed by anybody who
* so desires, with the following restrictions:
* 1.) No portion of this notice shall be removed.
* 2.) Credit shall not be taken for the creation of this source.
* 3.) This code is not to be traded, sold, or used for personal
* gain or profit.
*
*/
#include "rogue.h"
#define SWAP(x,y) (t = (x), (x) = (y), (y) = t)
static void add_mazes(void);
static int connect_rooms(short, short);
static void draw_simple_passage(short, short, short, short, short);
static void fill_it(int, boolean);
static void fill_out_level(void);
static int get_exp_level(long);
static void hide_boxed_passage(short, short, short, short, short);
static void make_maze(short, short, short, short, short, short);
static void make_room(short, short, short, short);
static boolean mask_room(short, short *, short *, unsigned short);
static void mix_random_rooms(void);
static void put_door(room *, short, short *, short *);
static void recursive_deadend(short, const short *, short, short);
static int same_col(int, int);
static int same_row(int, int);
short cur_level = 0;
short max_level = 1;
short cur_room;
const char *new_level_message = NULL;
short party_room = NO_ROOM;
switch(must_1) {
case 0:
must_1 = 0;
must_2 = 1;
must_3 = 2;
break;
case 1:
must_1 = 3;
must_2 = 4;
must_3 = 5;
break;
case 2:
must_1 = 6;
must_2 = 7;
must_3 = 8;
break;
case 3:
must_1 = 0;
must_2 = 3;
must_3 = 6;
break;
case 4:
must_1 = 1;
must_2 = 4;
must_3 = 7;
break;
case 5:
must_1 = 2;
must_2 = 5;
must_3 = 8;
break;
}
if (rand_percent(8)) {
party_room = 0;
}
big_room = ((party_room != NO_ROOM) && rand_percent(1));
if (big_room) {
make_room(BIG_ROOM, 0, 0, 0);
} else {
for (i = 0; i < MAXROOMS; i++) {
make_room(i, must_1, must_2, must_3);
}
}
if (!big_room) {
add_mazes();
mix_random_rooms();
for (j = 0; j < MAXROOMS; j++) {
i = random_rooms[j];
if (i < (MAXROOMS-1)) {
(void)connect_rooms(i, i+1);
}
if (i < (MAXROOMS-3)) {
(void)connect_rooms(i, i+3);
}
if (i < (MAXROOMS-2)) {
if (rooms[i+1].is_room & R_NOTHING) {
if (connect_rooms(i, i+2)) {
rooms[i+1].is_room = R_CROSS;
}
}
}
if (i < (MAXROOMS-6)) {
if (rooms[i+3].is_room & R_NOTHING) {
if (connect_rooms(i, i+6)) {
rooms[i+3].is_room = R_CROSS;
}
}
}
if (is_all_connected()) {
break;
}
}
fill_out_level();
}
if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
put_amulet();
}
}
static void
make_room(short rn, short r1, short r2, short r3)
{
short left_col, right_col, top_row, bottom_row;
short width, height;
short row_offset, col_offset;
short i, j, ch;
int
drop_check(void)
{
if (wizard) {
return(1);
}
if (dungeon[rogue.row][rogue.col] & STAIRS) {
if (levitate) {
messagef(0, "you're floating in the air!");
return(0);
}
return(1);
}
messagef(0, "I see no way down");
return(0);
}
int
check_up(void)
{
if (!wizard) {
if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
messagef(0, "I see no way up");
return(0);
}
if (!has_amulet()) {
messagef(0, "your way is magically blocked");
return(0);
}
}
new_level_message = "you feel a wrenching sensation in your gut";
if (cur_level == 1) {
win();
} else {
cur_level -= 2;
return(1);
}
return(0);
}
void
add_exp(int e, boolean promotion)
{
short new_exp;
short i, hp;
rogue.exp_points += e;
if (rogue.exp_points >= level_points[rogue.exp-1]) {
new_exp = get_exp_level(rogue.exp_points);
if (rogue.exp_points > MAX_EXP) {
rogue.exp_points = MAX_EXP + 1;
}
for (i = rogue.exp+1; i <= new_exp; i++) {
messagef(0, "welcome to level %d", i);
if (promotion) {
hp = hp_raise();
rogue.hp_current += hp;
rogue.hp_max += hp;
}
rogue.exp = i;
print_stats(STAT_HP | STAT_EXP);
}
} else {
print_stats(STAT_EXP);
}
}
static int
get_exp_level(long e)
{
short i;
for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
if (level_points[i] > e) {
break;
}
}
return(i+1);
}
int
hp_raise(void)
{
int hp;
hp = (wizard ? 10 : get_rand(3, 10));
return(hp);
}
static void
mix_random_rooms(void)
{
short i, t;
short x, y;
for (i = 0; i < (3 * MAXROOMS); i++) {
do {
x = get_rand(0, (MAXROOMS-1));
y = get_rand(0, (MAXROOMS-1));
} while (x == y);
SWAP(random_rooms[x], random_rooms[y]);
}
}