Shaped and themed rooms
Allows creating shaped or themed rooms for the Dungeons of Doom via lua script. Invalidates bones and saves. Makefiles updated for unix/linux by adding themerms.lua, but other OSes need to have that added.
This commit is contained in:
@@ -6,6 +6,7 @@ dungeon = {
|
||||
base = 25,
|
||||
range = 5,
|
||||
alignment = "unaligned",
|
||||
themerooms = "themerms.lua",
|
||||
branches = {
|
||||
{
|
||||
name = "The Gnomish Mines",
|
||||
|
||||
529
dat/themerms.lua
Normal file
529
dat/themerms.lua
Normal file
@@ -0,0 +1,529 @@
|
||||
|
||||
-- themerooms is an array of tables and/or functions.
|
||||
-- the tables define "frequency" and "contents",
|
||||
-- a plain function has frequency of 1
|
||||
-- des.room({ type = "ordinary", filled = 1 })
|
||||
-- - ordinary rooms can be converted to shops or any other special rooms.
|
||||
-- - filled = 1 means the room gets random room contents, even if it
|
||||
-- doesn't get converted into a special room. Without filled,
|
||||
-- the room only gets what you define in here.
|
||||
-- - use type = "themed" to force a room that's never converted
|
||||
-- to a special room, such as a shop or a temple.
|
||||
-- core calls themerooms_generate() multiple times per level
|
||||
-- to generate a single themed room.
|
||||
|
||||
|
||||
themerooms = {
|
||||
{
|
||||
-- the "default" room
|
||||
frequency = 1000,
|
||||
contents = function()
|
||||
des.room({ type = "ordinary", filled = 1 });
|
||||
end
|
||||
},
|
||||
|
||||
-- Fake Delphi
|
||||
function()
|
||||
des.room({ type = "ordinary", w = 11,h = 9, filled = 1,
|
||||
contents = function()
|
||||
des.room({ type = "ordinary", x = 4,y = 3, w = 3,h = 3, filled = 1,
|
||||
contents = function()
|
||||
des.door({ state="random", wall="all" });
|
||||
end
|
||||
});
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Room in a room
|
||||
-- FIXME: subroom location is too often left/top?
|
||||
function()
|
||||
des.room({ type = "ordinary", filled = 1,
|
||||
contents = function()
|
||||
des.room({ type = "ordinary",
|
||||
contents = function()
|
||||
des.door({ state="random", wall="all" });
|
||||
end
|
||||
});
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Huge room, with another room inside (90%)
|
||||
function()
|
||||
des.room({ type = "ordinary", w = nh.rn2(10)+11,h = nh.rn2(5)+8, filled = 1,
|
||||
contents = function()
|
||||
if (percent(90)) then
|
||||
des.room({ type = "ordinary", filled = 1,
|
||||
contents = function()
|
||||
des.door({ state="random", wall="all" });
|
||||
if (percent(50)) then
|
||||
des.door({ state="random", wall="all" });
|
||||
end
|
||||
end
|
||||
});
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Ice room
|
||||
function()
|
||||
des.room({ type = "themed", filled = 1,
|
||||
contents = function()
|
||||
des.terrain(selection.floodfill(1,1), "I");
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Boulder room
|
||||
function()
|
||||
des.room({ type = "themed",
|
||||
contents = function()
|
||||
for i = 1, 3 + d(6) do
|
||||
des.object("boulder");
|
||||
end
|
||||
for i = 1, d(4) do
|
||||
des.trap("rolling boulder");
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Spider nest
|
||||
function()
|
||||
des.room({ type = "themed",
|
||||
contents = function()
|
||||
for i = 1, d(3,3) do
|
||||
des.trap("web");
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Trap room
|
||||
function()
|
||||
des.room({ type = "themed", filled = 0,
|
||||
contents = function(rm)
|
||||
local traps = { "arrow", "dart", "falling rock", "bear",
|
||||
"land mine", "sleep gas", "rust",
|
||||
"anti magic" };
|
||||
shuffle(traps);
|
||||
for x = 0, rm.width do
|
||||
for y = 0, rm.height do
|
||||
if (percent(75)) then
|
||||
des.trap(traps[1], x, y);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Buried treasure
|
||||
function()
|
||||
des.room({ type = "ordinary", filled = 1,
|
||||
contents = function()
|
||||
des.object({ id = "chest", buried = true, contents = function()
|
||||
for i = 1, d(3,4) do
|
||||
des.object();
|
||||
end
|
||||
end });
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Massacre
|
||||
function()
|
||||
des.room({ type = "themed",
|
||||
contents = function()
|
||||
local mon = { "apprentice", "warrior", "ninja", "thug",
|
||||
"hunter", "acolyte", "abbot", "page",
|
||||
"attendant", "neanderthal", "chieftain",
|
||||
"student", "wizard", "valkyrie", "tourist",
|
||||
"samurai", "rogue", "ranger", "priestess",
|
||||
"priest", "monk", "knight", "healer",
|
||||
"cavewoman", "caveman", "barbarian",
|
||||
"archeologist" };
|
||||
shuffle(mon);
|
||||
for i = 1, d(5,5) do
|
||||
if (percent(10)) then shuffle(mon); end
|
||||
des.object({ id = "corpse", montype = mon[1] });
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Statuary
|
||||
function()
|
||||
des.room({ type = "themed",
|
||||
contents = function()
|
||||
for i = 1, d(5,5) do
|
||||
des.object({ id = "statue" });
|
||||
end
|
||||
for i = 1, d(3) do
|
||||
des.trap("statue");
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Light source
|
||||
function()
|
||||
des.room({ type = "themed", lit = 0,
|
||||
contents = function()
|
||||
des.object({ id = "oil lamp", lit = true });
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Temple of the gods
|
||||
function()
|
||||
des.room({ type = "themed",
|
||||
contents = function()
|
||||
des.altar({ align = align[1] });
|
||||
des.altar({ align = align[2] });
|
||||
des.altar({ align = align[3] });
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Mausoleum
|
||||
function()
|
||||
des.room({ type = "themed", w = 5,h = 5,
|
||||
contents = function()
|
||||
local pts = { {1,1}, {2,1}, {3,1},
|
||||
{1,2}, {3,2},
|
||||
{1,3}, {2,3}, {3,3} };
|
||||
for i = 1, #pts do
|
||||
des.terrain(pts[i], "-");
|
||||
end
|
||||
if (percent(50)) then
|
||||
local mons = { "M", "V", "L", "Z" };
|
||||
shuffle(mons);
|
||||
des.monster(mons[1], 2,2);
|
||||
else
|
||||
des.object({ id = "corpse", montype = "@", coord = {2,2} });
|
||||
end
|
||||
if (percent(20)) then
|
||||
local place = { {2,1}, {1,2}, {3,2}, {2,3} };
|
||||
shuffle(place);
|
||||
des.terrain(place[1], "S");
|
||||
end
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- Random dungeon feature in the middle of a odd-sized room
|
||||
function()
|
||||
local wid = 3 + (nh.rn2(3) * 2);
|
||||
local hei = 3 + (nh.rn2(3) * 2);
|
||||
des.room({ type = "ordinary", filled = 1, w = wid, h = hei,
|
||||
contents = function(rm)
|
||||
local feature = { "C", "L", "I", "P", "T" };
|
||||
shuffle(feature);
|
||||
des.terrain(rm.width / 2, rm.height / 2, feature[1]);
|
||||
end
|
||||
});
|
||||
end,
|
||||
|
||||
-- L-shaped
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----xxx
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
|...----
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
--------]], contents = function(m) des.region({ region={1,1,3,3}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- L-shaped, rot 1
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
----...|
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
--------]], contents = function(m) des.region({ region={5,1,5,3}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- L-shaped, rot 2
|
||||
function()
|
||||
des.map({ map = [[
|
||||
--------
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
----...|
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
xxx-----]], contents = function(m) des.region({ region={1,1,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- L-shaped, rot 3
|
||||
function()
|
||||
des.map({ map = [[
|
||||
--------
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
|...----
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
-----xxx]], contents = function(m) des.region({ region={1,1,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Blocked center
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----------
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
|...LLL...|
|
||||
|...LLL...|
|
||||
|...LLL...|
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
-----------]], contents = function(m)
|
||||
if (percent(30)) then
|
||||
local terr = { "-", "P" };
|
||||
shuffle(terr);
|
||||
des.replace_terrain({ region = {1,1, 9,9}, fromterrain = "L", toterrain = terr[1] });
|
||||
end
|
||||
des.region({ region={1,1,2,2}, type="ordinary", irregular=true, prefilled=true });
|
||||
end });
|
||||
end,
|
||||
|
||||
-- Circular, small
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xx---xx
|
||||
x--.--x
|
||||
--...--
|
||||
|.....|
|
||||
--...--
|
||||
x--.--x
|
||||
xx---xx]], contents = function(m) des.region({ region={3,3,3,3}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Circular, medium
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xx-----xx
|
||||
x--...--x
|
||||
--.....--
|
||||
|.......|
|
||||
|.......|
|
||||
|.......|
|
||||
--.....--
|
||||
x--...--x
|
||||
xx-----xx]], contents = function(m) des.region({ region={4,4,4,4}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Circular, big
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----xxx
|
||||
x---...---x
|
||||
x-.......-x
|
||||
--.......--
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
--.......--
|
||||
x-.......-x
|
||||
x---...---x
|
||||
xxx-----xxx]], contents = function(m) des.region({ region={5,5,5,5}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- T-shaped
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----xxx
|
||||
xxx|...|xxx
|
||||
xxx|...|xxx
|
||||
----...----
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
-----------]], contents = function(m) des.region({ region={5,5,5,5}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- T-shaped, rot 1
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----xxx
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
|...----
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
|...----
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
-----xxx]], contents = function(m) des.region({ region={2,2,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- T-shaped, rot 2
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----------
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
----...----
|
||||
xxx|...|xxx
|
||||
xxx|...|xxx
|
||||
xxx-----xxx]], contents = function(m) des.region({ region={2,2,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- T-shaped, rot 3
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
----...|
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
----...|
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
xxx-----]], contents = function(m) des.region({ region={5,5,5,5}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- S-shaped
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----xxx
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
|...----
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
----...|
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
xxx-----]], contents = function(m) des.region({ region={2,2,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- S-shaped, rot 1
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx--------
|
||||
xxx|......|
|
||||
xxx|......|
|
||||
----......|
|
||||
|......----
|
||||
|......|xxx
|
||||
|......|xxx
|
||||
--------xxx]], contents = function(m) des.region({ region={5,5,5,5}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Z-shaped
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----
|
||||
xxx|...|
|
||||
xxx|...|
|
||||
----...|
|
||||
|......|
|
||||
|......|
|
||||
|......|
|
||||
|...----
|
||||
|...|xxx
|
||||
|...|xxx
|
||||
-----xxx]], contents = function(m) des.region({ region={5,5,5,5}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Z-shaped, rot 1
|
||||
function()
|
||||
des.map({ map = [[
|
||||
--------xxx
|
||||
|......|xxx
|
||||
|......|xxx
|
||||
|......----
|
||||
----......|
|
||||
xxx|......|
|
||||
xxx|......|
|
||||
xxx--------]], contents = function(m) des.region({ region={2,2,2,2}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Cross
|
||||
function()
|
||||
des.map({ map = [[
|
||||
xxx-----xxx
|
||||
xxx|...|xxx
|
||||
xxx|...|xxx
|
||||
----...----
|
||||
|.........|
|
||||
|.........|
|
||||
|.........|
|
||||
----...----
|
||||
xxx|...|xxx
|
||||
xxx|...|xxx
|
||||
xxx-----xxx]], contents = function(m) des.region({ region={6,6,6,6}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
-- Four-leaf clover
|
||||
function()
|
||||
des.map({ map = [[
|
||||
-----x-----
|
||||
|...|x|...|
|
||||
|...---...|
|
||||
|.........|
|
||||
---.....---
|
||||
xx|.....|xx
|
||||
---.....---
|
||||
|.........|
|
||||
|...---...|
|
||||
|...|x|...|
|
||||
-----x-----]], contents = function(m) des.region({ region={6,6,6,6}, type="ordinary", irregular=true, prefilled=true }); end });
|
||||
end,
|
||||
|
||||
};
|
||||
|
||||
local total_frequency = 0;
|
||||
for i = 1, #themerooms do
|
||||
local t = type(themerooms[i]);
|
||||
if (t == "table") then
|
||||
total_frequency = total_frequency + themerooms[i].frequency;
|
||||
elseif (t == "function") then
|
||||
total_frequency = total_frequency + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (total_frequency == 0) then
|
||||
error("Theme rooms total_frequency == 0");
|
||||
end
|
||||
|
||||
function themerooms_generate()
|
||||
local pick = nh.rn2(total_frequency);
|
||||
for i = 1, #themerooms do
|
||||
local t = type(themerooms[i]);
|
||||
if (t == "table") then
|
||||
pick = pick - themerooms[i].frequency;
|
||||
if (pick < 0) then
|
||||
themerooms[i].contents();
|
||||
return;
|
||||
end
|
||||
elseif (t == "function") then
|
||||
pick = pick - 1;
|
||||
if (pick < 0) then
|
||||
themerooms[i]();
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -271,6 +271,7 @@ include more skill information in ^X output when dual-wielding
|
||||
item-using monsters will zap wand of undead turning at corpse-wielding hero
|
||||
when the corpse is harmful
|
||||
boiling a pool or fountain now creates a temporary cloud of steam
|
||||
random themed rooms in the dungeons of doom
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -1136,6 +1136,8 @@ struct instance_globals {
|
||||
struct sp_coder *coder;
|
||||
xchar xstart, ystart;
|
||||
xchar xsize, ysize;
|
||||
boolean in_mk_themerooms;
|
||||
boolean themeroom_failed;
|
||||
|
||||
/* spells.c */
|
||||
int spl_sortmode; /* index into spl_sortchoices[] */
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct dungeon { /* basic dungeon identifier */
|
||||
char dname[24]; /* name of the dungeon (eg. "Hell") */
|
||||
char proto[15]; /* name of prototype file (eg. "tower") */
|
||||
char fill_lvl[15]; /* name of "fill" level protype file */
|
||||
char themerms[15]; /* lua file name containing themed rooms */
|
||||
char boneid; /* character to id dungeon in bones files */
|
||||
d_flags flags; /* dungeon flags */
|
||||
xchar entry_lev; /* entry level */
|
||||
@@ -64,6 +65,7 @@ typedef struct dungeon { /* basic dungeon identifier */
|
||||
xchar dunlev_ureached; /* how deep you have been in this dungeon */
|
||||
int ledger_start, /* the starting depth in "real" terms */
|
||||
depth_start; /* the starting depth in "logical" terms */
|
||||
lua_State *themelua; /* themerms compiled lua */
|
||||
} dungeon;
|
||||
|
||||
/*
|
||||
|
||||
@@ -1446,6 +1446,7 @@ E int FDECL(somex, (struct mkroom *));
|
||||
E int FDECL(somey, (struct mkroom *));
|
||||
E boolean FDECL(inside_room, (struct mkroom *, XCHAR_P, XCHAR_P));
|
||||
E boolean FDECL(somexy, (struct mkroom *, coord *));
|
||||
E boolean FDECL(somexyspace, (struct mkroom *, coord *));
|
||||
E void FDECL(mkundead, (coord *, BOOLEAN_P, int));
|
||||
E struct permonst *NDECL(courtmon);
|
||||
E void FDECL(save_rooms, (NHFILE *));
|
||||
@@ -2478,6 +2479,7 @@ E void FDECL(sysopt_seduce_set, (int));
|
||||
|
||||
/* ### sp_lev.c ### */
|
||||
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
|
||||
E void NDECL(create_des_coder);
|
||||
E struct mapfragment *FDECL(mapfrag_fromstr, (char *));
|
||||
E void FDECL(mapfrag_free, (struct mapfragment **));
|
||||
E schar FDECL(mapfrag_get, (struct mapfragment *, int, int));
|
||||
|
||||
@@ -19,6 +19,7 @@ struct mkroom {
|
||||
schar fdoor; /* index for the first door of the room */
|
||||
schar nsubrooms; /* number of subrooms */
|
||||
boolean irregular; /* true if room is non-rectangular */
|
||||
schar roomnoidx;
|
||||
struct mkroom *sbrooms[MAX_SUBROOMS]; /* Subrooms pointers */
|
||||
struct monst *resident; /* priest/shopkeeper/guard for this room */
|
||||
};
|
||||
@@ -48,6 +49,7 @@ struct shclass {
|
||||
/* values for rtype in the room definition structure */
|
||||
enum roomtype_types {
|
||||
OROOM = 0, /* ordinary room */
|
||||
THEMEROOM = 1, /* like OROOM, but never converted to special room */
|
||||
COURT = 2, /* contains a throne */
|
||||
SWAMP = 3, /* contains pools */
|
||||
VAULT = 4, /* detached room usually reached via teleport trap */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 16
|
||||
#define EDITLEVEL 17
|
||||
|
||||
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020"
|
||||
#define COPYRIGHT_BANNER_B \
|
||||
|
||||
@@ -638,6 +638,8 @@ const struct instance_globals g_init = {
|
||||
UNDEFINED_VALUE, /* ystart */
|
||||
UNDEFINED_VALUE, /* xsize */
|
||||
UNDEFINED_VALUE, /* ysize */
|
||||
FALSE, /* in_mk_themerooms */
|
||||
FALSE, /* themeroom_failed */
|
||||
|
||||
/* spells.c */
|
||||
0, /* spl_sortmode */
|
||||
|
||||
@@ -842,6 +842,7 @@ init_dungeons()
|
||||
i = 0;
|
||||
while (lua_next(L, tidx) != 0) {
|
||||
char *dgn_name, *dgn_bonetag, *dgn_protoname, *dgn_fill;
|
||||
char *dgn_themerms;
|
||||
int dgn_base, dgn_range, dgn_align, dgn_entry, dgn_chance, dgn_flags;
|
||||
|
||||
if (!lua_istable(L, -1))
|
||||
@@ -858,6 +859,7 @@ init_dungeons()
|
||||
dgn_chance = get_table_int_opt(L, "chance", 100);
|
||||
dgn_flags = get_dgn_flags(L);
|
||||
dgn_fill = get_table_str_opt(L, "lvlfill", emptystr);
|
||||
dgn_themerms = get_table_str_opt(L, "themerooms", emptystr);
|
||||
|
||||
debugpline4("DUNGEON[%i]: %s, base=(%i,%i)",
|
||||
i, dgn_name, dgn_base, dgn_range);
|
||||
@@ -870,6 +872,7 @@ init_dungeons()
|
||||
free((genericptr_t) dgn_bonetag);
|
||||
free((genericptr_t) dgn_protoname);
|
||||
free((genericptr_t) dgn_fill);
|
||||
free((genericptr_t) dgn_themerms);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1023,10 +1026,13 @@ init_dungeons()
|
||||
Strcpy(g.dungeons[i].fill_lvl, dgn_fill); /* FIXME: fill_lvl len */
|
||||
Strcpy(g.dungeons[i].dname, dgn_name); /* FIXME: dname length */
|
||||
Strcpy(g.dungeons[i].proto, dgn_protoname); /* FIXME: proto length */
|
||||
Strcpy(g.dungeons[i].themerms, dgn_themerms); /* FIXME: length */
|
||||
g.dungeons[i].themelua = (lua_State *) 0;
|
||||
g.dungeons[i].boneid = *dgn_bonetag ? *dgn_bonetag : 0;
|
||||
free((genericptr) dgn_fill);
|
||||
/* free((genericptr) dgn_protoname); -- stored in pd.tmpdungeon[] */
|
||||
free((genericptr) dgn_bonetag);
|
||||
free((genericptr) dgn_themerms);
|
||||
|
||||
if (dgn_range)
|
||||
g.dungeons[i].num_dunlevs = (xchar) rn1(dgn_range, dgn_base);
|
||||
|
||||
213
src/mklev.c
213
src/mklev.c
@@ -9,6 +9,9 @@
|
||||
/* croom->lx etc are schar (width <= int), so % arith ensures that */
|
||||
/* conversion of result to int is reasonable */
|
||||
|
||||
static boolean FDECL(generate_stairs_room_good, (struct mkroom *, int));
|
||||
static struct mkroom *NDECL(generate_stairs_find_room);
|
||||
static void NDECL(generate_stairs);
|
||||
static void FDECL(mkfount, (int, struct mkroom *));
|
||||
static boolean FDECL(find_okay_roompos, (struct mkroom *, coord *));
|
||||
static void FDECL(mksink, (struct mkroom *));
|
||||
@@ -94,9 +97,14 @@ xchar xl, yl, xh, yh;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort rooms on the level so they're ordered from left to right on the map.
|
||||
makecorridors() by default links rooms N and N+1 */
|
||||
void
|
||||
sort_rooms()
|
||||
{
|
||||
int i, x, y;
|
||||
int ri[MAXNROFROOMS+1];
|
||||
|
||||
#if defined(SYSV) || defined(DGUX)
|
||||
#define CAST_nroom (unsigned) g.nroom
|
||||
#else
|
||||
@@ -104,6 +112,17 @@ sort_rooms()
|
||||
#endif
|
||||
qsort((genericptr_t) g.rooms, CAST_nroom, sizeof (struct mkroom), do_comp);
|
||||
#undef CAST_nroom
|
||||
|
||||
/* Update the roomnos on the map */
|
||||
for (i = 0; i < g.nroom; i++)
|
||||
ri[g.rooms[i].roomnoidx] = i;
|
||||
|
||||
for (x = 1; x < COLNO; x++)
|
||||
for (y = 0; y < ROWNO; y++) {
|
||||
int rno = levl[x][y].roomno;
|
||||
if (rno >= ROOMOFFSET && rno < MAXNROFROOMS+1)
|
||||
levl[x][y].roomno = ri[rno - ROOMOFFSET] + ROOMOFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -140,6 +159,7 @@ boolean is_room;
|
||||
} else
|
||||
croom->rlit = 0;
|
||||
|
||||
croom->roomnoidx = (croom - g.rooms);
|
||||
croom->lx = lowx;
|
||||
croom->hx = hix;
|
||||
croom->ly = lowy;
|
||||
@@ -156,6 +176,7 @@ boolean is_room;
|
||||
croom->nsubrooms = 0;
|
||||
croom->sbrooms[0] = (struct mkroom *) 0;
|
||||
if (!special) {
|
||||
croom->needjoining = TRUE;
|
||||
for (x = lowx - 1; x <= hix + 1; x++)
|
||||
for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
|
||||
levl[x][y].typ = HWALL;
|
||||
@@ -222,6 +243,27 @@ static void
|
||||
makerooms()
|
||||
{
|
||||
boolean tried_vault = FALSE;
|
||||
int themeroom_tries = 0;
|
||||
boolean dothemes = (g.dungeons[u.uz.dnum].themelua != NULL);
|
||||
char *fname = g.dungeons[u.uz.dnum].themerms;
|
||||
|
||||
if (*fname && !g.dungeons[u.uz.dnum].themelua) {
|
||||
g.dungeons[u.uz.dnum].themelua = nhl_init();
|
||||
if (g.dungeons[u.uz.dnum].themelua) {
|
||||
if (!nhl_loadlua(g.dungeons[u.uz.dnum].themelua, fname)) {
|
||||
/* loading lua failed, don't use themed rooms */
|
||||
g.dungeons[u.uz.dnum].themerms[0] = '\0';
|
||||
lua_close(g.dungeons[u.uz.dnum].themelua);
|
||||
g.dungeons[u.uz.dnum].themelua = NULL;
|
||||
} else {
|
||||
dothemes = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dothemes) {
|
||||
create_des_coder();
|
||||
}
|
||||
|
||||
/* make rooms until satisfied */
|
||||
/* rnd_rect() will returns 0 if no more rects are available... */
|
||||
@@ -233,10 +275,26 @@ makerooms()
|
||||
g.vault_y = g.rooms[g.nroom].ly;
|
||||
g.rooms[g.nroom].hx = -1;
|
||||
}
|
||||
} else if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
|
||||
return;
|
||||
} else {
|
||||
if (dothemes) {
|
||||
g.in_mk_themerooms = TRUE;
|
||||
g.themeroom_failed = FALSE;
|
||||
lua_getglobal(g.dungeons[u.uz.dnum].themelua, "themerooms_generate");
|
||||
lua_call(g.dungeons[u.uz.dnum].themelua, 0, 0);
|
||||
g.in_mk_themerooms = FALSE;
|
||||
if (g.themeroom_failed && ((themeroom_tries++ > 10) || (g.nroom >= (MAXNROFROOMS / 6))))
|
||||
break;
|
||||
} else {
|
||||
if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
|
||||
break;;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dothemes) {
|
||||
wallification(1, 0, COLNO - 1, ROWNO - 1);
|
||||
free(g.coder);
|
||||
g.coder = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -252,6 +310,9 @@ boolean nxcor;
|
||||
croom = &g.rooms[a];
|
||||
troom = &g.rooms[b];
|
||||
|
||||
if (!croom->needjoining || !troom->needjoining)
|
||||
return;
|
||||
|
||||
/* find positions cc and tt for doors in croom and troom
|
||||
and direction for a corridor between them */
|
||||
|
||||
@@ -711,25 +772,7 @@ makelevel()
|
||||
makerooms();
|
||||
sort_rooms();
|
||||
|
||||
/* construct stairs (up and down in different rooms if possible) */
|
||||
croom = &g.rooms[rn2(g.nroom)];
|
||||
if (!Is_botlevel(&u.uz))
|
||||
mkstairs(somex(croom), somey(croom), 0, croom); /* down */
|
||||
if (g.nroom > 1) {
|
||||
troom = croom;
|
||||
croom = &g.rooms[rn2(g.nroom - 1)];
|
||||
if (croom == troom)
|
||||
croom++;
|
||||
}
|
||||
|
||||
if (u.uz.dlevel != 1) {
|
||||
xchar sx, sy;
|
||||
do {
|
||||
sx = somex(croom);
|
||||
sy = somey(croom);
|
||||
} while (occupied(sx, sy));
|
||||
mkstairs(sx, sy, 1, croom); /* up */
|
||||
}
|
||||
generate_stairs(); /* up and down stairs */
|
||||
|
||||
branchp = Is_branchlev(&u.uz); /* possible dungeon branch */
|
||||
room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed
|
||||
@@ -807,7 +850,10 @@ makelevel()
|
||||
/* for each room: put things inside */
|
||||
for (croom = g.rooms; croom->hx > 0; croom++) {
|
||||
int trycnt = 0;
|
||||
if (croom->rtype != OROOM)
|
||||
coord pos;
|
||||
if (croom->rtype != OROOM && croom->rtype != THEMEROOM)
|
||||
continue;
|
||||
if (!croom->needfill)
|
||||
continue;
|
||||
|
||||
/* put a sleeping monster inside */
|
||||
@@ -816,13 +862,11 @@ makelevel()
|
||||
while a monster was on the stairs. Conclusion:
|
||||
we have to check for monsters on the stairs anyway. */
|
||||
|
||||
if (u.uhave.amulet || !rn2(3)) {
|
||||
x = somex(croom);
|
||||
y = somey(croom);
|
||||
tmonst = makemon((struct permonst *) 0, x, y, MM_NOGRP);
|
||||
if ((u.uhave.amulet || !rn2(3)) && somexyspace(croom, &pos)) {
|
||||
tmonst = makemon((struct permonst *) 0, pos.x, pos.y, MM_NOGRP);
|
||||
if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER]
|
||||
&& !occupied(x, y))
|
||||
(void) maketrap(x, y, WEB);
|
||||
&& !occupied(pos.x, pos.y))
|
||||
(void) maketrap(pos.x, pos.y, WEB);
|
||||
}
|
||||
/* put traps and mimics inside */
|
||||
x = 8 - (level_difficulty() / 6);
|
||||
@@ -830,8 +874,8 @@ makelevel()
|
||||
x = 2;
|
||||
while (!rn2(x) && (++trycnt < 1000))
|
||||
mktrap(0, 0, croom, (coord *) 0);
|
||||
if (!rn2(3))
|
||||
(void) mkgold(0L, somex(croom), somey(croom));
|
||||
if (!rn2(3) && somexyspace(croom, &pos))
|
||||
(void) mkgold(0L, pos.x, pos.y);
|
||||
if (Is_rogue_level(&u.uz))
|
||||
goto skip_nonrogue;
|
||||
if (!rn2(10))
|
||||
@@ -847,18 +891,18 @@ makelevel()
|
||||
mkgrave(croom);
|
||||
|
||||
/* put statues inside */
|
||||
if (!rn2(20))
|
||||
if (!rn2(20) && somexyspace(croom, &pos))
|
||||
(void) mkcorpstat(STATUE, (struct monst *) 0,
|
||||
(struct permonst *) 0, somex(croom),
|
||||
somey(croom), CORPSTAT_INIT);
|
||||
(struct permonst *) 0, pos.x,
|
||||
pos.y, CORPSTAT_INIT);
|
||||
/* put box/chest inside;
|
||||
* 40% chance for at least 1 box, regardless of number
|
||||
* of rooms; about 5 - 7.5% for 2 boxes, least likely
|
||||
* when few rooms; chance for 3 or more is negligible.
|
||||
*/
|
||||
if (!rn2(g.nroom * 5 / 2))
|
||||
(void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, somex(croom),
|
||||
somey(croom), TRUE, FALSE);
|
||||
if (!rn2(g.nroom * 5 / 2) && somexyspace(croom, &pos))
|
||||
(void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
|
||||
pos.x, pos.y, TRUE, FALSE);
|
||||
|
||||
/* maybe make some graffiti */
|
||||
if (!rn2(27 + 3 * abs(depth(&u.uz)))) {
|
||||
@@ -867,8 +911,9 @@ makelevel()
|
||||
|
||||
if (mesg) {
|
||||
do {
|
||||
x = somex(croom);
|
||||
y = somey(croom);
|
||||
somexyspace(croom, &pos);
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
} while (levl[x][y].typ != ROOM && !rn2(40));
|
||||
if (!(IS_POOL(levl[x][y].typ)
|
||||
|| IS_FURNITURE(levl[x][y].typ)))
|
||||
@@ -877,15 +922,15 @@ makelevel()
|
||||
}
|
||||
|
||||
skip_nonrogue:
|
||||
if (!rn2(3)) {
|
||||
(void) mkobj_at(0, somex(croom), somey(croom), TRUE);
|
||||
if (!rn2(3) && somexyspace(croom, &pos)) {
|
||||
(void) mkobj_at(0, pos.x, pos.y, TRUE);
|
||||
tryct = 0;
|
||||
while (!rn2(5)) {
|
||||
if (++tryct > 100) {
|
||||
impossible("tryct overflow4");
|
||||
break;
|
||||
}
|
||||
(void) mkobj_at(0, somex(croom), somey(croom), TRUE);
|
||||
(void) mkobj_at(0, pos.x, pos.y, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1124,7 +1169,7 @@ coord *mp;
|
||||
do
|
||||
croom = &g.rooms[rn2(g.nroom)];
|
||||
while ((croom == g.dnstairs_room || croom == g.upstairs_room
|
||||
|| croom->rtype != OROOM) && (++tryct < 100));
|
||||
|| (croom->rtype != OROOM && croom->rtype != THEMEROOM)) && (++tryct < 100));
|
||||
} else
|
||||
croom = &g.rooms[rn2(g.nroom)];
|
||||
|
||||
@@ -1133,6 +1178,7 @@ coord *mp;
|
||||
impossible("Can't place branch!");
|
||||
} while ((occupied(mp->x, mp->y)
|
||||
|| (levl[mp->x][mp->y].typ != CORR
|
||||
&& levl[mp->x][mp->y].typ != ICE
|
||||
&& levl[mp->x][mp->y].typ != ROOM)) && (++cnt < 1000));
|
||||
}
|
||||
return croom;
|
||||
@@ -1250,6 +1296,10 @@ xchar x, y;
|
||||
boolean near_door = bydoor(x, y);
|
||||
|
||||
return ((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL)
|
||||
&& (isok(x-1,y) && !IS_ROCK(levl[x-1][y].typ)
|
||||
|| isok(x+1,y) && !IS_ROCK(levl[x+1][y].typ)
|
||||
|| isok(x,y-1) && !IS_ROCK(levl[x][y-1].typ)
|
||||
|| isok(x,y+1) && !IS_ROCK(levl[x][y+1].typ))
|
||||
&& g.doorindex < DOORMAX && !near_door);
|
||||
}
|
||||
|
||||
@@ -1574,6 +1624,83 @@ struct mkroom *croom;
|
||||
levl[x][y].ladder = up ? LA_UP : LA_DOWN;
|
||||
}
|
||||
|
||||
/* is room a good one to generate up or down stairs in? */
|
||||
/* phase values, smaller allows for more relaxed criteria:
|
||||
2 == no relaxed criteria
|
||||
1 == allow a themed room
|
||||
0 == allow same room as existing up/downstairs
|
||||
-1 == allow an unjoined room
|
||||
*/
|
||||
static boolean
|
||||
generate_stairs_room_good(croom, phase)
|
||||
struct mkroom *croom;
|
||||
int phase;
|
||||
{
|
||||
return (croom && (croom->needjoining || (phase < 0))
|
||||
&& ((croom != g.dnstairs_room && croom != g.upstairs_room)
|
||||
|| phase < 1)
|
||||
&& (croom->rtype == OROOM
|
||||
|| ((phase < 2) || croom->rtype == THEMEROOM)));
|
||||
}
|
||||
|
||||
/* find a good room to generate an up or down stairs in */
|
||||
static struct mkroom *
|
||||
generate_stairs_find_room()
|
||||
{
|
||||
struct mkroom *croom;
|
||||
int i, phase, tryct = 0;
|
||||
|
||||
if (!g.nroom)
|
||||
return (struct mkroom *) 0;
|
||||
|
||||
for (phase = 2; phase > -1; phase--) {
|
||||
do {
|
||||
croom = &g.rooms[rn2(g.nroom)];
|
||||
} while (!generate_stairs_room_good(croom, phase) && (tryct++ < 50));
|
||||
if (tryct < 50)
|
||||
return croom;
|
||||
}
|
||||
|
||||
for (phase = 2; phase > -2; phase--) {
|
||||
for (i = 0; i < g.nroom; i++) {
|
||||
croom = &g.rooms[i];
|
||||
if (generate_stairs_room_good(croom, phase))
|
||||
return croom;
|
||||
}
|
||||
}
|
||||
|
||||
croom = &g.rooms[rn2(g.nroom)];
|
||||
return croom;
|
||||
}
|
||||
|
||||
/* construct stairs up and down within the same branch,
|
||||
up and down in different rooms if possible */
|
||||
static void
|
||||
generate_stairs()
|
||||
{
|
||||
struct mkroom *croom = generate_stairs_find_room();
|
||||
coord pos;
|
||||
|
||||
if (!Is_botlevel(&u.uz)) {
|
||||
if (!somexyspace(croom, &pos)) {
|
||||
pos.x = somex(croom);
|
||||
pos.y = somey(croom);
|
||||
}
|
||||
mkstairs(pos.x, pos.y, 0, croom); /* down */
|
||||
}
|
||||
|
||||
if (g.nroom > 1)
|
||||
croom = generate_stairs_find_room();
|
||||
|
||||
if (u.uz.dlevel != 1) {
|
||||
if (!somexyspace(croom, &pos)) {
|
||||
pos.x = somex(croom);
|
||||
pos.y = somey(croom);
|
||||
}
|
||||
mkstairs(pos.x, pos.y, 1, croom); /* up */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mkfount(mazeflag, croom)
|
||||
int mazeflag;
|
||||
|
||||
@@ -996,6 +996,7 @@ const char *s;
|
||||
if (*protofile) {
|
||||
check_ransacked(protofile);
|
||||
Strcat(protofile, LEV_EXT);
|
||||
g.in_mk_themerooms = FALSE;
|
||||
if (load_special(protofile)) {
|
||||
/* some levels can end up with monsters
|
||||
on dead mon list, including light source monsters */
|
||||
|
||||
17
src/mkroom.c
17
src/mkroom.c
@@ -713,6 +713,23 @@ coord *c;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
boolean
|
||||
somexyspace(croom, c)
|
||||
struct mkroom *croom;
|
||||
coord *c;
|
||||
{
|
||||
int trycnt = 0;
|
||||
boolean okay;
|
||||
|
||||
do {
|
||||
okay = somexy(croom, c) && isok(c->x, c->y) && !occupied(c->x, c->y)
|
||||
&& (levl[c->x][c->y].typ == ROOM
|
||||
|| levl[c->x][c->y].typ == CORR
|
||||
|| levl[c->x][c->y].typ == ICE);
|
||||
} while (trycnt++ < 100 && !okay);
|
||||
return okay;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a special room given its type (zoo, court, etc...)
|
||||
* Special values :
|
||||
|
||||
@@ -1079,11 +1079,17 @@ free_dungeons()
|
||||
{
|
||||
#ifdef FREE_ALL_MEMORY
|
||||
NHFILE tnhfp;
|
||||
int i;
|
||||
|
||||
zero_nhfile(&tnhfp); /* also sets fd to -1 */
|
||||
tnhfp.mode = FREEING;
|
||||
savelevchn(&tnhfp);
|
||||
save_dungeon(&tnhfp, FALSE, TRUE);
|
||||
for (i = 0; i < g.n_dgns; i++)
|
||||
if (g.dungeons[i].themelua) {
|
||||
lua_close(g.dungeons[i].themelua);
|
||||
g.dungeons[i].themelua = (lua_State *) 0;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
107
src/sp_lev.c
107
src/sp_lev.c
@@ -23,7 +23,6 @@ typedef void FDECL((*select_iter_func), (int, int, genericptr));
|
||||
|
||||
extern void FDECL(mkmap, (lev_init *));
|
||||
|
||||
static void NDECL(create_des_coder);
|
||||
static void NDECL(solidify_map);
|
||||
static void FDECL(lvlfill_maze_grid, (int, int, int, int, SCHAR_P));
|
||||
static void FDECL(lvlfill_solid, (SCHAR_P, SCHAR_P));
|
||||
@@ -1311,6 +1310,10 @@ boolean vault;
|
||||
register int x, y, hix = *lowx + *ddx, hiy = *lowy + *ddy;
|
||||
register struct rm *lev;
|
||||
int xlim, ylim, ymax;
|
||||
xchar s_lowx, s_ddx, s_lowy, s_ddy;
|
||||
|
||||
s_lowx = *lowx; s_ddx = *ddx;
|
||||
s_lowy = *lowy; s_ddy = *ddy;
|
||||
|
||||
xlim = XLIM + (vault ? 1 : 0);
|
||||
ylim = YLIM + (vault ? 1 : 0);
|
||||
@@ -1327,6 +1330,10 @@ boolean vault;
|
||||
if (hix <= *lowx || hiy <= *lowy)
|
||||
return FALSE;
|
||||
|
||||
if (g.in_mk_themerooms && (s_lowx != *lowx) && (s_ddx != *ddx)
|
||||
&& (s_lowy != *lowy) && (s_ddy != *ddy))
|
||||
return FALSE;
|
||||
|
||||
/* check area around room (and make room smaller if necessary) */
|
||||
for (x = *lowx - xlim; x <= hix + xlim; x++) {
|
||||
if (x <= 0 || x >= COLNO)
|
||||
@@ -1345,6 +1352,8 @@ boolean vault;
|
||||
}
|
||||
if (!rn2(3))
|
||||
return FALSE;
|
||||
if (g.in_mk_themerooms)
|
||||
return FALSE;
|
||||
if (x < *lowx)
|
||||
*lowx = x + xlim + 1;
|
||||
else
|
||||
@@ -1359,6 +1368,11 @@ boolean vault;
|
||||
}
|
||||
*ddx = hix - *lowx;
|
||||
*ddy = hiy - *lowy;
|
||||
|
||||
if (g.in_mk_themerooms && (s_lowx != *lowx) && (s_ddx != *ddx)
|
||||
&& (s_lowy != *lowy) && (s_ddy != *ddy))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1462,6 +1476,7 @@ xchar rtype, rlit;
|
||||
r2.hy = yabs + htmp;
|
||||
} else { /* Only some parameters are random */
|
||||
int rndpos = 0;
|
||||
xchar dx, dy;
|
||||
|
||||
if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
|
||||
xtmp = rnd(5);
|
||||
@@ -1518,6 +1533,12 @@ xchar rtype, rlit;
|
||||
r2.hx = xabs + wtmp + rndpos;
|
||||
r2.hy = yabs + htmp + rndpos;
|
||||
r1 = get_rect(&r2);
|
||||
dx = wtmp;
|
||||
dy = htmp;
|
||||
|
||||
if (r1 && !check_room(&xabs, &dx, &yabs, &dy, vault)) {
|
||||
r1 = 0;
|
||||
}
|
||||
}
|
||||
} while (++trycnt <= 100 && !r1);
|
||||
if (!r1) { /* creation of room failed ? */
|
||||
@@ -3703,9 +3724,8 @@ static const struct {
|
||||
const char *name;
|
||||
int type;
|
||||
} room_types[] = {
|
||||
/* for historical reasons, room types are not contiguous numbers */
|
||||
/* (type 1 is skipped) */
|
||||
{ "ordinary", OROOM },
|
||||
{ "themed", THEMEROOM },
|
||||
{ "throne", COURT },
|
||||
{ "swamp", SWAMP },
|
||||
{ "vault", VAULT },
|
||||
@@ -3764,6 +3784,9 @@ lua_State *L;
|
||||
{
|
||||
create_des_coder();
|
||||
|
||||
if (g.in_mk_themerooms && g.themeroom_failed)
|
||||
return 0;
|
||||
|
||||
lcheck_param_table(L);
|
||||
|
||||
if (g.coder->n_subroom > MAX_NESTED_ROOMS) {
|
||||
@@ -3802,7 +3825,7 @@ lua_State *L;
|
||||
tmproom.rtype = get_table_roomtype_opt(L, "type", OROOM);
|
||||
tmproom.chance = get_table_int_opt(L, "chance", 100);
|
||||
tmproom.rlit = get_table_int_opt(L, "lit", -1);
|
||||
tmproom.filled = get_table_int_opt(L, "filled", 1);
|
||||
tmproom.filled = get_table_int_opt(L, "filled", g.in_mk_themerooms ? 0 : 1);
|
||||
tmproom.joined = get_table_int_opt(L, "joined", 1);
|
||||
|
||||
if (!g.coder->failed_room[g.coder->n_subroom - 1]) {
|
||||
@@ -3822,6 +3845,8 @@ lua_State *L;
|
||||
spo_endroom(g.coder);
|
||||
return 0;
|
||||
}
|
||||
if (g.in_mk_themerooms)
|
||||
g.themeroom_failed = TRUE;
|
||||
} /* failed to create parent room, so fail this too */
|
||||
}
|
||||
g.coder->tmproomlist[g.coder->n_subroom] = (struct mkroom *) 0;
|
||||
@@ -3829,6 +3854,8 @@ lua_State *L;
|
||||
g.coder->n_subroom++;
|
||||
update_croom();
|
||||
spo_endroom(g.coder);
|
||||
if (g.in_mk_themerooms)
|
||||
g.themeroom_failed = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5628,7 +5655,7 @@ lua_State *L;
|
||||
/* for an ordinary room, `prefilled' is a flag to force
|
||||
an actual room to be created (such rooms are used to
|
||||
control placement of migrating monster arrivals) */
|
||||
room_not_needed = (rtype == OROOM && !irregular && !prefilled);
|
||||
room_not_needed = (rtype == OROOM && !irregular && !prefilled && !g.in_mk_themerooms);
|
||||
if (room_not_needed || g.nroom >= MAXNROFROOMS) {
|
||||
region tmpregion;
|
||||
if (!room_not_needed)
|
||||
@@ -5668,6 +5695,9 @@ lua_State *L;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g.in_mk_themerooms && prefilled)
|
||||
troom->needfill = 1;
|
||||
|
||||
if (!room_not_needed) {
|
||||
if (g.coder->n_subroom > 1)
|
||||
impossible("region as subroom");
|
||||
@@ -6009,9 +6039,14 @@ TODO: g.coder->croom needs to be updated
|
||||
struct mapfragment *mf;
|
||||
int argc = lua_gettop(L);
|
||||
boolean has_contents = FALSE;
|
||||
int tryct = 0;
|
||||
int ox, oy;
|
||||
|
||||
create_des_coder();
|
||||
|
||||
if (g.in_mk_themerooms && g.themeroom_failed)
|
||||
return 0;
|
||||
|
||||
if (argc == 1 && lua_type(L, 1) == LUA_TSTRING) {
|
||||
char *tmpstr = dupstr(luaL_checkstring(L, 1));
|
||||
lr = tb = CENTER;
|
||||
@@ -6040,10 +6075,34 @@ TODO: g.coder->croom needs to be updated
|
||||
return 0;
|
||||
}
|
||||
|
||||
ox = x;
|
||||
oy = y;
|
||||
redo_maploc:
|
||||
|
||||
g.xsize = mf->wid;
|
||||
g.ysize = mf->hei;
|
||||
|
||||
if (lr == -1 && tb == -1) {
|
||||
if (g.in_mk_themerooms && (ox == -1 || oy == -1)) {
|
||||
if (ox == -1) {
|
||||
if (g.coder->croom) {
|
||||
x = somex(g.coder->croom) - mf->wid;
|
||||
if (x < 1) x = 1;
|
||||
} else {
|
||||
x = 1 + rn2(COLNO - 1 - mf->wid);
|
||||
}
|
||||
}
|
||||
|
||||
if (oy == -1) {
|
||||
if (g.coder->croom) {
|
||||
y = somey(g.coder->croom) - mf->hei;
|
||||
if (y < 1) y = 1;
|
||||
} else {
|
||||
y = rn2(ROWNO - mf->wid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isok(x,y)) {
|
||||
/* x,y is given, place map starting at x,y */
|
||||
if (g.coder->croom) {
|
||||
@@ -6102,6 +6161,10 @@ TODO: g.coder->croom needs to be updated
|
||||
}
|
||||
|
||||
if (g.ystart < 0 || g.ystart + g.ysize > ROWNO) {
|
||||
if (g.in_mk_themerooms) {
|
||||
g.themeroom_failed = TRUE;
|
||||
goto skipmap;
|
||||
}
|
||||
/* try to move the start a bit */
|
||||
g.ystart += (g.ystart > 0) ? -2 : 2;
|
||||
if (g.ysize == ROWNO)
|
||||
@@ -6117,6 +6180,32 @@ TODO: g.coder->croom needs to be updated
|
||||
} else {
|
||||
xchar mptyp;
|
||||
|
||||
/* Themed rooms should never overwrite anything */
|
||||
if (g.in_mk_themerooms) {
|
||||
boolean isokp = TRUE;
|
||||
for (y = g.ystart - 1; y < min(ROWNO, g.ystart + g.ysize) + 1; y++)
|
||||
for (x = g.xstart - 1; x < min(COLNO, g.xstart + g.xsize) + 1; x++) {
|
||||
if (!isok(x, y)) {
|
||||
isokp = FALSE;
|
||||
} else if (y < g.ystart || y >= (g.ystart + g.ysize)
|
||||
|| x < g.xstart || x >= (g.xstart + g.xsize)) {
|
||||
if (levl[x][y].typ != STONE) isokp = FALSE;
|
||||
if (levl[x][y].roomno != NO_ROOM) isokp = FALSE;
|
||||
} else {
|
||||
mptyp = mapfrag_get(mf, (x - g.xstart), (y - g.ystart));
|
||||
if (mptyp >= MAX_TYPE) continue;
|
||||
if (levl[x][y].typ != STONE && levl[x][y].typ != mptyp) isokp = FALSE;
|
||||
if (levl[x][y].roomno != NO_ROOM) isokp = FALSE;
|
||||
}
|
||||
if (!isokp) {
|
||||
if ((tryct++ < 100) && ((lr == -1) || (tb == -1)))
|
||||
goto redo_maploc;
|
||||
g.themeroom_failed = TRUE;
|
||||
goto skipmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the map */
|
||||
for (y = g.ystart; y < min(ROWNO, g.ystart + g.ysize); y++)
|
||||
for (x = g.xstart; x < min(COLNO, g.xstart + g.xsize); x++) {
|
||||
@@ -6158,14 +6247,16 @@ TODO: g.coder->croom needs to be updated
|
||||
else if (splev_init_present && levl[x][y].typ == ICE)
|
||||
levl[x][y].icedpool = icedpools ? ICED_POOL : ICED_MOAT;
|
||||
}
|
||||
if (g.coder->lvl_is_joined)
|
||||
if (g.coder->lvl_is_joined && !g.in_mk_themerooms)
|
||||
remove_rooms(g.xstart, g.ystart,
|
||||
g.xstart + g.xsize, g.ystart + g.ysize);
|
||||
}
|
||||
|
||||
skipmap:
|
||||
|
||||
mapfrag_free(&mf);
|
||||
|
||||
if (has_contents) {
|
||||
if (has_contents && !(g.in_mk_themerooms && g.themeroom_failed)) {
|
||||
l_push_wid_hei_table(L, g.xsize, g.ysize);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
@@ -6290,7 +6381,7 @@ lua_State *L;
|
||||
lua_setglobal(L, "des");
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
create_des_coder()
|
||||
{
|
||||
if (!g.coder)
|
||||
|
||||
@@ -86,7 +86,7 @@ DATHELP = help hh cmdhelp keyhelp history opthelp wizhelp
|
||||
SPEC_LEVS = asmodeus.lua baalz.lua bigrm-*.lua castle.lua fakewiz?.lua \
|
||||
juiblex.lua knox.lua medusa-?.lua minend-?.lua minefill.lua \
|
||||
minetn-?.lua oracle.lua orcus.lua sanctum.lua soko?-?.lua \
|
||||
tower?.lua valley.lua wizard?.lua nhlib.lua \
|
||||
tower?.lua valley.lua wizard?.lua nhlib.lua themerms.lua \
|
||||
astral.lua air.lua earth.lua fire.lua water.lua
|
||||
QUEST_LEVS = ???-goal.lua ???-fil?.lua ???-loca.lua ???-strt.lua
|
||||
|
||||
|
||||
Reference in New Issue
Block a user