Attached Files |
crumbling_tartarus.des [^] (15,349 bytes) 2014-10-05 01:12 [Show Content] [Hide Content]###############################################################################
# Crumbling Tartarus Mockup
# by infiniplex
#
# The map gets is own file to protect the innocent from the
# horrible blackness of its LUA magic.
#
# A mockup of my proposal for how Tartarus could look with:
# 1. Layout Fortification
# -> alternating floor and wall cells along walls)
# -> dcss:brainstorm:dungeon:layouts&#fortification
# 2. Decaying Walls
# -> walls that turn into floor over time
# -> dcss:brainstorm:dungeon:branch:tartarus#ongoing_decay
# -> Uses the "&" glyph
# 3. Miasma "Walls"
# -> places where miasma clouds are used to limit movement
# -> dcss:brainstorm:dungeon:branch:tartarus#miasma
# -> Can appear on the ":" glyphs
#
# Basic layout design, fortifications and decaying walls are
# handcrafted. However, I did do the steps in order to
# accurately represent the process. I don't have good
# algorithms for the fortifications and decaying walls.
#
# Miasma clouds were generated procedurally and then stored in
# the map.
# -> This is to avoid the difficulty of translating the
# procedural code (c.300 lines) into Crawl.
#
# Map is in 4 quarters:
# Top-left: square rooms connected by straight passages
# Top-right: meandering passages with "bulges" of open area
# Bottom-left: city
# Bottom-right: layout_honeycomb
#
{{
-- Sometimes adds a miasma cloud at a position.
function add_miasma_if_feasible (data_layout, x, y, add_travel_exclusion)
local LIFESPAN_MIN = 5
local LIFESPAN_MAX = 10
--
-- We only spawn miasma on open floor cells with is_miasma set
-- -> We ignore existing clouds; this is handled somewhere
-- internally
-- -> Miasma will not spawn on player
-- -> The number of required travel exclusion is too slow
-- -> Miasma will not spawn on any monsters
-- -> The AI does not know to avoid dangerous areas
--
local you_x, you_y = you.pos()
local is_player_here = (x == you_x and y == you_y)
if (data_layout[x][y].is_miasma and not feat.is_solid(x, y) and
not dgn.mons_at(x, y) and not is_player_here) then
-- TODO: Do not spawn clouds adjacent to monsters (or player)
-- with undead or demonic holiness
-- Add a "is_vulnerable_to_holy_word" function to l_mons.cc
local lifespan = crawl.random_range(LIFESPAN_MIN, LIFESPAN_MAX)
local exclude_radius = add_travel_exclusion and 0 or -1
-- all the travel exclusions slow down the game too much
exclude_radius = -1
dgn.place_cloud(x, y, "foul pestilence", lifespan,
"", -1, "", "", "", exclude_radius)
end
end
-- Sometimes converts a piece of wall to floor and miasma cloud.
function crumble_if_feasible (data_layout, x, y)
-- it must be an uncrumbled wall that should crumble
if (data_layout[x][y].is_crumble and feat.is_solid(x, y)) then
-- we need at least existing 1 floor neighbour to avoid
-- creating a teleport trap
local open_xm = dgn.in_bounds(x - 1, y) and not feat.is_solid(x - 1, y)
local open_xp = dgn.in_bounds(x + 1, y) and not feat.is_solid(x + 1, y)
local open_ym = dgn.in_bounds(x, y - 1) and not feat.is_solid(x, y - 1)
local open_yp = dgn.in_bounds(x, y + 1) and not feat.is_solid(x, y + 1)
if (open_xm or open_xp or open_ym or open_yp) then
-- convert the wall to floor
dgn.grid(x, y, "floor")
-- add a miasma cloud and travel exclusion
add_miasma_if_feasible(data_layout, x, y, true)
end
end
end
-- make walls slowly decay all over the map
function crumble_walls_all_over (data, triggerable, triggerer, marker, ev)
if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
return
end
local gxm, gym = dgn.max_bounds()
for i = 1, 10 do
local x = crawl.random_range(1, gxm - 2)
local y = crawl.random_range(1, gym - 2)
if (dgn.in_bounds(x, y)) then
crumble_if_feasible(data.layout, x, y)
crawl.redraw_view()
end
end
end
-- make walls decay in LOS of player (faster if closer)
function crumble_walls_near_player (data, triggerable, triggerer, marker, ev)
if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
return
end
-- distance at which no crumbling happens
local CRUMBLE_DISTANCE_NONE = 9 -- LOS + 1
local CRUMBLE_CHANCE_MAX = 0.2
local you_x, you_y = you.pos()
local min_x = you_x - CRUMBLE_DISTANCE_NONE + 1
local max_x = you_x + CRUMBLE_DISTANCE_NONE - 1
local min_y = you_y - CRUMBLE_DISTANCE_NONE + 1
local max_y = you_y + CRUMBLE_DISTANCE_NONE - 1
for x = min_x, max_x do
for y = min_y, max_y do
local distance = math.sqrt((x - you_x) * (x - you_x) +
(y - you_y) * (y - you_y))
local distance_fraction = distance / CRUMBLE_DISTANCE_NONE
local crumble_chance = (1 - distance_fraction) * CRUMBLE_CHANCE_MAX
if (dgn.in_bounds(x, y) and you.see_cell(x, y) and
crawl.random_real() < crumble_chance) then
crumble_if_feasible(data.layout, x, y)
crawl.redraw_view()
end
end
end
end
-- spawn miasma clouds in LOS of the player
function spawn_miasma (data, triggerable, triggerer, marker, ev)
if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
return
end
-- maximum distance for miasma spawning
local MIASMA_DISTANCE_MAX = 8 -- LOS
local MIASMA_CHANCE = 0.2
local you_x, you_y = you.pos()
local min_x = you_x - MIASMA_DISTANCE_MAX
local max_x = you_x + MIASMA_DISTANCE_MAX
local min_y = you_y - MIASMA_DISTANCE_MAX
local max_y = you_y + MIASMA_DISTANCE_MAX
for x = min_x, max_x do
for y = min_y, max_y do
if (dgn.in_bounds(x, y) and you.see_cell(x, y) and
crawl.random_real() < MIASMA_CHANCE) then
add_miasma_if_feasible(data.layout, x, y, true)
end
end
end
end
}}
NAME: infiniplex_crumbling_tartarus
DEPTH: Tar, !Tar:$
WEIGHT: 10
ORIENT: encompass
# map must not rotate so that crumbling happens in correct places
TAGS: no_rotate no_hmirror no_vmirror
{{
local gxm, gym = dgn.max_bounds()
extend_map{width=gxm, height=gym, fill='x'}
--
-- We have to specify the map like this so we still have it after
-- calling extend_map.
--
-- Note: The coordinates will be (y, string pos) instead of (x, y).
--
local map_internal = {
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxx&x&xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxx&&&&&xxxxxxxxxxxxxxxxxxxxxxxxxxxx&x&x&x&xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxx&..&&x&xxxxxxxxxxxxxxxxxxxxxxxxx.....:.&xxxxxxxxxxxxxxxx&xxxxxxxxxx",
"xxxxxxxxxxxx&&.:.&&&&xxxxxxxxxxxxxxxxxxxxxxx.:x&&.:.:&xxxxxxxxxxxxxxx&xxxxxxxxxx",
"xxxxxxxxxxxxx&..:.:&xxxxxxxxxxx&x&x&xxxxxxx.x&xxx&.:&xxxxxxxxxxxx&x&&.&xxxxxxxxx",
"xxxxxxxxxxxx&&:..::&&xxxxxxxxx&&&&&&&xxxxx.xxxxxxx&.xxxxxxxxxxx&....:.:&&xxxxxxx",
"xxxxxxxxxxxxx&&{:.:&xxxxx&x&x&&:::::&&x&x&.&xxxxxxx.xxxxxxxxxx..x&x:...&xxxxxxxx",
"xxxxxxxxxxxxxx&&..:&&xxx&&&&&&.::..:......&xxxxxxx&:.x&x&xxxx&.&xxx&&.:{&xxxxxxx",
"xxxxxxxxxxxxxxx&:.:&xxxxx&.::::.:.:.&&x&x&xxxxxxxxx&x....x&xx.xxxxxxx&.&xxxxxxxx",
"xxxxxxxxxxxxxx&&:..&&xxx&&:.::.:{:.&&xxxxxxxxxxxxxxxxx&x&.:&.&xxxxxx&&..&xxxxxxx",
"xxxxxxxxxxxxxxx&..:.&&x&&.....::...&xxxxxxxxxxxxxxxxxxxxx&..&xxxxxxxxx&.xxxxxxxx",
"xxxxxxxxxxxxxx&:.&&:.....:&&&&..:.:&&xxxxxxxxxxxxxxxxxxx&:..:&xxxxxxx&.&xxxxxxxx",
"xxxxxxxxxxxxxxx.&&x&x&x&x&x&x&&.:.:&xxxxxxxxxxxxxxxxxxxxx&..&xxxxxxxx.xxxxxxxxxx",
"xxxxxxxxxxxxxx&.&xxxxxxxxxxxxx&&.::&&xxxxxxxxxxxxxxxxxxx&:.:.&xxxxx&.&xxxxxxxxxx",
"xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxx&:.:&xxxxx&x&x&x&xxxxxxxxx&..&..xxxx:.xxxxxxxxxxx",
"xxxxxxxxxxxxxx&.&xxxxxxxxxxxxx&&:..&&xxx&&&&&&&&&xxxxxxxxx.&x&x.x&&.:&xxxxxxxxxx",
"xxxxxxxxxxxxx&&.&&x&xxxxxxxxxxx&:.:.&&x&..:::....&xxxxxxx..xxxxx....&xxxxxxxxxxx",
"xxxxxxxxxxxx&&::.&&&&xxxxxxxxx&&.:.:....&&.:.&&&&.x&x&xx.x&xxxxx&::..&x&xxxxxxxx",
"xxxxxxxxxxxxx&&::.::&&xxxxxxxxx&&.&&x&x&x&&.&&x&x&...:..xxxxxxxxx&&:&.:&xxxxxxxx",
"xxxxxxxxxxxxxx&&.:...&&xxxxxxxxx&.&xxxxxxx&.&xxxxxx&&.{:&xxxxxxxxxx&x&.:&xxxxxxx",
"xxxxxxxxxxxxxxx&.&&:.&xxxxxxxxxxx.xxxxxxxxx.xxxxxxxxx&&.xxxxxxxxxxxxxxx.xxxxxxxx",
"xxxxxxxxxxxxxx&.&x&&.&&xxxxxxxxx&.&xxxxxxx&.&xxxxxxxx&x.&xxxxxxxxxxxxx&.&xxxxxxx",
"xxxxxxx&x&x&x&.&xxx&.&&&x&x&x&x&&.xxxxxxxxx.xxxxxxxxxxx&.xx&xxxxxxxxxxx.xxxxxxxx",
"xxxxxx&&&&&&&&.&&x&&&.......&&&&..&xxxxxxx&.&xxxxxxxxxx&x..:&xxxxxxxxx&{&&xxxxxx",
"xxxxxxx&{.:::..&xxx&x&x&x&x&..:.:&xxxxxxx&&.&&x&x&xxxxxxxx&.:&x&x&xxxx&.&xxxxxxx",
"xxxxxx&&:.....:&&xxxxxxxxxxx&&.:.&&xxxxx&&.:.&&&&&&xxxxx...:.:&...x&x&.::&xxxxxx",
"xxxxxxx&:::::.:&xxxxxxxxxxxxx&:.:&xxxxxxx&:...::::&&x&x.x&x&:..&x&....:.&xxxxxxx",
"xxxxxx&&&&&&:.:&&xxxxxxxxxxx&&.::&&xxxxx&&..:..:.:.....xxxxx&.&xxxx&x&.:&&xxxxxx",
"xxxxxxx&x&x&&.&&xxxxxxxxxxxxx&:.:.&&x&x&&.:.:.:.:.&&x&xxxxxxx.xxxxxxxx&&xxxxxxxx",
"xxxxxxxxxxxx&.&xxxxxxxxxxxxx&&:..:.........:.{::.&&xxxxxxxx&x.&xxxxxxxx&xxxxxxxx",
"xxxxxxxxxxxxx.xxxxxxx&x&x&x&&..:..&&x&x&&.:..::..&xxxxxxxxx&&..&xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxx&.&xxxxx&&::......:.::&xxxxx&&.::..::&&xxxxxx&&..::.&xxxxxxxxxxxxxxx",
"xxxxxxxxxxx&&.&&x&x&&:..&&x&&.&&.&xxxxxxx&:..::::&xxxxx&x&.:&..&xxxxxxxxxxxxxxxx",
"xxxxxxxxxx&&:.:&&&&&:.:&&xxx&.&x&.&xxxxx&&:.:&&&&&&xxx&::..&x&.xxxxxxxxxxxxxxxxx",
"xxxxxxxxx&&..:.......::&xxxxx.xxx.xxxxxxx&&.&&x&x&xxxx&:.::&xx.xxxxxxxxxxxxxxxxx",
"xxxxxxxxxx&&&&&&&&&&&&&&&xxx&.&x&.&xxxxxxx&.&xxxxxxxxxx.x&&xx.&x&&xxxxxxxxxxxxxx",
"xxxxxxxxxxx&x&x&x&x&x&x&xxx&&..&&.&&x&x&x&&.xxxxxxxxxxx.xxxx&.:&::&xxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxx&&&&&...........&.&xxxxxxxx&x.x&...&.::.:&&xxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxx&x&x&x&x&x&x&x&.&xxxxxxx&x&&.&.xxxx&......&xxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&.&xxxxxx&&...:.&&x&:.:{&&&&&xxxxxxxxx",
"xxxxxxxxxxxxxxxxx&x&x&x&x&x&x&x&x&x&x&x&x&.&xxxxxx&.:.:...:&xx&:.:.:&xxxxxxxxxxx",
"xxxxxx&&&&&&&&&c&&&&&&&&&&&&&&&&&&&&&&&&&&.&&x&&&xx&..&.&&&xx&::..:..&xxxxxxxxxx",
"xxxxxx&::::.::&cc&:.:::::::::::..:::..::..:&xxx&:&xx&.x.xxxx&:..:&::&xxxxxxxxxxx",
"xxxxxx&::..:::&c&&:.:...........:...:....::&&x&:.....&x&...xx&.&&x&&xxxxxxxxxxxx",
"xxxxxx&:::{..:&cc&.:.::&&.&&&&&&&&&&&&&&:..&xxx&.xxxx.xxxx&&xx.x&xxxx&&xxxxxxxxx",
"xxxxxx&:::.::.....:..:&&c.c&c&c&c&c&c&c&&:.&&x&:.&&x.xx&x&.:&x.xxxxx&..&&xxxxxxx",
"xxxxxx&:::.:::&cc&.:.:&cc.cccccccccccccc&.:&xxx&.&xx&...&.:.&x.x&xx&:{:&xxxxxxxx",
"xxxxxx&::::.::&c&&::.:&&c&.&&..................:.:&xxxx&...:.&.&...:.::.&xxxxxxx",
"xxxxxx&&&&&.&&&cc&::.:&cc&:..&cccccccccc&:.&xx&.:..&x&x&x&:.:...&x&.:..&xxxxxxxx",
"xxxxxxxxccc.cccc&&::.:&&c&:{:&c&c&c&c&c&&:.&&xx&:::.&xxxx.:..&.&xxx&.::&&xxxxxxx",
"xxxxxxxxx&c.c&c&&::.::&cc&..:&cc&&.&&......:&&xx&:.&xx&..&.:&x.xx&x&.&&xxxxxxxxx",
"xxxxxxxx&&&.&&&&.:::.:&&c&&&&&c&:.&..&&&&&:.:&&xx&.xxxx.xx&.&x.x&&xx.x&&xxxxxxxx",
"xxxxxxxxx&:.:...:...:.&ccccccccc.&c&c&c&c&&:.&xxx.xx&&&.&xx&xx.x&:&x.x&xxxxxxxxx",
"xxxxxxxx&&.:.&&&&&&&&&.&c&c&c&c.&ccccccccc&&.&&xx.x&.:.:.&xxx&.&..:&.xxxxxxxxxxx",
"xxxxxxxxx&.:&&c&c&c&c&.&&&&&&&&.cc&&&&&&&cc&.&xxx&{.:.:.&..&xx&.:.:.&xxxxxxxxxxx",
"xxxxxxxx&&.&&ccccccccc&..:::::.&&c&:::::&c&&......:..:&&x.x....:...&xxxxxxxxxxxx",
"xxxxxxxxx&.&cc&&&&&&c&&::..:..:&cc&:....&cc&.&xxx&.:.&xxx.xxxx&.:::&xxxxxxxxxxxx",
"xxxxxxxx&&.&&c&:...&cc&::.:..::&&c&.::::.....&&x&&&:.:&xx.xx&&:.::&xxxxxxxxxxxxx",
"xxxxxxxxx&.&cc&.&&&&c&&:.:...::&cc&&&&&&&cc&.&xxx&x&.&xxx.&xx&.&.&xxxxxxxxxxxxxx",
"xxxxxxxx&&.&&cc.cccccc&:..:.:.:&&ccccccccc&&.&&xxxx&:.......xx&x&.&&xxxxxxxxxxxx",
"xxxxxxxxx&.:&&c.c&c&c&&..::..:::&&c&c&c&c&&...:&x&xx&&xxx&x&.xxx&&x&xxxxxxxxxxxx",
"xxxxxxxx&&.::&&.&&&&&&.:::.:....:&&&&&&&&&.&&&.:&:&xxxx&xxx.xxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxx&:...........:::::{:::...........&&x&..:..&xxx&x&x.x&xxxxxxxxxxxxxxxxxx",
"xxxxxxxx&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&xxx&:.:&.....&&x.x&&xxxxxxxxxxxxxxxxx",
"xxxxxxxxx&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&xxxxx&.&x&xxx&..&.&:&xxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&{&xxxxx&x&.....&&xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&xxxxxxxxx&&:&&xxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&x&x&xxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
}
--
-- Copy the internal map into the vault map and make the
-- appropriate .des calls.
--
-- We won't use the internal map any more.
--
for x = 0, gxm - 1 do
for y = 0, gym - 1 do
-- LUA arrays and strings start at 1
local character = string.sub(map_internal[y + 1], x + 1, x + 1)
mapgrd[x][y] = character
end
end
-- Staircases are on the map to ensure that arbitrary locations can be
-- connected to non-miasma path network.
subst("c = xxx&")
nsubst("{ = 1:{ / 1:( / 1:[ / 1:< / 1:} / 1:) / 1:] / 1:> / *:.")
--
-- Record crumbling walls and miasma
-- We will later need to know which cells crumble and generate miasma for
-- Note that all walls leave miasma areas if destroyed
--
-- We make this array to simulate having extra feature types.
--
local data_layout = {}
for x = 0, gxm - 1 do
data_layout[x] = {}
for y = 0, gym - 1 do
data_layout[x][y] = {}
data_layout[x][y].is_crumble = false
data_layout[x][y].is_miasma = false
if mapgrd[x][y] == "&" then
data_layout[x][y].is_crumble = true
data_layout[x][y].is_miasma = true
elseif mapgrd[x][y] == ":" or
mapgrd[x][y] == "x" or
mapgrd[x][y] == "c" then
data_layout[x][y].is_miasma = true
end
end
end
--
-- Set up the triggerables the do the crumbling and miasma
--
local crumble_marker1 = TriggerableFunction:new (
{
func="crumble_walls_all_over",
repeated=true,
data = { layout = data_layout }
}
)
crumble_marker1:add_triggerer(DgnTriggerer:new
{ type="turn", delay_min=15, delay_max=25 } )
local crumble_marker2 = TriggerableFunction:new (
{
func="crumble_walls_near_player",
repeated=true,
data = { layout = data_layout }
}
)
crumble_marker2:add_triggerer(DgnTriggerer:new
{ type="turn", delay=10 } )
local miasma_marker = TriggerableFunction:new (
{
func="spawn_miasma",
repeated=true,
data = { layout = data_layout }
}
)
miasma_marker:add_triggerer(DgnTriggerer:new
{ type="turn", delay=10 } )
-- we just need any unique and indestructable glyphs to base these off
mapgrd[0][0] = "A"
mapgrd[0][1] = "B"
mapgrd[0][2] = "C"
lua_marker("A", crumble_marker1)
lua_marker("B", crumble_marker2)
lua_marker("C", miasma_marker)
}}
KFEAT: ABC& = x
KFEAT: : = .
MAP
ENDMAP
crumbling_tartarus.png [^] (11,974 bytes) 2014-10-05 01:13
screenshot.png [^] (224,498 bytes) 2014-10-05 01:13 |