Dump of #1610 (RPG RDB Room)

@create #364 named RPG RDB room:RPG RDB room
@prop #1610."room_data" {} r
@prop #1610."weather_zone" 0 r
@prop #1610."show_weather" 0 r
@prop #1610."lights" {} r
@prop #1610."illuminance" 0 r
@prop #1610."light" 0 r
@prop #1610."last_light" 0 r
@prop #1610."room_lumens" 0 r
@prop #1610."light_change_msgs" {} r
;;#1610.("light_change_msgs") = {"%N's %source provides only a feeble glow.", "Shadows are cast about %room by the pitiful %source.", "%room is slightly illuminated by %n's flickering %source.", "You can almost see %room clearly in the light.", "The light from %n's %source allows you to see details quite clearly.", "%room is well lit by the strong light from %n's %source.\"", "%room is completely lit by %n's %source.", "%room is flooded with the blinding light emanating from the powerful light source.\""}
@prop #1610."darken_change_msgs" {} r
;;#1610.("darken_change_msgs") = {"%room is cast into darkness.", "%room is now only feebly lit.", "Shadows loom darkly in %room.", "%room darkens considerably.", "You can almost see %room clearly in the light.", "You can still see details of %room quite clearly.", "%room is still well lit.", "%room is still completely lit."}
@prop #1610."slight_change_msgs" {} r
;;#1610.("slight_change_msgs") = {"%room becomes slightly dimmer.", "%room becomes slightly brighter."}
@prop #1610."lighter_doll_msgs" {} r
;;#1610.("lighter_doll_msgs") = {"%N's lightsource provides only a feeble glow.", "Shadows are cast about %room by the pitiful lightsource.", "%room is slightly illuminated by %n's flickering lightsource.", "You can almost see %room clearly in the light.", "The light from %n's lightsource allows you to see details quite clearly.", "%room is well lit by the strong light from %n's lightsource.\"", "%room is completely lit by %n's lightsource.", "%room is flooded with the blinding light emanating from the powerful light source.\""}
@prop #1610."darker_doll_msgs" {} r
;;#1610.("darker_doll_msgs") = {"%room is cast into darkness.", "%room is now only feebly lit.", "Shadows loom darkly in %room.", "%room darkens considerably.", "You can almost see %room clearly in the light.", "You can still see details of %room quite clearly.", "%room is still well lit.", "%room is still completely lit."}
@prop #1610."peace_msg" "" rc
@prop #1610."opeace_msg" "%N %<draws> back %p weapon, preparing to lunge for %d.  Suddenly, a look of calm melts %p angry features into an expression of cosmic warmth.  %N %<says>, \"I love you, %d.\"  You feel so peaceful." rc
;;#1610.("enabled") = 1
;;#1610.("residents") = {#102, #82, #259}
;;#1610.("free_entry") = 0
"#1610.("entrances") => E_PERM (Permission denied)
"#1610.("exits") => E_PERM (Permission denied)
"#1610.("key") => E_PERM (Permission denied)
;;#1610.("aliases") = {"RPG RDB room"}
;;#1610.("object_size") = {27638, 1141286558}

@verb #1610:"set_room_flag" this none this
@program #1610:set_room_flag
":set_room_flag(<flag>) => Add <flag> to the list of room flags, if its an appropriate flag, then add other flags that that flag requires.";
rdb = $local.rpg.room_db;
rdb:protected();
{flag} = args;
if (!(loc = flag in rdb.flag_names))
  return E_INVARG;
endif
flags = this.room_data;
for excluded in (rdb.flag_exclude[loc])
  flags = setremove(flags, excluded);
endfor
for required in (rdb.flag_depend[loc])
  flags = setadd(flags, required);
endfor
flags = setadd(flags, flag);
return this.room_data = flags;
.

@verb #1610:"get_room_flags" this none this
@program #1610:get_room_flags
":get_room_flags() => returns a list of flags on the room i.e {\"underwater\", \"cavern\"}";
return this.room_data;
.

