summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-01 14:03:23 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-01 14:03:23 +0000
commite5fc908cc50565402f1ea1acc037e5b8791870c1 (patch)
tree37f4d7e47addb7e81d0e375bb030456e189fb5c8
parent6384f9c708cf79f471df00d1e0cfa3f2c1bf4172 (diff)
downloadcrawl-ref-e5fc908cc50565402f1ea1acc037e5b8791870c1.tar.gz
crawl-ref-e5fc908cc50565402f1ea1acc037e5b8791870c1.zip
Fix .des timer messaging to be easier to customise, applied timer to sewer portals.
Fix typo in monspeak.txt (slinkies). Fixed hippogriff plural. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7709 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/clua.cc11
-rw-r--r--crawl-ref/source/dat/bazaar.des11
-rw-r--r--crawl-ref/source/dat/clua/lm_pdesc.lua12
-rw-r--r--crawl-ref/source/dat/clua/lm_timed.lua2
-rw-r--r--crawl-ref/source/dat/clua/lm_tmsg.lua191
-rw-r--r--crawl-ref/source/dat/clua/util.lua51
-rw-r--r--crawl-ref/source/dat/clua/ziggurat.lua8
-rw-r--r--crawl-ref/source/dat/database/monspeak.txt2
-rw-r--r--crawl-ref/source/dat/lab.des13
-rw-r--r--crawl-ref/source/dat/sewer.des39
-rw-r--r--crawl-ref/source/directn.cc16
-rw-r--r--crawl-ref/source/directn.h5
-rw-r--r--crawl-ref/source/libutil.cc4
13 files changed, 262 insertions, 103 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 84b164d97b..5273907367 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -2149,6 +2149,16 @@ static int crawl_split(lua_State *ls)
return (1);
}
+static int _crawl_grammar(lua_State *ls)
+{
+ description_level_type ndesc = DESC_PLAIN;
+ if (lua_isstring(ls, 2))
+ ndesc = description_type_by_name(lua_tostring(ls, 2));
+ PLUARET(string,
+ thing_do_grammar(ndesc, false,
+ false, luaL_checkstring(ls, 1)).c_str());
+}
+
static int crawl_article_a(lua_State *ls)
{
const char *s = luaL_checkstring(ls, 1);
@@ -2296,6 +2306,7 @@ static const struct luaL_reg crawl_lib[] =
{ "message_filter", crawl_message_filter },
{ "trim", crawl_trim },
{ "split", crawl_split },
+ { "grammar", _crawl_grammar },
{ "article_a", crawl_article_a },
{ "game_started", crawl_game_started },
{ "err_trace", crawl_err_trace },
diff --git a/crawl-ref/source/dat/bazaar.des b/crawl-ref/source/dat/bazaar.des
index b63caea014..a2a5ca73b5 100644
--- a/crawl-ref/source/dat/bazaar.des
+++ b/crawl-ref/source/dat/bazaar.des
@@ -11,7 +11,16 @@
lua {{
function bazaar_portal()
- local messager = bell_clock_msg { initmsg="You hear coins being counted." }
+ local messager =
+ timed_msg {
+ initmsg = { "You hear coins being counted.",
+ "An interdimensional caravan has stopped on this level "
+ .. "and set up a bazaar. Hurry and find its entrance before "
+ .. "they move on!" },
+ finalmsg = "You hear the last, dying notes of the bell.",
+ verb = 'tolling',
+ noisemaker = 'a massive bell'
+ }
local blow = 200 + 30*(40 - you.absdepth()) + crawl.random2(200)
local bhigh = blow + crawl.random2(blow) + 100
if not crawl.one_chance_in(6) then
diff --git a/crawl-ref/source/dat/clua/lm_pdesc.lua b/crawl-ref/source/dat/clua/lm_pdesc.lua
index f2e5cff9b2..32ae8e49a8 100644
--- a/crawl-ref/source/dat/clua/lm_pdesc.lua
+++ b/crawl-ref/source/dat/clua/lm_pdesc.lua
@@ -24,12 +24,20 @@ function PortalDescriptor:read(marker, th)
return self
end
+function PortalDescriptor:unmangle(x)
+ if x and type(x) == 'function' then
+ return x(self)
+ else
+ return x
+ end
+end
+
function PortalDescriptor:feature_description(marker)
- return self.props.desc
+ return self:unmangle(self.props.desc)
end
function PortalDescriptor:property(marker, pname)
- return self.props and self.props[pname] or ''
+ return self:unmangle(self.props and self.props[pname] or '')
end
function portal_desc(props)
diff --git a/crawl-ref/source/dat/clua/lm_timed.lua b/crawl-ref/source/dat/clua/lm_timed.lua
index a70ec69156..c12ec8157f 100644
--- a/crawl-ref/source/dat/clua/lm_timed.lua
+++ b/crawl-ref/source/dat/clua/lm_timed.lua
@@ -108,4 +108,4 @@ end
function timed_marker(pars)
return TimedMarker:new(pars)
-end
+end \ No newline at end of file
diff --git a/crawl-ref/source/dat/clua/lm_tmsg.lua b/crawl-ref/source/dat/clua/lm_tmsg.lua
index 1939e39bc1..564ced9a6b 100644
--- a/crawl-ref/source/dat/clua/lm_tmsg.lua
+++ b/crawl-ref/source/dat/clua/lm_tmsg.lua
@@ -6,37 +6,37 @@
TimedMessaging = { }
TimedMessaging.__index = TimedMessaging
-function TimedMessaging._new()
- local m = { }
- setmetatable(m, TimedMessaging)
- return m
-end
+function TimedMessaging:new(m, nocheck)
+ m = m or { }
+ setmetatable(m, self)
+ self.__index = self
-function TimedMessaging.new(pars)
- pars = pars or { }
- local m = TimedMessaging._new()
- m.noisemaker = pars.noisemaker
- m.verb = pars.verb
- m.finalmsg = pars.finalmsg
- m.ranges = pars.ranges
- m.initmsg = pars.initmsg or ''
- return m
-end
+ if not nocheck then
+ if not m.messages then
+ assert(m.noisemaker, "No noisemaker specified")
+ assert(m.verb, "No verb specified")
+ end
-function TimedMessaging:init(tmarker, cm, verbose)
- local lab = dgn.grid(cm:pos()) == dgn.feature_number('enter_labyrinth')
- if not self.noisemaker then
- self.noisemaker = lab and "an ancient clock" or "a massive bell"
+ if m.visible and not m.messages then
+ error("No messages set for timer messager")
+ end
end
- self.verb = self.verb or (lab and 'ticking' or 'tolling')
+ return m
+end
- if not self.finalmsg then
- self.finalmsg = lab and "last, dying ticks of the clock"
- or "last, dying notes of the bell"
+function TimedMessaging:channel()
+ if not self.sound_channel then
+ self.sound_channel =
+ crawl.msgch_num(self.visible and 'default' or 'sound')
end
+ return self.sound_channel
+end
+
+function TimedMessaging:init(tmarker, cm, verbose)
+ self.entity = tmarker.props.entity or tmarker.props.desc
- if not self.ranges then
+ if not self.ranges and not self.visible then
self.ranges = { { 5000, 'stately ' }, { 4000, '' },
{ 2500, 'brisk ' }, { 1500, 'urgent ' },
{ 0, 'frantic ' } }
@@ -47,33 +47,73 @@ function TimedMessaging:init(tmarker, cm, verbose)
self.check = 50
end
- if verbose and #self.initmsg > 0 and you.hear_pos(cm:pos()) then
- crawl.mpr(self.initmsg, "sound")
- if lab then
- crawl.mpr("Behold! There is an entrance to a minotaur's labyrinth on this level. Find the entrance quickly before it seals the gate!",
- "sound")
- else
- crawl.mpr("An interdimensional caravan has stopped on this level and set up a bazaar. Hurry and find its entrance before they move on!", "sound")
+ if verbose and self.initmsg then
+ self:emit_message(cm, self.initmsg)
+ end
+end
+
+function TimedMessaging:perceptible(cm)
+ if not cm then
+ return true
+ end
+
+ if self.visible then
+ return you.see_grid(cm:pos())
+ else
+ return you.hear_pos(cm:pos())
+ end
+end
+
+function TimedMessaging:emit_message(cm, msg)
+ if not msg or not self:perceptible(cm) then
+ return
+ end
+
+ if type(msg) == 'table' then
+ util.foreach(msg,
+ function (m)
+ self:emit_message(cm, m)
+ end)
+ else
+ if #msg < 1 then
+ return
end
+
+ crawl.mpr(util.expand_entity(self.entity, msg), self:channel())
end
end
-function TimedMessaging:say_message(dur)
- self.sound_channel = self.sound_channel or crawl.msgch_num('sound')
- if dur <= 0 then
- crawl.mpr("You hear the " .. self.finalmsg .. ".", self.sound_channel)
+function TimedMessaging:proc_ranges(ranges, dur, fn)
+ if not ranges then
return
end
- for _, chk in ipairs(self.ranges) do
+ for _, chk in ipairs(ranges) do
if dur > chk[1] then
- crawl.mpr("You hear the " .. chk[2] .. self.verb
- .. " of " .. self.noisemaker .. ".",
- self.sound_channel)
+ fn(chk, dur)
break
end
end
end
+function TimedMessaging:say_message(cm, dur)
+ if dur <= 0 then
+ self:emit_message(cm, self.finalmsg)
+ return
+ end
+
+ self:proc_ranges(self.ranges, dur,
+ function (chk)
+ self:emit_message(cm,
+ "You hear the " .. chk[2] .. self.verb
+ .. " of " .. self.noisemaker .. ".")
+ end)
+
+ self:proc_ranges(self.messages, dur,
+ function (chk)
+ self:emit_message(cm, chk[2])
+ end)
+end
+
function TimedMessaging:event(luamark, cmarker, event)
if luamark.dur < self.check or luamark.dur <= 0 then
self.check = luamark.dur - 250
@@ -81,32 +121,69 @@ function TimedMessaging:event(luamark, cmarker, event)
self.check = self.check - 250
end
- if you.hear_pos(cmarker:pos()) then
- self:say_message(luamark.dur)
+ if self:perceptible(cmarker) then
+ self:say_message(nil, luamark.dur)
end
end
end
function TimedMessaging:write(th)
- file.marshall(th, self.check)
- file.marshall(th, self.noisemaker)
- file.marshall(th, self.verb)
- file.marshall(th, self.initmsg)
- file.marshall(th, self.finalmsg)
- lmark.marshall_table(th, self.ranges)
+ lmark.marshall_table(th, self)
end
function TimedMessaging.read(th)
- local tm = TimedMessaging._new()
- tm.check = file.unmarshall_number(th)
- tm.noisemaker = file.unmarshall_string(th)
- tm.verb = file.unmarshall_string(th)
- tm.initmsg = file.unmarshall_string(th)
- tm.finalmsg = file.unmarshall_string(th)
- tm.ranges = lmark.unmarshall_table(th)
- return tm
+ return TimedMessaging:new(lmark.unmarshall_table(th))
end
-function bell_clock_msg(pars)
- return TimedMessaging.new(pars)
+function timed_msg(pars)
+ return TimedMessaging:new(pars)
end
+
+-- Accepts pairs of turns and messages used for a timer. For instance
+-- timer_interval_messages(500, 'You feel vaguely uneasy.',
+-- 250, 'You feel extremely uneasy.',
+-- 100, 'You feel a primal terror.')
+-- Will produce the first message when the timer has > 500 turns, the
+-- second message when the timer has <= 500 turns and >250 turns, and so on.
+-- Note that any given interval message will be repeated, usually every 50
+-- or 25 turns.
+function timer_interval_messages(...)
+ local breakpoints = util.partition({ ... }, 2)
+ -- Expand turn breakpoints into tenths of a turn.
+ util.foreach(breakpoints,
+ function (brk)
+ brk[1] = brk[1] * 10
+ end)
+ return breakpoints
+end
+
+-- Accepts timer messages as with timer_interval_messages, but with no
+-- explicit intervals. Instead, the total turn count is divided by the
+-- number of messages to determine intervals.
+function time_messages(total_turns, ...)
+ local messages = { ... }
+
+ local n = #messages
+
+ -- Each interval is 1.2 * the previous (lower) interval.
+ local inflate = 1.2
+
+ local function power_sum(n)
+ local sum = 1
+ for i = 1, n - 1 do
+ sum = sum + inflate ^ i
+ end
+ return sum
+ end
+
+ local base_interval = total_turns / power_sum(n)
+
+ local res = { }
+ for i = 1, n - 1 do
+ local pow = n - i
+ total_turns = total_turns - base_interval * inflate ^ pow
+ table.insert(res, { math.floor(10 * total_turns), messages[i] } )
+ end
+ table.insert(res, { 0, messages[n] })
+ return res
+end \ No newline at end of file
diff --git a/crawl-ref/source/dat/clua/util.lua b/crawl-ref/source/dat/clua/util.lua
index c9d6a9af3c..f0c16dc537 100644
--- a/crawl-ref/source/dat/clua/util.lua
+++ b/crawl-ref/source/dat/clua/util.lua
@@ -18,6 +18,28 @@ function util.identity(x)
return x
end
+-- Returns the sublist of elements at indices [istart, iend) of the
+-- supplied list.
+function util.slice(list, istart, iend)
+ if not iend then
+ iend = #list + 1
+ end
+
+ local res = { }
+ for i = istart, iend - 1 do
+ table.insert(res, list[i])
+ end
+ return res
+end
+
+function util.partition(list, slice, increment)
+ local res = { }
+ for i = 1, #list, increment or slice do
+ table.insert(res, util.slice(list, i, i + slice))
+ end
+ return res
+end
+
function util.curry(fn, ...)
local params = { ... }
if #params == 1 then
@@ -51,14 +73,7 @@ end
-- Creates a string of the elements in list joined by separator.
function util.join(sep, list)
- local res = ""
- for i, val in ipairs(list) do
- if i > 1 then
- res = res .. sep
- end
- res = res .. val
- end
- return res
+ return table.concat(list, sep)
end
-- Creates a set (a map of keys to true) from the list supplied.
@@ -70,10 +85,13 @@ function util.set(list)
return set
end
-function util.catlist(...)
- local res = { }
+-- Appends the elements in any number of additional tables to the first table.
+function util.append(table, ...)
+ local res = table
local tables = { ... }
- if #tables == 1 then
+ if #tables == 0 then
+ return res
+ elseif #tables == 1 and #res == 0 then
return tables[1]
else
for _, tab in ipairs(tables) do
@@ -85,6 +103,10 @@ function util.catlist(...)
return res
end
+function util.catlist(...)
+ return util.append({ }, ...)
+end
+
function util.cathash(...)
local res = { }
local tables = { ... }
@@ -191,6 +213,13 @@ function util.random_weighted_from(weightfn, list)
return chosen
end
+function util.expand_entity(entity, msg)
+ return string.gsub(msg, "$F%{(%w+)%}",
+ function (desc)
+ return crawl.grammar(entity, desc)
+ end)
+end
+
----------------------------------------------------------
util.Timer = { }
diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua
index 63095862a5..d9a55c2402 100644
--- a/crawl-ref/source/dat/clua/ziggurat.lua
+++ b/crawl-ref/source/dat/clua/ziggurat.lua
@@ -376,14 +376,6 @@ local function ziggurat_create_loot_at(c)
local nloot = depth
nloot = nloot + crawl.random2(math.floor(nloot * zig().portal.amount / 10000))
- local function free_space_threshold(max)
- local function is_free_space(p)
- return dgn.grid(p.x, p.y) == dgn.fnum("floor") and
- #dgn.items_at(p.x, p.y) <= max
- end
- return is_free_space
- end
-
local function find_free_space(nspaces)
local spaces = { }
local function add_spaces(p)
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index 80ae1f879d..a16ee346a0 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -2226,7 +2226,7 @@ VISUAL:@The_monster@ grows dozens of eye stalks in order to get a better look at
VISUAL:@The_monster@ splits into many small globs of multi-coloured light, then recombines.
-VISUAL:@The_monster@ breifly grows a face disturbingly similar to your own.
+VISUAL:@The_monster@ briefly grows a face disturbingly similar to your own.
@The_monster@ ululates chillingly with its many mouths.
diff --git a/crawl-ref/source/dat/lab.des b/crawl-ref/source/dat/lab.des
index 3655a3f9b4..c6e08d78d5 100644
--- a/crawl-ref/source/dat/lab.des
+++ b/crawl-ref/source/dat/lab.des
@@ -15,7 +15,18 @@ TAGS: luniq_lab chance_lab transparent trowel_portal allow_dup extra
# chance to 2.85%.
CHANCE: 50 : 285
DEPTH: 12-27
-: messager = bell_clock_msg { initmsg="You hear a distant snort." }
+{{
+ local messager =
+ timed_msg {
+ initmsg = { "You hear a distant snort.",
+ "Behold! There is an entrance to a minotaur's labyrinth "
+ .. "on this level. Find the entrance quickly before "
+ .. "the gate is sealed!" },
+ finalmsg = "You hear the last, dying ticks of the clock.",
+ verb = 'ticking',
+ noisemaker = 'an ancient clock'
+ }
+}}
MARKER: O = lua: timed_marker { \
low=400, high=600, msg=messager, floor = 'stone_arch' \
}
diff --git a/crawl-ref/source/dat/sewer.des b/crawl-ref/source/dat/sewer.des
index bc5f589e94..ce8fc647a4 100644
--- a/crawl-ref/source/dat/sewer.des
+++ b/crawl-ref/source/dat/sewer.des
@@ -15,20 +15,37 @@
{{
function sewer_portal(e)
- e.marker([[O = lua:one_way_stair { desc = "A glowing drain",
- dst = "sewer",
- dstorigin = "in the sewers",
- overmap = "glowing drain",
- floor = "stone_arch" }]])
+ local timeout_turns = crawl.random_range(1500, 2000)
+
+ local messager =
+ timed_msg {
+ visible = true,
+ -- $F{xxx} will be substituted with the 'entity' property of the timed
+ -- marker, or with the desc property (if entity is not set).
+ messages = time_messages(timeout_turns,
+ "$F{The} is slowly rusting away.",
+ "$F{The} is rusting away.",
+ "$F{The} is quickly rusting away.",
+ "$F{The} is falling apart.")
+ }
+
+ e.lua_marker('O',
+ timed_marker {
+ desc = "glowing drain",
+ entity = 'drain',
+ dst = "sewer",
+ dstorigin = "in the sewers",
+ overmap = "glowing drain",
+ turns = timeout_turns,
+ floor = "stone_arch",
+ msg = messager })
e.kfeat("O = enter_portal_vault")
e.colour("O = lightgreen")
end
-}}
-# Use the following line in destination maps after all SUBST's have taken place
-# : sewer_colours(_G)
-# Note that the function also defines < to be the exit portal.
-{{
+-- Use the following line in destination maps after all SUBSTs
+-- : sewer_colours(_G)
+-- Note that the function also defines < to be the exit portal.
function sewer_colours(e)
e.kfeat("< = exit_portal_vault")
e.colour("< = darkgrey")
@@ -305,7 +322,7 @@ MONS: worm / nothing w:3
MONS: ooze / nothing w:2
# chances are good you'll find something to cross the deep water
ITEM: scroll of fear / scroll of fog / scroll of teleportation w:50 / \
- scroll of blinking / scroll of identify / nothing
+ scroll of blinking / scroll of identify / nothing
ITEM: potion of levitation w:50 / potion of invisibility / \
potion of might / nothing
# possibly rather generous loot, if you get to the center
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 276b60266c..ba3f2df750 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -2271,12 +2271,12 @@ void describe_floor()
mpr("Beware, for starvation awaits!", MSGCH_EXAMINE);
}
-static std::string _feature_do_grammar(description_level_type dtype,
- bool add_stop,
- bool force_article,
- std::string desc)
+std::string thing_do_grammar(description_level_type dtype,
+ bool add_stop,
+ bool force_article,
+ std::string desc)
{
- if (add_stop)
+ if (add_stop && (desc.empty() || desc[desc.length() - 1] != '.'))
desc += ".";
if (dtype == DESC_PLAIN || (!force_article && isupper(desc[0])))
{
@@ -2320,7 +2320,7 @@ std::string feature_description(dungeon_feature_type grid,
if (bloody)
desc += ", spattered with blood";
- return _feature_do_grammar(dtype, add_stop, grid_is_trap(grid), desc);
+ return thing_do_grammar(dtype, add_stop, grid_is_trap(grid), desc);
}
std::string raw_feature_description(dungeon_feature_type grid,
@@ -2592,7 +2592,7 @@ std::string feature_description(const coord_def& where, bool bloody,
if (bloody)
desc += ", spattered with blood";
- return _feature_do_grammar(dtype, add_stop, false, desc);
+ return thing_do_grammar(dtype, add_stop, false, desc);
}
switch (grid)
@@ -2606,7 +2606,7 @@ std::string feature_description(const coord_def& where, bool bloody,
return (shop_name(where, add_stop));
case DNGN_ENTER_PORTAL_VAULT:
- return (_feature_do_grammar(
+ return (thing_do_grammar(
dtype, add_stop, false,
_marker_feature_description(where)));
default:
diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h
index a422f0fc2a..4b0b5ae841 100644
--- a/crawl-ref/source/directn.h
+++ b/crawl-ref/source/directn.h
@@ -153,6 +153,11 @@ bool in_los(const coord_def &pos);
bool in_vlos(int x, int y);
bool in_vlos(const coord_def &pos);
+std::string thing_do_grammar(description_level_type dtype,
+ bool add_stop,
+ bool force_article,
+ std::string desc);
+
std::string get_terse_square_desc(const coord_def &gc);
void terse_describe_square(const coord_def &c, bool in_range = true);
void full_describe_square(const coord_def &c);
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 7d06e22c5f..5a34a0a825 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -341,9 +341,9 @@ std::string pluralise(const std::string &name,
// knife -> knives
return name.substr(0, name.length() - 2) + "ves";
}
- else if (ends_with(name, "ff"))
+ else if (ends_with(name, "staff"))
{
- // staff -> staves
+ // staff -> staves, but not hippogriff -> hippogrives.
return name.substr(0, name.length() - 2) + "ves";
}
else if (ends_with(name, "f"))