@verb #1610:"clear_room_flag" this none this
@program #1610:clear_room_flag
":clear_room_flag(<flag>) => remove <flag> from the rooms flags, if its in there.  Also remove any other flags that depend on it on.  Returns the state of the rooms flags.";
rdb = $local.rpg.room_db;
rdb:protected();
rdb:wait_for_tasks();
{flag} = args;
flags = this.room_data;
names = rdb.flag_names;
if ((!flag) in names)
  return E_INVARG;
endif
depends = rdb.flag_depend;
for n in [1..length(depends)]
  if (flag in depends[n])
    flags = setremove(flags, names[n]);
  endif
endfor
flags = setremove(flags, flag);
return this.room_data = flags;
.

@verb #1610:"clear_room_flags" this none this
@program #1610:clear_room_flags
":clear_room_flags() => clears the room flags.";
rdb = $local.rpg.room_db;
rdb:protected();
this.room_data = {};
.

@verb #1610:"get_weather_zone" this none this
@program #1610:get_weather_zone
":get_weather_zone() = > get the name of the rooms weather zone.";
rpg = $local.rpg;
rdb = rpg.room_db;
rdb:wait_for_tasks();
if (this.weather_zone)
  return rdb.zone_names[this.weather_zone];
endif
return "none";
.

@verb #1610:"set_weather_zone" this none this
@program #1610:set_weather_zone
":set_weather_zone(<zone name>) => Sets the weather zone of the room. none means no weather zone.";
rdb = $local.rpg.room_db;
rdb:protected();
rdb:wait_for_tasks();
zone = args[1];
if (typeof(zone) == STR)
  if (!(zone == "none"))
    zonenum = zone in rdb.zone_names;
    if (!zonenum)
      return E_INVARG;
    endif
  else
    zonenum = 0;
  endif
else
  return E_TYPE;
endif
return this.weather_zone = zonenum;
.

@verb #1610:"description" this none this
@program #1610:description
":description() => Add the weather to the rooms .description.";
rpg = $local.rpg;
if ((callers()[$][2] in {"@exam", "@examine"}) && (!(player in {@rpg.gms, @rpg.wannabees})))
  player:tell("Use 'examine' rather than '@examine' to look at LambdaRPG rooms.");
  kill_task(task_id());
endif
if (valid(doll = rpg:get_doll(player)))
  if (blind_msg = doll:cannot_see())
    return (("lighting" in this.room_data) && (this.illuminance < 1)) ? this:dark_description() | blind_msg;
  endif
elseif (("lighting" in this.room_data) && (this.illuminance < 1))
  return this:dark_description();
endif
desc = pass(@args);
rdb = rpg.room_db;
if (this.weather_zone && this.show_weather)
  weather = this:get_weather();
  w_desc = `this:weather_desc(weather) ! ANY => rdb:default_weather_desc(weather)';
  if (typeof(w_desc != STR))
  else
    desc = `(desc + "  ") + w_desc ! ANY => {@desc, w_desc}';
  endif
endif
return desc;
.

@verb #1610:"enterfunc" this none this
@program #1610:enterfunc
"Kill storms and windwalls if entering an inappropriate room.  Add victim to drowning list, if underwater.";
{what} = args;
pass(what);
(rpg = $local.rpg):secure_stack(2);
rpg:s_i_n(0);
{rdb, mdb, odb, l_u, t_u} = {rpg.room_db, rpg.magic_db, rpg.object_db, $list_utils, $time_utils};
flags = this.room_data;
if (valid(doll = rpg:get_doll(what)))
  if ("lighting" in flags)
    if ("outdoors" in flags)
      {abacus, Sun, Moon} = odb.ephemeris;
      day = max(t_u:sun(), 0);
      if ((Sun in this.lights) && (!day))
        this.lights = setadd(setremove(this.lights, Sun), Moon);
        this:recalc_illum();
      elseif ((Moon in this.lights) && day)
        this.lights = setadd(setremove(this.lights, Moon), Sun);
        this:recalc_illum();
      endif
    endif
    (doll.lights && (what.location == this)) && this:relight(doll, 1);
  endif
  if ("tavern" in flags)
    odb.natweap_db:add_natweap(doll, odb.pirate_brawling, 2);
  endif
  if ("submerged" in flags)
    if (mdb:storms_cast_by(what))
      mdb:kill_storm(what, "silent");
      rpg:playertell(what, "Your conjured weather dissipates in the water.");
      rpg:rpg_announce_all_but(this, {what}, "The conjured weather summoned by ", what.name, " dissipates in the water.");
    endif
    if (x = l_u:iassoc("unwind", sch = doll.schedule, 2))
      doll:cancel(sch[x]);
      mdb.ww_combat_effect:remove(doll);
      rpg:playertell(what, "Your windwall dissipates in the water.");
      rpg:rpg_announce_all_but(this, {what}, "The windwall surrounding ", what.name, " dissipates in the water.");
    endif
    if (x = l_u:iassoc("bite", sch = doll.schedule, 2))
      doll:cancel(sch[x]);
      mdb.bc_combat_effect:remove(doll);
      rpg:say_action("The cloud of insects surrounding %n disperses.");
    endif
    if (x = l_u:iassoc("unbackfire", sch = doll.schedule, 2))
      doll:cancel(sch[x]);
      rpg.magic_db.bf_combat_effect:remove(doll);
      rpg:say_action("The aura of flame about %n is extinguished.", what);
    endif
    `rpg.user_utils.griffen.tides_db:do_entrance(what) ! ANY';
  elseif (("cavern" in flags) || ("structure" in flags))
    window = $nothing;
    for t in (`this:exits() ! ANY => {}')
      if ("outdoors" in `t.dest.room_data ! ANY => {}')
        window = t;
        break t;
      endif
    endfor
    if (valid(window) && mdb:storms_cast_by(what))
      rpg:playertell(what, "Your conjured storm swirls madly outside.");
      rpg:rpg_announce_all_but(this, {what}, "The conjured weather summoned by ", what.name, " howls just outside.");
    elseif (mdb:storms_cast_by(what))
      mdb:kill_storm(what, "silent");
      rpg:playertell(what, "Your conjured weather dissipates in the enclosed area.");
      rpg:rpg_announce_all_but(this, {what}, "The conjured weather summoned by ", what.name, " quickly dissipates in the enclosed area.");
    endif
  elseif ((("swamp" in flags) && (is_player(what) || (!("swamp_thing" in what.flags)))) && (!((mire = odb.mired_effect) in doll.combat_effects)))
    rpg:playertell(what, "Your feet sink into the ", {"boggy", "muddy", "swampy", "oozy", "mucky"}[random($)], " ground.");
    mire:add(doll);
  endif
elseif (is_player(what))
  rpg.object_db.recruit:maybe_offer(what);
endif
"Mooshie (#106469) - Fri Dec 26, 1997 - Added Griff's tide_db hook.";
"Mooshie (#106469) - Fri Jan  2, 1998 - Updated security, de-ticking.";
"Profane (#30788) - Sat Aug 22, 1998 - Biting clouds go away underwater, and more deticking.";
"Profane (#30788) - Sun May  2, 1999 - backfire goes away underwater.";
"THX (#105941) - Mon Jul  3, 2000 - Altered so that players can control a storm even if they are inside a structure/cavern _IF_ that structure is right next to an outdoor area.  i.e., the storm rages just outside.  Lightning qual is weakened in sheltered areas in rpg.magic_db:blast.";
"THX (#105941) - Sat Mar 31, 2001 - Added a hack for the room lighting stuff.";
.

@verb #1610:"magic_effect" this none this
@program #1610:magic_effect
":magic_effect(<caster>, <qual>, <skill>, <target>) => returns a value, negative for increased magic, positive for decrease, based on stats of the room.  Also will notify the caster of what might be messing with their spells.";
(rpg = $local.rpg):secure();
{caster_doll, qual, skill, target_doll} = args;
caster = caster_doll.character;
if (rpg.magic_db.en_combat_effect in caster_doll.magic_effects)
  caster:tell("The constricting vines prevent you from using your spell foci properly.");
  return 500;
endif
rdb = rpg.room_db;
spell = `skill.aliases[1] ! ANY => skill';
flags = this:get_room_flags();
if (this.weather_zone)
  weather = rdb.zone_weather[this.weather_zone];
else
  weather = "none";
endif
strings = {};
spell_num = spell in {"biting_cloud", "waterwhip", "iceshell", "storm", "windwall", "stinkcloud", "calm", "predict", "firebolt", "heat"};
if ((spell_num == 0) || (weather == "none"))
  value = 0;
elseif (n = weather in {"chilly", "flakes", "snow", "blizzard"})
  word = "freezing weather";
  value = n * {-8, 1, 10, -10, 2, -2, -3, -1, -8, -8}[spell_num];
elseif (n = weather in {"sun", "hot", "muggy"})
  word = "balmy weather";
  value = n * {6, -1, -8, -4, 0, 1, 4, 1, 1, 2}[spell_num];
elseif (n = weather in {"cloudy", "overcast"})
  word = "drifting clouds";
  value = n * {0, 0, 0, 1, 0, 0, 0, 0, 0, 0}[spell_num];
elseif (n = weather in {"breeze", "wind", "gusts"})
  word = "wind";
  value = n * {-6, 0, 0, 1, 6, -10, -2, -2, 0, 0}[spell_num];
elseif (n = weather in {"drizzle", "rain", "downpour"})
  word = "rainy weather";
  value = n * {-10, 10, 1, 4, 1, -8, -2, -1, -6, -3}[spell_num];
elseif (weather in {"sleet", "hail"})
  word = "icy precipitation";
  value = {-30, 8, 20, 2, -1, -15, -8, -4, -20, -15}[spell_num];
elseif (n = weather in {"thunder", "storm", "tempest"})
  word = "stormy weather";
  value = n * {-10, 8, 1, 10, 4, -6, -5, -2, -6, -3}[spell_num];
elseif (n = weather in {"mist", "fog"})
  word = "misty air";
  value = n * {2, 2, 2, -10, -10, 4, 5, 0, 0, 0}[spell_num];
else
  word = "<error>";
  value = 0;
endif
if (value > 1)
  strings = setadd(strings, ("Your spell draws energy from the " + word) + ".");
elseif (value < -1)
  strings = setadd(strings, ("The " + word) + " interferes with your spell.");
endif
if ("outdoors" in flags)
  mark = spell in {};
  if (mark)
    value = value + {}[mark];
  endif
endif
if ("cavern" in flags)
  mark = spell in {"hail", "storm", "stinkcloud", "windwall"};
  if (mark)
    value = value + {10, -200, -10, -10}[mark];
    if (value > 0)
      strings = setadd(strings, "Your magic draws upon the surrounding rocks for power.");
    else
      strings = setadd(strings, "The enclosed area interferes with the casting of the spell.");
    endif
  endif
endif
if ("structure" in flags)
  mark = spell in {"storm", "windwall", "stinkcloud"};
  if (mark)
    value = value + {-200, -10, -10}[mark];
    strings = setadd(strings, "The enclosed area interferes with the casting of the spell.");
  endif
endif
if ("wet" in flags)
  mark = spell in {"waterwhip", "iceshell"};
  if (mark)
    value = value + {10, 10}[mark];
    strings = setadd(strings, "The dampness of the area feeds energy into the spell.");
  endif
endif
if ("submerged" in flags)
  mark = spell in {"firebolt", "heat", "biting_cloud", "storm", "windwall", "stinkcloud", "hail", "calm", "predict", "backfire", "parch"};
  if (mark)
    value = value + {-200, -50, -200, -200, -200, -200, -50, -200, -200, -200, -200}[mark];
    strings = setadd(strings, "The water interferes with the spell.");
  endif
endif
if ("blessed" in flags)
  if (spell in {"biting_cloud", "iceshell", "storm", "stinkcloud", "firebolt", "heat", "hail", "shatter", "depress", "stealskill", "wound", "drain"})
    value = value - 20;
    strings = setadd(strings, "The flows of magic in this blessed place are not well suited to aggressive spells.");
  elseif (spell in {"heal", "windwall", "forcewall", "lifelink"})
    value = value + 20;
    strings = setadd(strings, "Your spell draws energy from the peaceful magic of this area.");
  endif
endif
if ("damned" in flags)
  if (spell in {"biting_cloud", "iceshell", "storm", "stinkcloud", "firebolt", "heat", "hail", "shatter", "depress", "stealskill", "wound", "drain"})
    value = value + 20;
    strings = setadd(strings, "Your destructive spell is empowered by the dark forces that permeate this area.");
  elseif (spell in {"heal", "windwall", "forcewall", "lifelink"})
    value = value - 20;
    strings = setadd(strings, "The evil aura of this fell place interferes with your spell.");
  endif
endif
value = value - this.magic_effect;
if (strings)
  caster:tell($list_utils:random_element(strings));
endif
"if (-value > qual)";
"  caster:tell(\"Nothing happens.\");";
"endif";
return -value;
.

@verb #1610:"combat_effect" this none this
@program #1610:combat_effect
":room_combat_effect(by, target, weapon) => returns a value based on inhibition of attacker by rooms stuff.  Maybe integrate?";
rpg = $local.rpg;
if (!rpg:trusted(caller_perms()))
  return E_PERM;
endif
rdb = rpg.room_db;
{by, target, weapon} = args;
by_doll = rpg:get_doll(by);
flags = this:get_room_flags();
value = 0;
strings = {};
if ("peaceful" in flags)
  this:announce_peaceful(@args);
  return E_NACC;
elseif ("submerged" in flags)
  if (is_player(by) && (!(parent(weapon) in rdb.seaworthy_weapon_parents)))
    value = value - (weapon.blunt ? 60 | 20);
    by_doll:check_fatigue(random(12));
    strings = setadd(strings, ("It's hard to use your " + weapon.name) + " underwater.");
  else
    value = value + 10;
  endif
endif
if ("dim" in flags)
  value = value - 15;
  strings = setadd(strings, "It's a little bit difficult to see your foe in the dim light.");
elseif ("dark" in flags)
  value = value - 40;
  strings = setadd(strings, "It's hard to hit your foe when it's this dark.");
endif
if (("sun-lit" in flags) && (rdb:time_of_day() == "night"))
  value = value - 10;
  strings = setadd(strings, "The darkness of night makes your foe a little hard to see.");
endif
if (strings)
  by:tell($list_utils:random_element(strings));
endif
return value;
"Mooshie (#106469) - Sun Mar  3, 2002 - Added check for 'peaceful' flag. Streamline verb a lil' bit.";
.

@verb #1610:"set_show_weather" this none this
@program #1610:set_show_weather
"Cruddy hacks to allow other GMs to set the .show_weather prop.  Sets this.show_weather to args[1]";
if ($local.rpg.room_db:trusted(caller_perms()) || (caller_perms() == this.owner))
  return this.show_weather = args[1];
else
  return E_PERM;
endif
.

@verb #1610:"show_weather" this none none rxd
@program #1610:show_weather
"Give information about Room database flags on the room.";
player:tell("----------- Report on ", this.name, "  ", tostr(this), "  -----------");
player:tell("Flags set:  ", $string_utils:english_list(this:get_room_flags()), ".");
player:tell("Weather zone:  ", this:get_weather_zone(), ".");
player:tell("----------- End of show ------------");
.

@verb #1610:"get_weather" this none this
@program #1610:get_weather
$local.rpg.room_db:cycle();
return $local.rpg.room_db.zone_weather[this.weather_zone];
"Profane (#30788) - Sat Apr 14, 2001 - new cycle paradigm here.";
.

@verb #1610:"hidden_verbs" this none this
@program #1610:hidden_verbs
{who} = args;
prev = pass(who);
if (!$local.rpg:trusted(who))
  prev = {@prev, {$local.rpg.room_db.room_parent, "show", {"this", "none", "none"}}};
endif
return prev;
.

@verb #1610:"ok" this none this
@program #1610:ok
"An object is 'OK' for inclusion in the room's desc if it has some sort of look_msg";
"If the message is a string it gets included.";
"If it's a non-string the object is invisible (must be owned by the room's owner, or a resident).";
"A blank look_msg or .enabled<=0 suppresses players being included.";
{k} = args;
if (($object_utils:has_callable_verb(k, "look_msg") && (y = k:look_msg())) || ($object_utils:has_property(k, "look_msg") && (y = k.look_msg)))
  if (is_player(k) && ((this.enabled <= 0) || (!$string_utils:strip_chars(tostr(y), " "))))
    return 0;
  elseif ((k.owner == this.owner) || (k in this.residents))
    return (typeof(y) == STR) ? 1 | ((typeof(y) == OBJ) ? -1 | 0);
  else
    return (typeof(y) == STR) && 1;
  endif
endif
.

@verb #1610:"check_lights(obsolete)" this none this
@program #1610:check_lights(obsolete)
"Usage: check_lights()";
"Sets this.light to reflect light in the room and on dolled objects in the room.";
(rpg = $local.rpg):secure();
for light in (this.lights)
  try
    if (valid(doll = rpg:get_doll(light)))
      total = total + doll.room_light;
    elseif (rpg:trusted_verb(light, "room_light"))
      if (typeof(result = light:room_light(total, sofar)) == INT)
        total = total + result;
        sofar = {@sofar, light};
      endif
    else
      this.lights = setremove(this.lights, light);
    endif
  except (ANY)
    this.lights = setremove(this.lights, light);
  endtry
endfor
return this.light = total;
.

@verb #1610:"add_light(obsolete)" this none this
@program #1610:add_light(obsolete)
"Usage: add_light(OBJ light source | PC) => Adds light (or lights on PC) to room";
"       remove_light(OBJ light source | PC) => Removes object lights from room";
(rpg = $local.rpg):secure();
{what} = args;
if (verb == "add_light")
  this.lights = setadd(this.lights, what);
else
  this.lights = setremove(this.lights, what);
endif
"this:check_lights();";
return this.lights;
.

@verb #1610:"relight" this none this
@program #1610:relight
"Usage: relight(OBJ lightsource | doll, BOOLEAN add/remove) =>  Adds|Removes lightsource (or lighted doll) to|from room.lights and recalculates room illuminance.";
{source, add} = args;
(rpg = $local.rpg):secure();
if (add)
  if (source in this.lights)
    return;
  elseif (source:lumens(this))
    this.lights = setadd(this.lights, source);
  else
    return;
  endif
elseif (source in this.lights)
  this.lights = setremove(this.lights, source);
else
  return;
endif
this:recalc_illum();
this:announce_light(source, add);
"THX (#105941) - Sat Mar 31, 2001 - Added.";
.

@verb #1610:"illuminance" this none this
@program #1610:illuminance
{doll} = args;
raw = this.(prop);
if (raw < THRESHOLD_VALUE_WHICH_I_HAVE_NOT_FIGURED_OUT_YET)
  for t in (doll.lights)
    raw = raw + `t:infrared(this, raw) ! E_VERBNF => 0';
  endfor
endif
return raw;
"THX (#105941) - Sat Mar 31, 2001 - Added";
.

@verb #1610:"recalc_illum" this none this
@program #1610:recalc_illum
(rpg = $local.rpg):secure();
lumens = this.room_lumens;
for t in (this.lights)
  curr = `t:lumens(this) ! E_VERBNF';
  if (curr)
    lumens = lumens + curr;
  else
    this.lights = setremove(this.lights, t);
  endif
endfor
"Gonna have to think about the following line ... This is some characteristic cross-sectional thingummy of the room.";
reynolds_number = max(toint(sqrt(tofloat(`this.space ! ANY => 999'))), 1);
this.illuminance = min(lumens / reynolds_number, 100);
if (player in rpg.grand_masters)
  rpg:playertell_lines(player, {tostr(#20:nn(this), " ", this.illuminance, " ", #20:nn(this.lights)), tostr(#20:nn(doll = rpg:get_doll(player)), " ", doll.illuminance, " ", #20:nn(doll.lights))});
endif
(this in rpg.dark_rooms) && this:illumination_check();
"THX (#105941) - Sat Mar 31, 2001 - Added.";
"THX (#105941) - Sun Apr  1, 2001 - Grandparent protection for the interim.";
.

@verb #1610:"resting sleeping" this none this
@program #1610:resting
return args ? 0 | {};
.

@verb #1610:"slight_change_msgs light_change_msgs darken_change_msgs lighter_doll_msgs darker_doll_msgs" this none this
@program #1610:slight_change_msgs
{source, slot} = args;
return this.(verb)[slot];
.

@verb #1610:"announce_light" this none this
@program #1610:announce_light
{source, add} = args;
(rpg = $local.rpg):secure();
if (valid(source))
  illum = this.illuminance;
  prev = this.last_light;
  factor = (illum + 5) / 10;
  priori = (prev + 5) / 10;
  if (factor == priori)
    return;
  elseif (abs(factor - priori) == 1)
    msg = this:slight_change_msgs(source, add + 1);
  elseif (add)
    msg = this:((source in rpg.dolls) ? "lighter_doll_msgs" | "light_change_msgs")(source, factor);
  else
    msg = this:((source in rpg.dolls) ? "darker_doll_msgs" | "darken_change_msgs")(source, factor);
  endif
  msg = strsub(msg, "%source", source.name);
  msg = strsub(msg, "%room", this.name);
  if (source.location in rpg.pcs)
    rpg:say_action(msg, source.location);
  else
    msg = strsub(msg, "%n's", "the");
    msg = strsub(msg, "%N's", "The");
    rpg:rpg_announce_all_but(this, {source}, msg);
  endif
endif
this.last_light = this.illuminance;
"THX (#105941) - Fri Jun 29, 2001 - Changed to call for *_msgs verb including 'source' for possible customization by builders.";
.

@verb #1610:"dark_description" this none this rx
@program #1610:dark_description
desc = this:read_misc_note("dark_description");
desc = (typeof(desc) != ERR) ? desc | "";
return desc || "It is too dark to see.";
"THX (#105941) - Fri Jun 29, 2001 - If set +d, this verb will crash E_VERBNF unless on child of $local.rpg.dungeon.  But #1610 will never be set with lighting on anyway.  I could move the misc_notes and related verbs to #1610, but we can do that if it becomes unwieldy.  Feh.";
.

@verb #1610:"announce_peaceful" this none this
@program #1610:announce_peaceful
{by, target, weapon} = args;
if (msg = this:peace_msg(@args))
  by:tell(msg);
endif
if (!(omsg = this:opeace_msg(@args)))
elseif (msg)
  this:announce_all_but({by}, this:opeace_msg(@args));
else
  $local.rpg:say_action(omsg, @args);
endif
.

@verb #1610:"peace_msg opeace_msg" this none this
@program #1610:peace_msg
{by, target, weapon} = args;
return $string_utils:pronoun_sub(this.(verb), by, weapon, this, target);
.

"***finished***