<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.legendmud.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rufus</id>
	<title>LegendMUD - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.legendmud.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rufus"/>
	<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php/Special:Contributions/Rufus"/>
	<updated>2026-07-21T10:33:50Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.2</generator>
	<entry>
		<id>https://www.legendmud.org/index.php?title=GMCP_Packages&amp;diff=843</id>
		<title>GMCP Packages</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=GMCP_Packages&amp;diff=843"/>
		<updated>2026-07-18T18:25:15Z</updated>

		<summary type="html">&lt;p&gt;Rufus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This document describes LegendMUD’s GMCP (Generic MUD Communication&lt;br /&gt;
Protocol) support from the client’s point of view: how to enable it,&lt;br /&gt;
what you can request, what the server pushes on its own, and the exact&lt;br /&gt;
shape of every payload. It is written for people building or scripting&lt;br /&gt;
MUD clients (Mudlet, TinTin++, custom clients, etc.). No knowledge of&lt;br /&gt;
the server code is needed — or useful — here.&lt;br /&gt;
&lt;br /&gt;
In-game, &amp;lt;code&amp;gt;HELP GMCP&amp;lt;/code&amp;gt; covers the basics.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== 1. Enabling GMCP ==&lt;br /&gt;
&lt;br /&gt;
GMCP is telnet option '''201'''. On connect the server offers it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;server → client:   IAC WILL 201&lt;br /&gt;
client → server:   IAC DO   201     (enables GMCP)&lt;br /&gt;
client → server:   IAC DONT 201     (disables GMCP)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Most scriptable clients handle this negotiation for you and expose&lt;br /&gt;
GMCP events directly. Nothing is sent over GMCP until you answer&lt;br /&gt;
&amp;lt;code&amp;gt;IAC DO 201&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
All GMCP traffic — both directions — is framed as telnet&lt;br /&gt;
sub-negotiation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;IAC SB 201  &amp;amp;lt;package name&amp;amp;gt; [&amp;amp;lt;JSON payload&amp;amp;gt;]  IAC SE&amp;lt;/pre&amp;gt;&lt;br /&gt;
A single space separates the package name from the JSON when a payload&lt;br /&gt;
is present.&lt;br /&gt;
&lt;br /&gt;
== 2. Making requests ==&lt;br /&gt;
&lt;br /&gt;
Send the package name, optionally followed by JSON arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;char.score&lt;br /&gt;
object.info {&amp;amp;quot;oid&amp;amp;quot;:&amp;amp;quot;0x1a2b3c4d5e6f7890&amp;amp;quot;}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Rules:&lt;br /&gt;
&lt;br /&gt;
* '''Package names are case-insensitive''' (&amp;lt;code&amp;gt;Char.Score&amp;lt;/code&amp;gt; works), and must be dotted — at least &amp;lt;code&amp;gt;word.word&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''JSON keys are case-sensitive''', in both requests and replies.&lt;br /&gt;
* Most packages take no arguments; any request body they receive is ignored. The exceptions are &amp;lt;code&amp;gt;object.info&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt; (an &amp;lt;code&amp;gt;oid&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;help.topic&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;keywords&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;char.journal.entry&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;vnum&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Requests are size-capped: package name up to 49 characters, JSON body up to 399 characters.&lt;br /&gt;
* A malformed request, unknown package, or invalid JSON gets a '''&amp;lt;code&amp;gt;logging.error&amp;lt;/code&amp;gt;''' reply (see §7) rather than silence.&lt;br /&gt;
&lt;br /&gt;
Every reply arrives as its own GMCP message, tagged with the package&lt;br /&gt;
name. One request can produce several messages (&amp;lt;code&amp;gt;spells.all&amp;lt;/code&amp;gt; sends&lt;br /&gt;
four).&lt;br /&gt;
&lt;br /&gt;
== 3. Reading the reference: conventions ==&lt;br /&gt;
&lt;br /&gt;
* '''Request-only''' — sent only when you ask. Most packages.&lt;br /&gt;
* '''Pushed''' — sent by the server when game state changes, whether or not you asked (§5 lists them).&lt;br /&gt;
* '''&amp;lt;code&amp;gt;*.all&amp;lt;/code&amp;gt; packages are static reference data.''' They describe the game, not your character, and do not change during play. Request each once per session, cache it, and join the per-character packages against it by id.&lt;br /&gt;
* '''Ids are stable for your session''' but not guaranteed across server reboots for every package (each entry below says which field is the durable identifier). The safe pattern is: fetch &amp;lt;code&amp;gt;*.all&amp;lt;/code&amp;gt; once per login, join on id from there.&lt;br /&gt;
* '''Empty means empty.''' Per-character list packages always reply, even when the answer is “none” — a non-chanter asking for &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt; gets &amp;lt;code&amp;gt;{&amp;amp;quot;spells&amp;amp;quot;: []}&amp;lt;/code&amp;gt;, not silence. You can rely on a reply to every valid request.&lt;br /&gt;
* All numbers are raw integers — no display formatting, no commas.&lt;br /&gt;
&lt;br /&gt;
== 4. Package reference ==&lt;br /&gt;
&lt;br /&gt;
=== 4.1 Character basics ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; — pushed on every prompt, also requestable ====&lt;br /&gt;
&lt;br /&gt;
An object keyed by prompt tokens: hit points, mana, movement, position,&lt;br /&gt;
room, gold, opponent condition, and everything else the text prompt can&lt;br /&gt;
show. Immortal-only tokens are omitted for mortals.&lt;br /&gt;
&lt;br /&gt;
By default the keys are the short prompt codes. Turn on the&lt;br /&gt;
&amp;lt;code&amp;gt;gmcplongpromptkeys&amp;lt;/code&amp;gt; config option in-game to get verbose,&lt;br /&gt;
self-describing keys instead — recommended for new clients. See&lt;br /&gt;
&amp;lt;code&amp;gt;HELP GMCPLONGPROMPT&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.prompt.delta&amp;lt;/code&amp;gt; — opt-in, pushed only ====&lt;br /&gt;
&lt;br /&gt;
Off by default — nothing about &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; changes until you ask.&lt;br /&gt;
Opt in with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;char.prompt.delta { &amp;amp;quot;on&amp;amp;quot;: true }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Once opted in:&lt;br /&gt;
&lt;br /&gt;
* '''Every prompt render''' — whether you typed something or game output re-rendered it — arrives as &amp;lt;code&amp;gt;char.prompt.delta&amp;lt;/code&amp;gt; containing only the keys whose values changed since the last message you were sent. Do not expect a full after your own commands.&lt;br /&gt;
* '''Nothing changed''' → nothing arrives at all, not even an empty &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;. Don’t use either package as a heartbeat — if your UI needs a “prompt happened” signal, use the telnet prompt line instead.&lt;br /&gt;
* '''Fulls are rare and always meaningful.''' You get a full &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; only: right after opting in (your starting baseline), when you request one, after SHOWPROMPT, or when the server must rebase you (reconnect, key-style toggle, immortal-status change, character change). If you want a full, ask for it.&lt;br /&gt;
&lt;br /&gt;
Send &amp;lt;code&amp;gt;char.prompt.delta { &amp;amp;quot;on&amp;amp;quot;: false }&amp;lt;/code&amp;gt; to go back to full-every-&lt;br /&gt;
render. The setting is per connection and does not persist — re-send&lt;br /&gt;
it every session. The first prompt after opting in is always a full&lt;br /&gt;
&amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Merging deltas''': keep a cumulative baseline — your last full&lt;br /&gt;
&amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt;, updated by every &amp;lt;code&amp;gt;char.prompt.delta&amp;lt;/code&amp;gt; since — and apply&lt;br /&gt;
each delta as a key-by-key overwrite; your model then always matches&lt;br /&gt;
the server’s. No key ever disappears from the schema — a key absent&lt;br /&gt;
from a delta simply hasn’t changed. A value that goes away (e.g.&lt;br /&gt;
&amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;fighting_name&amp;lt;/code&amp;gt; when combat ends) arrives as JSON &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; rather&lt;br /&gt;
than being omitted — treat &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; as an ordinary value, in both&lt;br /&gt;
directions (&amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; → value and value → &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; are both changes). Deltas use whichever key style (short or&lt;br /&gt;
&amp;lt;code&amp;gt;gmcplongpromptkeys&amp;lt;/code&amp;gt;) your connection is set to, same as &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt;;&lt;br /&gt;
toggling that setting mid-session forces the next message to be a full&lt;br /&gt;
&amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; under the new names.&lt;br /&gt;
&lt;br /&gt;
'''Resync any time''': request &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; and you get a full package;&lt;br /&gt;
the server resets its baseline to match, so the deltas that follow are&lt;br /&gt;
relative to that full — use this if you ever suspect drift. '''A full&lt;br /&gt;
can still arrive unrequested''' (the rebase cases above) and always&lt;br /&gt;
replaces your entire prompt state; never diff a full against your&lt;br /&gt;
model, just adopt it.&lt;br /&gt;
&lt;br /&gt;
Values in a delta are byte-identical to what the same key would carry&lt;br /&gt;
in a full &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt; — same types, same formatting, only the&lt;br /&gt;
selection of keys differs. Immortal-only keys follow the same&lt;br /&gt;
present-for-imms/absent-otherwise rule as fulls.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.score&amp;lt;/code&amp;gt; — request-only ====&lt;br /&gt;
&lt;br /&gt;
A single snapshot of the full score sheet, grouped:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;identity&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Merlin&amp;quot;, &amp;quot;pretitle&amp;quot;: &amp;quot;the Great&amp;quot;, &amp;quot;title&amp;quot;: &amp;quot;Mighty Wizard&amp;quot;,&lt;br /&gt;
    &amp;quot;posttitle&amp;quot;: &amp;quot;of the Tower&amp;quot;, &amp;quot;sex&amp;quot;: &amp;quot;Male&amp;quot;, &amp;quot;age&amp;quot;: 156,&lt;br /&gt;
    &amp;quot;played&amp;quot;: 5000000, &amp;quot;hometown&amp;quot;: &amp;quot;Midgaard&amp;quot;, &amp;quot;clan&amp;quot;: &amp;quot;Archmages&amp;quot;,&lt;br /&gt;
    &amp;quot;level&amp;quot;: 25, &amp;quot;align&amp;quot;: 450, &amp;quot;practices&amp;quot;: 15, &amp;quot;redemptions&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;pvp&amp;quot;: &amp;quot;PKE, PKOK&amp;quot;, &amp;quot;area&amp;quot;: &amp;quot;The Midgaard Forest&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;vitals&amp;quot;:  { &amp;quot;hp&amp;quot;: 180, &amp;quot;maxHp&amp;quot;: 250, &amp;quot;mana&amp;quot;: 400, &amp;quot;maxMana&amp;quot;: 500,&lt;br /&gt;
               &amp;quot;move&amp;quot;: 120, &amp;quot;maxMove&amp;quot;: 150 },&lt;br /&gt;
  &amp;quot;stats&amp;quot;:   { &amp;quot;str&amp;quot;: 18, &amp;quot;min&amp;quot;: 16, &amp;quot;dex&amp;quot;: 17, &amp;quot;con&amp;quot;: 16, &amp;quot;per&amp;quot;: 14,&lt;br /&gt;
               &amp;quot;spi&amp;quot;: 15, &amp;quot;prestige&amp;quot;: 2 },&lt;br /&gt;
  &amp;quot;combat&amp;quot;:  { &amp;quot;ac&amp;quot;: -45, &amp;quot;hitroll&amp;quot;: 28, &amp;quot;damroll&amp;quot;: 35, &amp;quot;damcap&amp;quot;: 400,&lt;br /&gt;
               &amp;quot;spellCrit&amp;quot;: 12, &amp;quot;spellDam&amp;quot;: 25, &amp;quot;concentration&amp;quot;: 10,&lt;br /&gt;
               &amp;quot;manaReduction&amp;quot;: 15, &amp;quot;damageShield&amp;quot;: 8,&lt;br /&gt;
               &amp;quot;mitigation&amp;quot;: { &amp;quot;cur&amp;quot;: 120, &amp;quot;cap&amp;quot;: 300 },&lt;br /&gt;
               &amp;quot;parry&amp;quot;: 5, &amp;quot;wary&amp;quot;: 0, &amp;quot;wimpy&amp;quot;: 0, &amp;quot;rangedAccuracy&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;weaponSpeed&amp;quot;: 2, &amp;quot;critChance&amp;quot;: 8, &amp;quot;critBonus&amp;quot;: 25,&lt;br /&gt;
               &amp;quot;meleeDamMod&amp;quot;: 0, &amp;quot;dodge&amp;quot;: 12, &amp;quot;block&amp;quot;: 15 },&lt;br /&gt;
  &amp;quot;regen&amp;quot;:   { &amp;quot;hp&amp;quot;: 50, &amp;quot;mana&amp;quot;: 80, &amp;quot;move&amp;quot;: 40 },&lt;br /&gt;
  &amp;quot;xp&amp;quot;:      { &amp;quot;total&amp;quot;: 2500000, &amp;quot;toLevel&amp;quot;: 150000, &amp;quot;eraSplitPct&amp;quot;: 50,&lt;br /&gt;
               &amp;quot;era&amp;quot;: {&lt;br /&gt;
                 &amp;quot;ancient&amp;quot;:    { &amp;quot;exp&amp;quot;: 750000, &amp;quot;levels&amp;quot;: 15, &amp;quot;used&amp;quot;: 10, &amp;quot;free&amp;quot;: 5 },&lt;br /&gt;
                 &amp;quot;medieval&amp;quot;:   { &amp;quot;exp&amp;quot;: 1000000, &amp;quot;levels&amp;quot;: 20, &amp;quot;used&amp;quot;: 15, &amp;quot;free&amp;quot;: 5 },&lt;br /&gt;
                 &amp;quot;industrial&amp;quot;: { &amp;quot;exp&amp;quot;: 0, &amp;quot;levels&amp;quot;: 0, &amp;quot;used&amp;quot;: 0, &amp;quot;free&amp;quot;: 0 }&lt;br /&gt;
               } },&lt;br /&gt;
  &amp;quot;carry&amp;quot;:   { &amp;quot;items&amp;quot;: 25, &amp;quot;weight&amp;quot;: 450, &amp;quot;maxWeight&amp;quot;: 500,&lt;br /&gt;
               &amp;quot;rent&amp;quot;: 1200, &amp;quot;maxRent&amp;quot;: 2000 },&lt;br /&gt;
  &amp;quot;gold&amp;quot;: 50000,&lt;br /&gt;
  &amp;quot;bank&amp;quot;: 100000,&lt;br /&gt;
  &amp;quot;resistances&amp;quot;: [ { &amp;quot;name&amp;quot;: &amp;quot;fire&amp;quot;, &amp;quot;value&amp;quot;: 15 },&lt;br /&gt;
                   { &amp;quot;name&amp;quot;: &amp;quot;cold&amp;quot;, &amp;quot;value&amp;quot;: -10 } ]&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nullable fields — treat &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; as “not applicable”:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;identity.clan&amp;lt;/code&amp;gt; — no clan; &amp;lt;code&amp;gt;identity.area&amp;lt;/code&amp;gt; — unknown area.&lt;br /&gt;
* &amp;lt;code&amp;gt;xp.toLevel&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; above level 50 (no further levels). Below 50 it is XP to the next level; at exactly 50, XP to redeem.&lt;br /&gt;
* &amp;lt;code&amp;gt;xp.eraSplitPct&amp;lt;/code&amp;gt; and every &amp;lt;code&amp;gt;xp.era.*.exp&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; below level 50 for non-remorts (the text SCORE shows &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; there; the detail is hidden until you reach 50).&lt;br /&gt;
* &amp;lt;code&amp;gt;carry.maxRent&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; above level 50 (unlimited).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sex&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;&amp;amp;quot;Male&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;Female&amp;amp;quot;&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;&amp;amp;quot;Other&amp;amp;quot;&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;pvp&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;&amp;amp;quot;PKE&amp;amp;quot;&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;quot;PKOK&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;PKE, PKOK&amp;amp;quot;&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;&amp;amp;quot;none&amp;amp;quot;&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;resistances&amp;lt;/code&amp;gt; has one entry per&lt;br /&gt;
nonzero damage modifier; empty array when you have none.&lt;br /&gt;
&lt;br /&gt;
Conditions, affects, and timers are deliberately ''not'' here — see&lt;br /&gt;
&amp;lt;code&amp;gt;char.status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.status&amp;lt;/code&amp;gt; — request-only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;{ conditions, affectedBy, timers }&amp;lt;/code&amp;gt;, each an array or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;. Three&lt;br /&gt;
sub-packages return one slice each, in the same shapes:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;char.status.conditions&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;{ &amp;amp;quot;conditions&amp;amp;quot;: [&amp;amp;quot;hungry&amp;amp;quot;, …] | null }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;char.status.affectedby&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;{ &amp;amp;quot;affectedBy&amp;amp;quot;: [{ &amp;amp;quot;time&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;, … }, …] | null }&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;time&amp;lt;/code&amp;gt; is remaining seconds; stacked copies of the same affect collapse into one entry. Each entry can also carry &amp;lt;code&amp;gt;applies&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;grants&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dmgMods&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;resists&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;immunities&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;susceptibilities&amp;lt;/code&amp;gt; — see below. The &amp;lt;code&amp;gt;affectedBy&amp;lt;/code&amp;gt; member embedded directly in &amp;lt;code&amp;gt;char.status&amp;lt;/code&amp;gt; is built the same way and carries identical entries.&lt;br /&gt;
&lt;br /&gt;
'''Affect payload''' — additive, no opt-in, no new package. &amp;lt;code&amp;gt;time&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; are unchanged; &amp;lt;code&amp;gt;disposition&amp;lt;/code&amp;gt; is '''always present'''; every other&lt;br /&gt;
new key is '''omitted when it would be empty''', so a&lt;br /&gt;
&amp;lt;code&amp;gt;{ &amp;amp;quot;time&amp;amp;quot;, &amp;amp;quot;name&amp;amp;quot;, &amp;amp;quot;disposition&amp;amp;quot; }&amp;lt;/code&amp;gt; entry is still normal and common&lt;br /&gt;
(e.g. a flag-only or otherwise-inert affect). Example of a&lt;br /&gt;
fully-loaded entry:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;time&amp;quot;: 512,&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;armor of faith&amp;quot;,&lt;br /&gt;
  &amp;quot;disposition&amp;quot;: &amp;quot;beneficial&amp;quot;,&lt;br /&gt;
  &amp;quot;applies&amp;quot;:          { &amp;quot;ac&amp;quot;: -20, &amp;quot;saving_spell&amp;quot;: -2 },&lt;br /&gt;
  &amp;quot;grants&amp;quot;:           [ &amp;quot;sanctuary&amp;quot; ],&lt;br /&gt;
  &amp;quot;dmgMods&amp;quot;:          { &amp;quot;slash&amp;quot;: 10 },&lt;br /&gt;
  &amp;quot;resists&amp;quot;:          [ &amp;quot;fire&amp;quot; ],&lt;br /&gt;
  &amp;quot;immunities&amp;quot;:       [ &amp;quot;poison&amp;quot; ],&lt;br /&gt;
  &amp;quot;susceptibilities&amp;quot;: [ &amp;quot;cold&amp;quot; ]&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;disposition&amp;lt;/code&amp;gt; — always one of &amp;lt;code&amp;gt;&amp;amp;quot;beneficial&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;detrimental&amp;amp;quot;&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;&amp;amp;quot;neutral&amp;amp;quot;&amp;lt;/code&amp;gt;; how the game classifies the affect (the same classification that colors the affect’s name green/red in the text affects list). If an affect somehow carries both classifications, &amp;lt;code&amp;gt;detrimental&amp;lt;/code&amp;gt; wins. Exactly these three strings — but treat an unknown value as &amp;lt;code&amp;gt;neutral&amp;lt;/code&amp;gt; rather than erroring, per the usual forward-compatibility rule. Beneficial affects are player-removable: a UI may offer a remove control on &amp;lt;code&amp;gt;&amp;amp;quot;beneficial&amp;amp;quot;&amp;lt;/code&amp;gt; entries that sends &amp;lt;code&amp;gt;removeaffect &amp;amp;lt;name&amp;amp;gt;&amp;lt;/code&amp;gt; (the entry’s &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; verbatim) — word the player-facing confirmation &amp;lt;code&amp;gt;Remove &amp;amp;lt;name&amp;amp;gt;?&amp;lt;/code&amp;gt;, not the command name. Don’t offer it on detrimental/neutral entries; the server refuses those.&lt;br /&gt;
* &amp;lt;code&amp;gt;applies&amp;lt;/code&amp;gt; — object, numeric stat modifiers this affect currently contributes. Keys are stat names (&amp;lt;code&amp;gt;strength&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;saving_spell&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hp_regen&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ac&amp;lt;/code&amp;gt;, …); values are signed JSON ints (negative values are normal and mean the same thing they do everywhere else — e.g. lower &amp;lt;code&amp;gt;ac&amp;lt;/code&amp;gt; is better).&lt;br /&gt;
* &amp;lt;code&amp;gt;grants&amp;lt;/code&amp;gt; — array of flag names this affect grants (e.g. &amp;lt;code&amp;gt;&amp;amp;quot;sanctuary&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;detect_invis&amp;amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;dmgMods&amp;lt;/code&amp;gt; — object of damage-type → signed percent modifier, e.g. &amp;lt;code&amp;gt;{ &amp;amp;quot;slash&amp;amp;quot;: 10 }&amp;lt;/code&amp;gt; means +10% slash damage. Its damage-type names heavily overlap with &amp;lt;code&amp;gt;resists&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;immunities&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;susceptibilities&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;flame&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;poison&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;slash&amp;lt;/code&amp;gt;, …) but the sets are '''not identical''' — each key’s vocabulary comes from its own server table. Don’t build one fixed shared list; treat each key’s names as its own open vocabulary and ignore unknowns.&lt;br /&gt;
* &amp;lt;code&amp;gt;resists&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;immunities&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;susceptibilities&amp;lt;/code&amp;gt; — arrays of damage-type names this affect resists, grants immunity to, or makes the character more susceptible to.&lt;br /&gt;
* All key/value vocabularies are mechanical lowercase of the game’s internal names — the same information &amp;lt;code&amp;gt;STATUS full&amp;lt;/code&amp;gt; shows a player for that affect, just structured instead of prose. Key names are the server’s mechanical internal names, which sometimes differ from the friendly labels &amp;lt;code&amp;gt;STATUS&amp;lt;/code&amp;gt; prints (e.g., &amp;lt;code&amp;gt;mod_buf_hitroll&amp;lt;/code&amp;gt; is the HITROLL line). This is forward-compatible: new names can appear with no protocol change, so ignore any key or value you don’t recognize rather than treating it as an error.&lt;br /&gt;
* If an affect contributes to the same stat/damage-type more than once (e.g. two stacked sources folded into one entry), the value you receive is already the summed total — you never need to add entries together yourself.&lt;br /&gt;
* &amp;lt;code&amp;gt;char.status.timers&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;{ &amp;amp;quot;timers&amp;amp;quot;: [{ &amp;amp;quot;name&amp;amp;quot;, &amp;amp;quot;time&amp;amp;quot; }, …] | null }&amp;lt;/code&amp;gt; — skill/ability reuse timers.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.offer&amp;lt;/code&amp;gt; — request-only ====&lt;br /&gt;
&lt;br /&gt;
Mirrors the OFFER command: &amp;lt;code&amp;gt;{ &amp;amp;quot;items&amp;amp;quot;: [{ &amp;amp;quot;name&amp;amp;quot;, &amp;amp;quot;rent&amp;amp;quot;, &amp;amp;quot;count&amp;amp;quot; }, …] | null, &amp;amp;quot;totalRent&amp;amp;quot;, &amp;amp;quot;totalItems&amp;amp;quot; }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.colors&amp;lt;/code&amp;gt; — request, login push, and config-change push ====&lt;br /&gt;
&lt;br /&gt;
The player’s own condition colors (the mud’s &amp;lt;code&amp;gt;color&amp;lt;/code&amp;gt; slots 16–20) in&lt;br /&gt;
compiled form, so you can tint hp/mana/mv gauges, prompt tiles, and&lt;br /&gt;
group bars exactly the way the player’s text prompt does. Request with&lt;br /&gt;
an empty body; also pushed once at login/reconnect and whenever the&lt;br /&gt;
player’s color config changes (&amp;lt;code&amp;gt;color set&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;color scheme&amp;lt;/code&amp;gt; /&lt;br /&gt;
&amp;lt;code&amp;gt;color set default&amp;lt;/code&amp;gt;). Every message is a full snapshot — adopt it&lt;br /&gt;
wholesale, never merge. Always complete (scheme defaults fill slots the&lt;br /&gt;
player never touched), never &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;condition&amp;quot;: {&lt;br /&gt;
    &amp;quot;full&amp;quot;:     { &amp;quot;fg&amp;quot;: 2,  &amp;quot;bg&amp;quot;: -1, &amp;quot;attrs&amp;quot;: [] },&lt;br /&gt;
    &amp;quot;low&amp;quot;:      { &amp;quot;fg&amp;quot;: 10, &amp;quot;bg&amp;quot;: -1, &amp;quot;attrs&amp;quot;: [] },&lt;br /&gt;
    &amp;quot;medium&amp;quot;:   { &amp;quot;fg&amp;quot;: 3,  &amp;quot;bg&amp;quot;: -1, &amp;quot;attrs&amp;quot;: [&amp;quot;bold&amp;quot;] },&lt;br /&gt;
    &amp;quot;bad&amp;quot;:      { &amp;quot;fg&amp;quot;: 1,  &amp;quot;bg&amp;quot;: -1, &amp;quot;attrs&amp;quot;: [&amp;quot;bold&amp;quot;] },&lt;br /&gt;
    &amp;quot;critical&amp;quot;: { &amp;quot;fg&amp;quot;: 9,  &amp;quot;bg&amp;quot;: -1, &amp;quot;attrs&amp;quot;: [&amp;quot;blink&amp;quot;] }&lt;br /&gt;
} }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;fg&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;bg&amp;lt;/code&amp;gt; are classic 16-color palette indices (0–7 normal, 8–15&lt;br /&gt;
bright) or -1 for terminal default; render through the same palette&lt;br /&gt;
your output pane uses for ANSI SGR. &amp;lt;code&amp;gt;attrs&amp;lt;/code&amp;gt; draws from &amp;lt;code&amp;gt;&amp;amp;quot;bold&amp;amp;quot;&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;quot;dim&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;italic&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;underline&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;blink&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;reverse&amp;amp;quot;&amp;lt;/code&amp;gt; — same&lt;br /&gt;
semantics as the SGR attributes in output text (&amp;lt;code&amp;gt;bold&amp;lt;/code&amp;gt; can appear&lt;br /&gt;
alongside a 0–7 fg instead of a bright 8–15 fg; render both like the&lt;br /&gt;
output pane would; reinterpreting &amp;lt;code&amp;gt;blink&amp;lt;/code&amp;gt; as a gentle pulse is fine).&lt;br /&gt;
Ignore keys you don’t recognize, at both the group and color-object&lt;br /&gt;
level — more groups may be added without a version bump.&lt;br /&gt;
&lt;br /&gt;
Pick the tier with the server’s integer arithmetic, in this order, on&lt;br /&gt;
the same cur/max you already have from vitals data — do NOT&lt;br /&gt;
reformulate as percentages (rounding disagrees at the boundaries):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;cur &amp;amp;gt;= max            -&amp;amp;gt; full&lt;br /&gt;
cur &amp;amp;lt;= max / 10       -&amp;amp;gt; critical&lt;br /&gt;
cur &amp;amp;lt;= max / 4        -&amp;amp;gt; bad&lt;br /&gt;
cur &amp;amp;lt;= max * 2 / 3    -&amp;amp;gt; medium&lt;br /&gt;
otherwise             -&amp;amp;gt; low&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;code&amp;gt;max &amp;amp;lt;= 0&amp;lt;/code&amp;gt; or the values are hidden, the mud shows &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt; uncolored —&lt;br /&gt;
fall back to your untinted rendering rather than guessing a tier.&lt;br /&gt;
Full contract: &amp;lt;code&amp;gt;docs/updates/2026-07-15-gmcp-char-colors-client-spec.md&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.2 Room and world ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;room.info&amp;lt;/code&amp;gt; — pushed on movement and look, also requestable ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;name&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;desc&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;area&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;vnum&amp;quot;: 3001,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;indoors&amp;quot;, &amp;quot;is_inn&amp;quot;: false,&lt;br /&gt;
  &amp;quot;exits&amp;quot;: [ { &amp;quot;dir&amp;quot;: &amp;quot;north&amp;quot;, &amp;quot;door&amp;quot;: &amp;quot;closed&amp;quot;,&lt;br /&gt;
               &amp;quot;to_name&amp;quot;: &amp;quot;A Quiet Lane&amp;quot;, &amp;quot;to_vnum&amp;quot;: 3005 }, … ] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* '''Darkness''': if your character can’t see, &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;desc&amp;lt;/code&amp;gt; are both &amp;lt;code&amp;gt;&amp;amp;quot;It is too dark to see...&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;exits&amp;lt;/code&amp;gt; is omitted entirely.&lt;br /&gt;
* '''Blindness''': &amp;lt;code&amp;gt;exits&amp;lt;/code&amp;gt; is omitted while blind, whatever the light.&lt;br /&gt;
* &amp;lt;code&amp;gt;area&amp;lt;/code&amp;gt; is present only when the room belongs to a known area.&lt;br /&gt;
* &amp;lt;code&amp;gt;vnum&amp;lt;/code&amp;gt; is present for every room ''except'' rooms inside transient instances, whose recycled vnums are meaningless and suppressed. The same applies to &amp;lt;code&amp;gt;to_vnum&amp;lt;/code&amp;gt; on exits. Don’t key persistent mapper data on instance rooms.&lt;br /&gt;
* &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is always present: one of &amp;lt;code&amp;gt;&amp;amp;quot;indoors&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;underwater&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;aerial&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;water&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;outdoors&amp;amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;is_inn&amp;lt;/code&amp;gt; is always present and is '''character-dependent''': whether ''you'' could rent here ''right now'' (false while fighting, for example). It is not a fixed property of the room. Immortals always see &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;exits&amp;lt;/code&amp;gt; mirrors the in-game autoexit line, including its secrecy rules — hidden or unrevealed exits simply don’t appear. Per exit: &amp;lt;code&amp;gt;dir&amp;lt;/code&amp;gt; always; &amp;lt;code&amp;gt;door&amp;lt;/code&amp;gt; only for door exits (&amp;lt;code&amp;gt;&amp;amp;quot;open&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;closed&amp;amp;quot;&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;&amp;amp;quot;locked&amp;amp;quot;&amp;lt;/code&amp;gt;); &amp;lt;code&amp;gt;to_name&amp;lt;/code&amp;gt; only when the destination’s name is visible.&lt;br /&gt;
&lt;br /&gt;
=== 4.3 Objects, inventory, equipment ===&lt;br /&gt;
&lt;br /&gt;
Objects are identified by '''OID''' — an opaque 64-bit id rendered as a&lt;br /&gt;
hex string with a mandatory &amp;lt;code&amp;gt;0x&amp;lt;/code&amp;gt; prefix (e.g. &amp;lt;code&amp;gt;&amp;amp;quot;0x1a2b3c4d5e6f7890&amp;amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
Always send it back exactly as you received it, prefix included. OIDs&lt;br /&gt;
are how the three packages below link together.&lt;br /&gt;
&lt;br /&gt;
You can only look up objects your character can actually see — the&lt;br /&gt;
same visibility rules as in-game. An unknown, invalid, or unseen OID&lt;br /&gt;
gets &amp;lt;code&amp;gt;{ &amp;amp;quot;oid&amp;amp;quot;: &amp;amp;quot;&amp;amp;lt;what you sent&amp;amp;gt;&amp;amp;quot;, &amp;amp;quot;found&amp;amp;quot;: false }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;object.info&amp;lt;/code&amp;gt; — request with &amp;lt;code&amp;gt;{&amp;amp;quot;oid&amp;amp;quot;: &amp;amp;quot;...&amp;amp;quot;}&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Full detail for one object. The reply always echoes the requested&lt;br /&gt;
&amp;lt;code&amp;gt;oid&amp;lt;/code&amp;gt;. When found and visible:&lt;br /&gt;
&lt;br /&gt;
* Core fields: &amp;lt;code&amp;gt;oid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; (keywords), &amp;lt;code&amp;gt;short&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;desc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; (item-type name), &amp;lt;code&amp;gt;weight&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;rent&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ac&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;timer&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;condition: { &amp;amp;quot;dam&amp;amp;quot;, &amp;amp;quot;damMax&amp;amp;quot; }&amp;lt;/code&amp;gt; — only when the item has a damage / repair ceiling.&lt;br /&gt;
* &amp;lt;code&amp;gt;flags[]&amp;lt;/code&amp;gt; — every item flag set on the object, present only when at least one is set. Names are the lowercase flag words: &amp;lt;code&amp;gt;&amp;amp;quot;glow&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;magic&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;invis&amp;amp;quot;&amp;lt;/code&amp;gt; (the item is invis but you can see it anyway — style it accordingly), &amp;lt;code&amp;gt;&amp;amp;quot;no_repair&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;no_backstab&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;amp;quot;unique&amp;amp;quot;&amp;lt;/code&amp;gt;, and so on. New flags appear automatically as the game adds them, so ignore names you don’t recognize.&lt;br /&gt;
* &amp;lt;code&amp;gt;wearFlags[]&amp;lt;/code&amp;gt; — wear-position names.&lt;br /&gt;
* A '''per-type block''' keyed by the item type, with named fields for that type. Nearly every item type in the game has one; the ones you’ll see most:&lt;br /&gt;
** &amp;lt;code&amp;gt;weapon: { attack, maxDam, quality, speed }&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;speed&amp;lt;/code&amp;gt; is the effective base speed factor. Weapons with an on-hit spell add &amp;lt;code&amp;gt;spellChance&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spell&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spellLevel&amp;lt;/code&amp;gt;; weapons with a secondary attack add &amp;lt;code&amp;gt;secondaryAttack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;secondaryMaxDam&amp;lt;/code&amp;gt; (and &amp;lt;code&amp;gt;secondarySpellChance/secondarySpell/secondarySpellLevel&amp;lt;/code&amp;gt; when the secondary carries a spell). Plain weapons omit all of those.&lt;br /&gt;
** &amp;lt;code&amp;gt;armor: { acApply, material }&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;container: { capacity, capWeight, capSize, flags, keyVal, weightReduction }&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;gun: { numDice, diceSize, charges, maxCharges, ammoType, jamChance, explodeChance, accuracy }&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ammo: { ammoType, shots[, affect] }&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;light&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;drink&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;food&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;wand&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;staff&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scroll&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;potion&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pill&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;money&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;oil&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;powder&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;rune&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spelltool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spellbook&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;instrument&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fountain&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;furniture&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;boat&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bundle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;vehicle&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;currency&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;currencyPile&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fuel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;manaStore&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;lock&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;note&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;seeds&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bandage&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medicament&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medicalTool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dressing&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;portal&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;attack&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;grenade&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;corpse&amp;lt;/code&amp;gt; (NPC corpses: &amp;lt;code&amp;gt;{ mobVnum, undead, skinVnum }&amp;lt;/code&amp;gt;), and a few more — every field is a named integer (or string where noted), so render what you receive.&lt;br /&gt;
** Item types without an interpreted block (decorative/misc items, and a few whose values are internal state) simply omit it.&lt;br /&gt;
* &amp;lt;code&amp;gt;affects[]&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[{ &amp;amp;quot;stat&amp;amp;quot;, &amp;amp;quot;mod&amp;amp;quot; }, …]&amp;lt;/code&amp;gt;, plus &amp;lt;code&amp;gt;{ &amp;amp;quot;stat&amp;amp;quot;: &amp;amp;quot;dmgmod&amp;amp;quot;, &amp;amp;quot;mod&amp;amp;quot;, &amp;amp;quot;pct&amp;amp;quot; }&amp;lt;/code&amp;gt; entries for damage-modifier affects.&lt;br /&gt;
* &amp;lt;code&amp;gt;props{}&amp;lt;/code&amp;gt; — the object’s key/value property table, when it has one.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt; — request, two modes ====&lt;br /&gt;
&lt;br /&gt;
* '''No arguments''' → your base inventory (held, unworn items): &amp;lt;code&amp;gt;{ &amp;amp;quot;items&amp;amp;quot;: [ { …object detail… }, …] }&amp;lt;/code&amp;gt;. Each row is a '''complete &amp;lt;code&amp;gt;object.info&amp;lt;/code&amp;gt; detail object''' — no per-item follow-up fetch needed.&lt;br /&gt;
* '''&amp;lt;code&amp;gt;{&amp;amp;quot;oid&amp;amp;quot;: &amp;amp;quot;&amp;amp;lt;container&amp;amp;gt;&amp;amp;quot;}&amp;lt;/code&amp;gt;''' → that container’s direct contents: &amp;lt;code&amp;gt;{ &amp;amp;quot;oid&amp;amp;quot;, &amp;amp;quot;items&amp;amp;quot;: [ … ] }&amp;lt;/code&amp;gt;, same full-detail entry shape. A closed container answers &amp;lt;code&amp;gt;{ &amp;amp;quot;oid&amp;amp;quot;, &amp;amp;quot;closed&amp;amp;quot;: true, &amp;amp;quot;items&amp;amp;quot;: [] }&amp;lt;/code&amp;gt; (same rule as &amp;lt;code&amp;gt;look in&amp;lt;/code&amp;gt;). Not found / not visible → &amp;lt;code&amp;gt;{ &amp;amp;quot;oid&amp;amp;quot;, &amp;amp;quot;found&amp;amp;quot;: false }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tell the two reply modes apart by the &amp;lt;code&amp;gt;oid&amp;lt;/code&amp;gt; key: container replies&lt;br /&gt;
have it, base-inventory replies don’t.&lt;br /&gt;
&lt;br /&gt;
'''Paging''': replies carry at most 100 rows. A capped reply adds&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;quot;more&amp;amp;quot;: true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;offset&amp;amp;quot;: &amp;amp;lt;n&amp;amp;gt;&amp;lt;/code&amp;gt;; re-send the same request with that&lt;br /&gt;
&amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; added (e.g. &amp;lt;code&amp;gt;{&amp;amp;quot;oid&amp;amp;quot;: &amp;amp;quot;…&amp;amp;quot;, &amp;amp;quot;offset&amp;amp;quot;: 100}&amp;lt;/code&amp;gt;) to get the next&lt;br /&gt;
page, until a reply arrives without &amp;lt;code&amp;gt;more&amp;lt;/code&amp;gt;. Most inventories fit in&lt;br /&gt;
one page.&lt;br /&gt;
&lt;br /&gt;
To walk someone’s whole carry tree, request base inventory, then&lt;br /&gt;
request each container row’s &amp;lt;code&amp;gt;oid&amp;lt;/code&amp;gt; as you (or the user) open it —&lt;br /&gt;
one container level per request.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt; is request/reply only — it never pushes. For live&lt;br /&gt;
updates as your inventory changes during play, see &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt;&lt;br /&gt;
below.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt; — pushed only, coalesced per moment ====&lt;br /&gt;
&lt;br /&gt;
Tells you about '''every object-state change on your character’s&lt;br /&gt;
person''': picked up, dropped, given, worn, removed, moved in or out of&lt;br /&gt;
a carried container, destroyed, and (over time) in-place changes like&lt;br /&gt;
charges and condition. Changes are coalesced server-side — no matter&lt;br /&gt;
how many things happen to your stuff in one game moment, you get at&lt;br /&gt;
most one frame describing the net result, per moment. &amp;lt;code&amp;gt;wear all&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;remove all&amp;lt;/code&amp;gt;, and death each arrive as one message with final state,&lt;br /&gt;
not a hail of per-item deltas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;changed&amp;quot;: [&lt;br /&gt;
    { &amp;quot;loc&amp;quot;: &amp;quot;inv&amp;quot;,                    &amp;quot;item&amp;quot;: { …object detail… } },&lt;br /&gt;
    { &amp;quot;loc&amp;quot;: &amp;quot;worn:head&amp;quot;,              &amp;quot;item&amp;quot;: { … } },&lt;br /&gt;
    { &amp;quot;loc&amp;quot;: &amp;quot;in:0x1a2b3c4d5e6f7890&amp;quot;,  &amp;quot;item&amp;quot;: { … } }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;removed&amp;quot;: [ &amp;quot;0xaabbccddeeff0011&amp;quot; ],&lt;br /&gt;
  &amp;quot;more&amp;quot;: true&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;item&amp;lt;/code&amp;gt; is exactly an &amp;lt;code&amp;gt;object.info&amp;lt;/code&amp;gt; detail object — the same one &amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt; rows and &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; items use.&lt;br /&gt;
* &amp;lt;code&amp;gt;loc&amp;lt;/code&amp;gt; says where the object now lives: &amp;lt;code&amp;gt;&amp;amp;quot;inv&amp;amp;quot;&amp;lt;/code&amp;gt; (carried, unworn, top level), &amp;lt;code&amp;gt;&amp;amp;quot;worn:&amp;amp;lt;slot&amp;amp;gt;&amp;amp;quot;&amp;lt;/code&amp;gt; (the same slot vocabulary as &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt;, below), or &amp;lt;code&amp;gt;&amp;amp;quot;in:&amp;amp;lt;container-oid&amp;amp;gt;&amp;amp;quot;&amp;lt;/code&amp;gt; (direct container only — for nested bags, reconstruct the tree by following each object’s own &amp;lt;code&amp;gt;loc&amp;lt;/code&amp;gt; oid).&lt;br /&gt;
* &amp;lt;code&amp;gt;removed&amp;lt;/code&amp;gt; — oids no longer anywhere on your character. Dropped, given away, put into a container that isn’t carried, or destroyed: all identical here. It means “off your person,” not “gone from the world.” Removal of an oid you’ve never seen is a no-op — silently ignore it, never error (an item picked up and dropped in the same moment can arrive only as a removal).&lt;br /&gt;
* An oid appears in '''exactly one''' of &amp;lt;code&amp;gt;changed&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;removed&amp;lt;/code&amp;gt; per frame. Both keys are '''omitted when empty''' — treat a missing key as &amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;; every frame has at least one of them.&lt;br /&gt;
* '''&amp;lt;code&amp;gt;more: true&amp;lt;/code&amp;gt;''' means a large burst is being delivered across several frames and the rest follows within the next second or so. Each frame is self-contained and correct on its own; &amp;lt;code&amp;gt;more&amp;lt;/code&amp;gt; is a hint (e.g. to debounce a re-sort), not something you must handle.&lt;br /&gt;
* '''Coalescing means final-state-only''': if an item is worn and removed in the same moment, you get one &amp;lt;code&amp;gt;changed&amp;lt;/code&amp;gt; row with its final location — intermediate states are never sent.&lt;br /&gt;
* There is '''no replay'''. &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt; only carries deltas from the moment you’re connected forward. On login or reconnect, request &amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; as usual to get your baseline, then let pushes keep it current.&lt;br /&gt;
&lt;br /&gt;
Recommended model: one oid-keyed map (&amp;lt;code&amp;gt;oid -&amp;amp;gt; {loc, item}&amp;lt;/code&amp;gt;) for&lt;br /&gt;
everything on your character. &amp;lt;code&amp;gt;changed&amp;lt;/code&amp;gt; upserts by &amp;lt;code&amp;gt;item.oid&amp;lt;/code&amp;gt;;&lt;br /&gt;
&amp;lt;code&amp;gt;removed&amp;lt;/code&amp;gt; deletes by oid. Inventory panel = entries with&lt;br /&gt;
&amp;lt;code&amp;gt;loc == &amp;amp;quot;inv&amp;amp;quot;&amp;lt;/code&amp;gt;; equipment panel = entries with &amp;lt;code&amp;gt;loc&amp;lt;/code&amp;gt; starting&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;amp;quot;worn:&amp;amp;quot;&amp;lt;/code&amp;gt;; a bag’s contents = entries with &amp;lt;code&amp;gt;loc == &amp;amp;quot;in:&amp;amp;lt;bag's oid&amp;amp;gt;&amp;amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
Full detail, including an incremental adoption ladder (you don’t have&lt;br /&gt;
to build the full merge on day one), is in&lt;br /&gt;
&amp;lt;code&amp;gt;docs/updates/2026-07-14-gmcp-char-items-update-client-spec.md&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; — request-only ====&lt;br /&gt;
&lt;br /&gt;
Request (no arguments) → '''full snapshot''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;full&amp;quot;: true,&lt;br /&gt;
  &amp;quot;equipment&amp;quot;: [ { &amp;quot;slot&amp;quot;: &amp;quot;wield&amp;quot;, &amp;quot;item&amp;quot;: { …object detail… } }, … ] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;item&amp;lt;/code&amp;gt; is exactly an &amp;lt;code&amp;gt;object.info&amp;lt;/code&amp;gt; detail object. Empty &amp;lt;code&amp;gt;equipment&amp;lt;/code&amp;gt;&lt;br /&gt;
array when nothing is worn.&lt;br /&gt;
&lt;br /&gt;
'''Slot keys''' are unique per body position (left and right are&lt;br /&gt;
distinct, so keying your equipment map by slot never clobbers a pair):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;light, finger_l, finger_r, neck_1, neck_2, body, head, face, legs,&lt;br /&gt;
feet, hands, arms, shield, about, waist, wrist_l, wrist_r, wield,&lt;br /&gt;
held, ear_l, ear_r, arm, aux, amulet&amp;lt;/pre&amp;gt;&lt;br /&gt;
A slot the server can’t classify reports as &amp;lt;code&amp;gt;&amp;amp;quot;unknown&amp;amp;quot;&amp;lt;/code&amp;gt; rather than&lt;br /&gt;
being dropped.&lt;br /&gt;
&lt;br /&gt;
'''2026-07-14: no more pushed deltas.''' &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; used to also&lt;br /&gt;
push per-item &amp;lt;code&amp;gt;&amp;amp;quot;full&amp;amp;quot;: false&amp;lt;/code&amp;gt; deltas as you wore/removed things,&lt;br /&gt;
coalesced during bulk wear/remove into one &amp;lt;code&amp;gt;full: true&amp;lt;/code&amp;gt; snapshot.&lt;br /&gt;
Those pushes are gone — equipment changes now arrive through&lt;br /&gt;
&amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt; (above), which covers your whole person, not just&lt;br /&gt;
worn items. &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; is request/reply only now: fetch it for&lt;br /&gt;
your initial snapshot and whenever you want to resync your equipment&lt;br /&gt;
map from scratch.&lt;br /&gt;
&lt;br /&gt;
=== 4.4 Skills ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;skills.all&amp;lt;/code&amp;gt; — static reference, request once per session ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;skills&amp;quot;: [&lt;br /&gt;
    { &amp;quot;name&amp;quot;: &amp;quot;kick&amp;quot;,    &amp;quot;slot&amp;quot;: 63, &amp;quot;type&amp;quot;: &amp;quot;fight&amp;quot;,  &amp;quot;trainLevels&amp;quot;: [] },&lt;br /&gt;
    { &amp;quot;name&amp;quot;: &amp;quot;bandage&amp;quot;, &amp;quot;slot&amp;quot;: 12, &amp;quot;type&amp;quot;: &amp;quot;druid&amp;quot;,  &amp;quot;trainLevels&amp;quot;: [15, 25] }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* One entry per skill, in slot order. &amp;lt;code&amp;gt;slot&amp;lt;/code&amp;gt; is the durable identifier — join &amp;lt;code&amp;gt;char.skills&amp;lt;/code&amp;gt; on it.&lt;br /&gt;
* &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is the school: &amp;lt;code&amp;gt;weapon&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fight&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;merchant&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;rogue&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;thief&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;druid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medical&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bardic&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gun&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mage&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;runic&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ranger&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;miscellaneous&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;none&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;trainLevels&amp;lt;/code&amp;gt; — character levels where extra training tiers unlock (the raw schedule, not adjusted for your character); empty for single-tier skills. Total tiers = &amp;lt;code&amp;gt;trainLevels.length + 1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Spells are not in this table — see §4.5.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.skills&amp;lt;/code&amp;gt; — your skill standing ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;skills&amp;quot;: [&lt;br /&gt;
    { &amp;quot;slot&amp;quot;: 63, &amp;quot;qualifies&amp;quot;: true,  &amp;quot;known&amp;quot;: 1 },&lt;br /&gt;
    { &amp;quot;slot&amp;quot;: 12, &amp;quot;qualifies&amp;quot;: false, &amp;quot;known&amp;quot;: 2 }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
The union of the SKILLS and ALLSKILLS views. A slot appears iff you’ve&lt;br /&gt;
learned it or currently qualify for it:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! state&lt;br /&gt;
! &amp;lt;code&amp;gt;qualifies&amp;lt;/code&amp;gt;&lt;br /&gt;
! &amp;lt;code&amp;gt;known&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| qualify, haven’t learned&lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| learned and still qualify&lt;br /&gt;
| &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| learned, lost the prerequisites&lt;br /&gt;
| &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;known&amp;lt;/code&amp;gt; is the trained tier count, '''not''' a percentage.&lt;br /&gt;
&lt;br /&gt;
=== 4.5 Magic: spells and words ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spells.all&amp;lt;/code&amp;gt; — static reference; one request, four replies ====&lt;br /&gt;
&lt;br /&gt;
Requesting &amp;lt;code&amp;gt;spells.all&amp;lt;/code&amp;gt; sends four messages, one per school batch:&lt;br /&gt;
&amp;lt;code&amp;gt;spells.know&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spells.create&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spells.cause&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;spells.noschool&amp;lt;/code&amp;gt;&lt;br /&gt;
(wordless spells — includes affect-carriers and procs, so you can name&lt;br /&gt;
any slot you ever see). Each has the same shape:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;spells&amp;quot;: [&lt;br /&gt;
    { &amp;quot;name&amp;quot;: &amp;quot;identify&amp;quot;, &amp;quot;slot&amp;quot;: 530, &amp;quot;mana&amp;quot;: 10, &amp;quot;listed&amp;quot;: true,&lt;br /&gt;
      &amp;quot;words&amp;quot;: [1], &amp;quot;categories&amp;quot;: [&amp;quot;utility&amp;quot;], &amp;quot;element&amp;quot;: &amp;quot;none&amp;quot; },&lt;br /&gt;
    { &amp;quot;name&amp;quot;: &amp;quot;immolation&amp;quot;, &amp;quot;slot&amp;quot;: 657, &amp;quot;mana&amp;quot;: 52, &amp;quot;listed&amp;quot;: true,&lt;br /&gt;
      &amp;quot;words&amp;quot;: [5, 14, 20], &amp;quot;categories&amp;quot;: [&amp;quot;dd&amp;quot;], &amp;quot;element&amp;quot;: &amp;quot;fire&amp;quot; }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;slot&amp;lt;/code&amp;gt; is the durable identifier — join &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;char.spell.update&amp;lt;/code&amp;gt; on it.&lt;br /&gt;
* &amp;lt;code&amp;gt;mana&amp;lt;/code&amp;gt; is the base cost. &amp;lt;code&amp;gt;listed&amp;lt;/code&amp;gt; = appears in ALLSPELLS.&lt;br /&gt;
* &amp;lt;code&amp;gt;words&amp;lt;/code&amp;gt; — word ids in chant order (0–3 of them; always empty in &amp;lt;code&amp;gt;spells.noschool&amp;lt;/code&amp;gt;, never empty in the other three). Join against &amp;lt;code&amp;gt;words.all&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;categories&amp;lt;/code&amp;gt; — what the spell does: &amp;lt;code&amp;gt;dd&amp;lt;/code&amp;gt; (direct damage), &amp;lt;code&amp;gt;dot&amp;lt;/code&amp;gt; (damage over time), &amp;lt;code&amp;gt;buff&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;debuff&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;heal&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;summon&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;utility&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;necromancy&amp;lt;/code&amp;gt;. A spell can carry several (drown is &amp;lt;code&amp;gt;[&amp;amp;quot;dd&amp;amp;quot;,&amp;amp;quot;dot&amp;amp;quot;]&amp;lt;/code&amp;gt;); placeholder slots carry &amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;element&amp;lt;/code&amp;gt; — the damage flavor for &amp;lt;code&amp;gt;dd&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;dot&amp;lt;/code&amp;gt; spells: &amp;lt;code&amp;gt;fire&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ice&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magic&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;death&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt;. Always present; &amp;lt;code&amp;gt;&amp;amp;quot;none&amp;amp;quot;&amp;lt;/code&amp;gt; for non-damage spells.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;words.all&amp;lt;/code&amp;gt; — static reference ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;words&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 1,  &amp;quot;name&amp;quot;: &amp;quot;vid&amp;quot;,  &amp;quot;meaning&amp;quot;: &amp;quot;know&amp;quot;, &amp;quot;circle&amp;quot;: 1 },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 14, &amp;quot;name&amp;quot;: &amp;quot;agni&amp;quot;, &amp;quot;meaning&amp;quot;: &amp;quot;fire&amp;quot;, &amp;quot;circle&amp;quot;: 3 }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
All words, in id order. The stat/level requirements for learning a&lt;br /&gt;
word are deliberately not exposed — &amp;lt;code&amp;gt;char.words&amp;lt;/code&amp;gt;’s &amp;lt;code&amp;gt;qualifies&amp;lt;/code&amp;gt; field&lt;br /&gt;
is the verdict.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.words&amp;lt;/code&amp;gt; — your word standing ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;words&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 1, &amp;quot;learned&amp;quot;: true,  &amp;quot;qualifies&amp;quot;: true },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 3, &amp;quot;learned&amp;quot;: false, &amp;quot;qualifies&amp;quot;: true },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 8, &amp;quot;learned&amp;quot;: true,  &amp;quot;qualifies&amp;quot;: false }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Union of the WORDS and ALLWORDS views; same three-state logic as&lt;br /&gt;
&amp;lt;code&amp;gt;char.skills&amp;lt;/code&amp;gt;. Non-chanters get &amp;lt;code&amp;gt;{ &amp;amp;quot;words&amp;amp;quot;: [] }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt; — your spellbook ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;spells&amp;quot;: [ { &amp;quot;slot&amp;quot;: 507, &amp;quot;level&amp;quot;: 12 }, { &amp;quot;slot&amp;quot;: 530, &amp;quot;level&amp;quot;: 3 } ] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Every spell you’ve cast at least once. &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; is the displayed spell&lt;br /&gt;
level from SPELLBOOK. Non-chanters get &amp;lt;code&amp;gt;{ &amp;amp;quot;spells&amp;amp;quot;: [] }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.spell.update&amp;lt;/code&amp;gt; — pushed only ====&lt;br /&gt;
&lt;br /&gt;
A single-spell delta with &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt; field semantics, pushed when a&lt;br /&gt;
spell’s level changes through play — first cast (&amp;lt;code&amp;gt;&amp;amp;quot;level&amp;amp;quot;: 0&amp;lt;/code&amp;gt;),&lt;br /&gt;
mastery gain, or spellbook study:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;slot&amp;quot;: 507, &amp;quot;level&amp;quot;: 13 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Not requestable. Administrative bulk changes to a character’s spells&lt;br /&gt;
do '''not''' push updates — if you have reason to think that happened,&lt;br /&gt;
re-request &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.6 Runes ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;runes.all&amp;lt;/code&amp;gt; — static reference ====&lt;br /&gt;
&lt;br /&gt;
The full rune table, as RUNES FULL would show a master runecaster:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;runes&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 0, &amp;quot;name&amp;quot;: &amp;quot;fehu&amp;quot;, &amp;quot;aett&amp;quot;: &amp;quot;Freyr&amp;quot;, &amp;quot;cost&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;costMerkstave&amp;quot;: 12, &amp;quot;merkstave&amp;quot;: true,&lt;br /&gt;
      &amp;quot;description&amp;quot;: &amp;quot;Restores movement over time. Merkstave: ...&amp;quot; },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 7, &amp;quot;name&amp;quot;: &amp;quot;wunjo&amp;quot;, &amp;quot;aett&amp;quot;: &amp;quot;Freyr&amp;quot;, &amp;quot;cost&amp;quot;: 24,&lt;br /&gt;
      &amp;quot;costMerkstave&amp;quot;: 0, &amp;quot;merkstave&amp;quot;: false,&lt;br /&gt;
      &amp;quot;description&amp;quot;: &amp;quot;Fast mana regeneration.&amp;quot; }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; is fully durable (it never changes, even across reboots).&lt;br /&gt;
* &amp;lt;code&amp;gt;aett&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;Freyr&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Heimdall&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;Tyr&amp;lt;/code&amp;gt; — 8 runes each, in id order.&lt;br /&gt;
* Costs are base values; if the caster has aett focus, the effective cost is one third — apply that client-side if you display costs.&lt;br /&gt;
* &amp;lt;code&amp;gt;merkstave&amp;lt;/code&amp;gt; = the rune can be cast reversed; &amp;lt;code&amp;gt;costMerkstave&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; when it can’t.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.runes&amp;lt;/code&amp;gt; — your learned runes ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;runes&amp;quot;: [0, 2, 5, 11] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Just the learned ids, in order. Non-runecasters get &amp;lt;code&amp;gt;{ &amp;amp;quot;runes&amp;amp;quot;: [] }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.7 Era abilities ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;abilities.all&amp;lt;/code&amp;gt; — static reference ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;abilities&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 0, &amp;quot;key&amp;quot;: &amp;quot;ClearCasting&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Clear Casting&amp;quot;,&lt;br /&gt;
      &amp;quot;era&amp;quot;: &amp;quot;ancient&amp;quot;, &amp;quot;maxLevel&amp;quot;: 3, &amp;quot;pk&amp;quot;: false },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 8, &amp;quot;key&amp;quot;: &amp;quot;DeathtrapAvoidance&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Deathtrap Avoidance&amp;quot;,&lt;br /&gt;
      &amp;quot;era&amp;quot;: &amp;quot;industrial&amp;quot;, &amp;quot;maxLevel&amp;quot;: 5, &amp;quot;pk&amp;quot;: false }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; is stable for your session; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; is the durable identifier across reboots. Fetch &amp;lt;code&amp;gt;abilities.all&amp;lt;/code&amp;gt; once per login and join &amp;lt;code&amp;gt;char.abilities&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;ancient&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medieval&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;industrial&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;maxLevel&amp;lt;/code&amp;gt; is the training cap for that ability.&lt;br /&gt;
* &amp;lt;code&amp;gt;pk: true&amp;lt;/code&amp;gt; marks abilities that stop working while you carry pk damage (they still appear in &amp;lt;code&amp;gt;char.abilities&amp;lt;/code&amp;gt; — it’s a use-time gate, not a listing gate).&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.abilities&amp;lt;/code&amp;gt; — your earned abilities ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;abilities&amp;quot;: [ { &amp;quot;id&amp;quot;: 0, &amp;quot;level&amp;quot;: 2 }, { &amp;quot;id&amp;quot;: 7, &amp;quot;level&amp;quot;: 3 } ] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; runs 1..&amp;lt;code&amp;gt;maxLevel&amp;lt;/code&amp;gt;. Characters who haven’t earned any era&lt;br /&gt;
abilities get &amp;lt;code&amp;gt;{ &amp;amp;quot;abilities&amp;amp;quot;: [] }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.8 Tradeskills ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;tradeskills.all&amp;lt;/code&amp;gt; — static reference ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;tradeskills&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 0, &amp;quot;name&amp;quot;: &amp;quot;smithing&amp;quot;, &amp;quot;limited&amp;quot;: true },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 7, &amp;quot;name&amp;quot;: &amp;quot;farming&amp;quot;,  &amp;quot;limited&amp;quot;: false }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; is stable for your session; &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the durable identifier.&lt;br /&gt;
* &amp;lt;code&amp;gt;limited: true&amp;lt;/code&amp;gt; marks the tradeskills that share the capped skill pool; unlimited ones can all be raised freely.&lt;br /&gt;
* Recipes are intentionally not available over GMCP.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.tradeskills&amp;lt;/code&amp;gt; — your levels ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;tradeskills&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 0,  &amp;quot;level&amp;quot;: 42, &amp;quot;title&amp;quot;: &amp;quot;hobbyist&amp;quot; },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 11, &amp;quot;level&amp;quot;: 1,  &amp;quot;title&amp;quot;: &amp;quot;beginner&amp;quot; }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Every tradeskill you can use, including level-0 rows — the same list&lt;br /&gt;
the TRADESKILLS command prints. (Mortals don’t see &amp;lt;code&amp;gt;enchanting&amp;lt;/code&amp;gt; unless&lt;br /&gt;
they currently have access to it.) &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; is the proficiency bracket:&lt;br /&gt;
&amp;lt;code&amp;gt;beginner&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;dabbler&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hobbyist&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apprentice&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;journeyman&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;grand master&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 4.9 Factions ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.factions&amp;lt;/code&amp;gt; — your standings ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;factions&amp;quot;: [&lt;br /&gt;
    { &amp;quot;vnum&amp;quot;: 13306, &amp;quot;name&amp;quot;: &amp;quot;Yama Temple&amp;quot;, &amp;quot;value&amp;quot;: 1000,&lt;br /&gt;
      &amp;quot;min&amp;quot;: 0, &amp;quot;max&amp;quot;: 2000, &amp;quot;status&amp;quot;: &amp;quot;Indifferent&amp;quot; },&lt;br /&gt;
    { &amp;quot;vnum&amp;quot;: 33500, &amp;quot;name&amp;quot;: &amp;quot;Iceland Explorers&amp;quot;, &amp;quot;value&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;min&amp;quot;: 0, &amp;quot;max&amp;quot;: 2999, &amp;quot;status&amp;quot;: &amp;quot;Unknown&amp;quot; }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* One entry per faction you have a standing with (hidden factions are never sent). &amp;lt;code&amp;gt;vnum&amp;lt;/code&amp;gt; is fully durable.&lt;br /&gt;
* &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; is your current standing; &amp;lt;code&amp;gt;min&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; are that faction’s bounds — enough to draw a meter.&lt;br /&gt;
* &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; is the faction’s own label for your current standing; &amp;lt;code&amp;gt;&amp;amp;quot;Unknown&amp;amp;quot;&amp;lt;/code&amp;gt; when your value falls outside its labeled ranges (the FACTIONS command shows the same).&lt;br /&gt;
* There is no &amp;lt;code&amp;gt;factions.all&amp;lt;/code&amp;gt;; each entry already carries the static fields a client needs.&lt;br /&gt;
&lt;br /&gt;
=== 4.10 Moods ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;moods.all&amp;lt;/code&amp;gt; — static reference ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;moods&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 0,  &amp;quot;name&amp;quot;: &amp;quot;normal&amp;quot; },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 27, &amp;quot;name&amp;quot;: &amp;quot;cheerful&amp;quot; }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Every mood, in id order — the same list the MOODS command prints. All&lt;br /&gt;
moods are available to all players. &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; is stable for your session;&lt;br /&gt;
&amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the durable identifier.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.moods&amp;lt;/code&amp;gt; — your mood settings ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;combat&amp;quot;: 27, &amp;quot;talk&amp;quot;: 0, &amp;quot;walk&amp;quot;: 0, &amp;quot;social&amp;quot;: 0, &amp;quot;temporary&amp;quot;: null }&amp;lt;/pre&amp;gt;&lt;br /&gt;
The mood id set in each of the four categories; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;normal&amp;lt;/code&amp;gt;, the&lt;br /&gt;
default. &amp;lt;code&amp;gt;temporary&amp;lt;/code&amp;gt; is the one-shot mood override that the next&lt;br /&gt;
mood-bearing action consumes — &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; when none is pending, which is&lt;br /&gt;
nearly always. Join the ids against &amp;lt;code&amp;gt;moods.all&amp;lt;/code&amp;gt; for names.&lt;br /&gt;
&lt;br /&gt;
=== 4.11 Groups ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;group.info&amp;lt;/code&amp;gt; — request-only ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;groups&amp;quot;: [&lt;br /&gt;
    { &amp;quot;name&amp;quot;: &amp;quot;Merlin&amp;quot;, &amp;quot;longName&amp;quot;: &amp;quot;Merlin the Great&amp;quot;, &amp;quot;level&amp;quot;: 25,&lt;br /&gt;
      &amp;quot;position&amp;quot;: &amp;quot;Standing&amp;quot;, &amp;quot;rank&amp;quot;: &amp;quot;L&amp;quot;,&lt;br /&gt;
      &amp;quot;hp&amp;quot;: 180, &amp;quot;maxHp&amp;quot;: 250, &amp;quot;mana&amp;quot;: 400, &amp;quot;maxMana&amp;quot;: 500,&lt;br /&gt;
      &amp;quot;move&amp;quot;: 120, &amp;quot;maxMove&amp;quot;: 150, &amp;quot;agg&amp;quot;: 0, &amp;quot;sameRoom&amp;quot;: true }, …&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;rank&amp;lt;/code&amp;gt; is a single character: &amp;lt;code&amp;gt;L&amp;lt;/code&amp;gt; = leader, &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; = the character you&lt;br /&gt;
follow, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = next-in-line leader, space = ordinary member.&lt;br /&gt;
&amp;lt;code&amp;gt;sameRoom&amp;lt;/code&amp;gt; is true when that member is in the same room as you —&lt;br /&gt;
useful for graying out members you can’t currently assist.&lt;br /&gt;
&lt;br /&gt;
=== 4.12 Help ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;help.topic&amp;lt;/code&amp;gt; — request with &amp;lt;code&amp;gt;{&amp;amp;quot;keywords&amp;amp;quot;: &amp;amp;quot;...&amp;amp;quot;}&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Fetches a helpfile — the same content the &amp;lt;code&amp;gt;HELP&amp;lt;/code&amp;gt; command prints,&lt;br /&gt;
without the banner.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;help.topic {&amp;amp;quot;keywords&amp;amp;quot;: &amp;amp;quot;pk&amp;amp;quot;}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;keywords&amp;quot;: &amp;quot;pk&amp;quot;, &amp;quot;found&amp;quot;: true,&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;PK PKILL PLAYERKILLING&amp;quot;,&lt;br /&gt;
  &amp;quot;text&amp;quot;: &amp;quot;Pkill, also known as Playerkilling, …&amp;quot; }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Keywords resolve exactly like &amp;lt;code&amp;gt;HELP&amp;lt;/code&amp;gt;: case-insensitive, and aliases work (&amp;lt;code&amp;gt;pk&amp;lt;/code&amp;gt; finds the pkill file). Omit &amp;lt;code&amp;gt;keywords&amp;lt;/code&amp;gt; (or send &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;) and you get the same summary a bare &amp;lt;code&amp;gt;HELP&amp;lt;/code&amp;gt; shows, with &amp;lt;code&amp;gt;&amp;amp;quot;keywords&amp;amp;quot;: &amp;amp;quot;summary&amp;amp;quot;&amp;lt;/code&amp;gt; echoed back.&lt;br /&gt;
* &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; is the topic’s keyword line, uppercased — use it as the window header. &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; is the raw helpfile body (plain text with newlines).&lt;br /&gt;
* &amp;lt;code&amp;gt;found: false&amp;lt;/code&amp;gt; (with empty &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;) means no helpfile you can read matches — nonexistent and restricted topics are indistinguishable by design.&lt;br /&gt;
* The reply always has these four fields, so you can parse it with a fixed shape.&lt;br /&gt;
&lt;br /&gt;
=== 4.13 Journal ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt; — request, also pushed ====&lt;br /&gt;
&lt;br /&gt;
Your full quest journal — every entry you currently hold, complete and&lt;br /&gt;
incomplete alike:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;entries&amp;quot;: [&lt;br /&gt;
    { &amp;quot;vnum&amp;quot;: 4108, &amp;quot;name&amp;quot;: &amp;quot;The Lost Heirloom&amp;quot;, &amp;quot;area&amp;quot;: &amp;quot;midgaard&amp;quot;,&lt;br /&gt;
      &amp;quot;complete&amp;quot;: false, &amp;quot;stagesDone&amp;quot;: 1, &amp;quot;stagesTotal&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;lastUpdated&amp;quot;: 1752438000 },&lt;br /&gt;
    { &amp;quot;vnum&amp;quot;: 4200, &amp;quot;name&amp;quot;: &amp;quot;Trial by Fire&amp;quot;, &amp;quot;area&amp;quot;: &amp;quot;asgard&amp;quot;,&lt;br /&gt;
      &amp;quot;complete&amp;quot;: true, &amp;quot;stagesDone&amp;quot;: 2, &amp;quot;stagesTotal&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;lastUpdated&amp;quot;: 0 }&lt;br /&gt;
] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* One row per entry you hold, in catalog order. &amp;lt;code&amp;gt;stagesDone&amp;lt;/code&amp;gt; equals &amp;lt;code&amp;gt;stagesTotal&amp;lt;/code&amp;gt; once &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;; otherwise it’s how many stages you’ve finished so far.&lt;br /&gt;
* &amp;lt;code&amp;gt;lastUpdated&amp;lt;/code&amp;gt; is a raw epoch-seconds timestamp — format it client-side. '''It can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;''' on an entry you haven’t touched this session: the timestamp isn’t saved to your player file, so it only starts counting once something about that entry changes while you’re online (added, a stage completes, it completes, or it’s removed).&lt;br /&gt;
* An empty journal replies &amp;lt;code&amp;gt;{ &amp;amp;quot;entries&amp;amp;quot;: [] }&amp;lt;/code&amp;gt;, same as any other per-character list package.&lt;br /&gt;
* '''Pushed''': the server re-sends this same full snapshot — not a delta — every time a journal entry is added, a stage completes, an entry completes, or an entry is removed. Treat every &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt; message (requested or pushed) as a full replace of your local list.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;char.journal.entry&amp;lt;/code&amp;gt; — request with &amp;lt;code&amp;gt;{&amp;amp;quot;vnum&amp;amp;quot;: N}&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Detail for one journal entry:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;char.journal.entry {&amp;amp;quot;vnum&amp;amp;quot;: 4108}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;{ &amp;quot;vnum&amp;quot;: 4108, &amp;quot;found&amp;quot;: true, &amp;quot;name&amp;quot;: &amp;quot;The Lost Heirloom&amp;quot;,&lt;br /&gt;
  &amp;quot;area&amp;quot;: &amp;quot;midgaard&amp;quot;,&lt;br /&gt;
  &amp;quot;description&amp;quot;: &amp;quot;An old family amulet has gone missing from the manor.&amp;quot;,&lt;br /&gt;
  &amp;quot;complete&amp;quot;: false,&lt;br /&gt;
  &amp;quot;stages&amp;quot;: [&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 1, &amp;quot;text&amp;quot;: &amp;quot;Find the amulet.&amp;quot;, &amp;quot;done&amp;quot;: true },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 2, &amp;quot;text&amp;quot;: &amp;quot;Return it to Lady Anne.&amp;quot;, &amp;quot;done&amp;quot;: false },&lt;br /&gt;
    { &amp;quot;id&amp;quot;: 3, &amp;quot;text&amp;quot;: &amp;quot;Report back to the mayor.&amp;quot;, &amp;quot;done&amp;quot;: false }&lt;br /&gt;
  ] }&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;stages&amp;lt;/code&amp;gt; always lists every stage’s text, whether done or not — a &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt; entry reports every stage &amp;lt;code&amp;gt;done: true&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Never pushed — if you keep a detail pane open for an entry, re-fetch it after the next &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt; push.&lt;br /&gt;
* '''Unknown, unheld, and malformed requests all get the same reply''': &amp;lt;code&amp;gt;{ &amp;amp;quot;vnum&amp;amp;quot;: N, &amp;amp;quot;found&amp;amp;quot;: false }&amp;lt;/code&amp;gt; — nothing else. That covers a vnum that doesn’t exist, a real quest vnum you don’t currently hold, and a request with a missing or non-numeric &amp;lt;code&amp;gt;vnum&amp;lt;/code&amp;gt; (which echoes back as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;). This is deliberate: the reply gives you no way to tell “no such quest” from “not your quest,” so &amp;lt;code&amp;gt;char.journal.entry&amp;lt;/code&amp;gt; can’t be used to fish for quests in the game you haven’t found yet.&lt;br /&gt;
* There’s no &amp;lt;code&amp;gt;journals.all&amp;lt;/code&amp;gt; — LegendMUD doesn’t ship a static catalog of every quest in the game the way it does for skills or spells, since that would spoil quests you haven’t discovered. Fetch &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt; for what you hold, and &amp;lt;code&amp;gt;char.journal.entry&amp;lt;/code&amp;gt; per vnum for detail; don’t wait for a bulk catalog package that isn’t coming.&lt;br /&gt;
&lt;br /&gt;
== 5. What the server pushes ==&lt;br /&gt;
&lt;br /&gt;
Everything else is request-only. These arrive on their own:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Package&lt;br /&gt;
! When&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.prompt&amp;lt;/code&amp;gt;&lt;br /&gt;
| every prompt — your main live-vitals feed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.prompt.delta&amp;lt;/code&amp;gt;&lt;br /&gt;
| opt-in: changed prompt keys only on output-triggered renders&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;room.info&amp;lt;/code&amp;gt;&lt;br /&gt;
| every room change and LOOK&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt;&lt;br /&gt;
| any object-state change on your person (get, drop, wear, remove, container moves); at most one coalesced frame per game moment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.spell.update&amp;lt;/code&amp;gt;&lt;br /&gt;
| a spell’s level changes through play&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt; (full snapshot)&lt;br /&gt;
| a journal entry is added, a stage completes, an entry completes, or an entry is removed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;char.colors&amp;lt;/code&amp;gt; (full snapshot)&lt;br /&gt;
| once at login/reconnect, then whenever the player’s color config changes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logging.error&amp;lt;/code&amp;gt;&lt;br /&gt;
| your request couldn’t be handled&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt; no longer pushes — it’s request/reply only now (§4.3).&lt;br /&gt;
Use &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt; to keep your equipment and inventory current.&lt;br /&gt;
&lt;br /&gt;
A practical session bootstrap:&lt;br /&gt;
&lt;br /&gt;
# Negotiate GMCP (§1).&lt;br /&gt;
# Request the static tables you care about: &amp;lt;code&amp;gt;skills.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spells.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;words.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;runes.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;abilities.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tradeskills.all&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;moods.all&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Request your character’s state: &amp;lt;code&amp;gt;char.score&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.skills&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.spells&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.words&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.runes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.abilities&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.tradeskills&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.factions&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.moods&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.inventory&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.equipment&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;group.info&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;char.journal&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Let the pushes keep &amp;lt;code&amp;gt;prompt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;inventory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;equipment&amp;lt;/code&amp;gt; (via &amp;lt;code&amp;gt;char.items.update&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;journal&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;colors&amp;lt;/code&amp;gt; current (&amp;lt;code&amp;gt;char.colors&amp;lt;/code&amp;gt; arrives on its own at login); re-request anything else when you want it fresh (e.g. &amp;lt;code&amp;gt;group.info&amp;lt;/code&amp;gt; on a timer, &amp;lt;code&amp;gt;char.factions&amp;lt;/code&amp;gt; after questing).&lt;br /&gt;
# Fetch helpfiles on demand with &amp;lt;code&amp;gt;help.topic&amp;lt;/code&amp;gt; — no need to prefetch; entries resolve in one round trip. Fetch journal-entry detail on demand with &amp;lt;code&amp;gt;char.journal.entry&amp;lt;/code&amp;gt;, per vnum, when a quest pane opens.&lt;br /&gt;
&lt;br /&gt;
== 6. Accepted no-ops ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;core.hello&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;core.supports.set&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;.add&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;.remove&amp;lt;/code&amp;gt;,&lt;br /&gt;
&amp;lt;code&amp;gt;core.keepalive&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;core.ping&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;external.discord.hello&amp;lt;/code&amp;gt; are&lt;br /&gt;
accepted without error but currently do nothing. You may send them&lt;br /&gt;
(many client GMCP stacks do automatically); today they don’t change&lt;br /&gt;
what the server broadcasts. A future subscription model may start&lt;br /&gt;
honoring &amp;lt;code&amp;gt;core.supports.*&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 7. Errors ==&lt;br /&gt;
&lt;br /&gt;
Any malformed request, unknown package, or invalid JSON payload gets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;logging.error { &amp;quot;error&amp;quot;: …, &amp;quot;package&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;message&amp;quot;: &amp;quot;...&amp;quot; }&amp;lt;/pre&amp;gt;&lt;br /&gt;
Common causes: a package name without a dot, a request body that isn’t&lt;br /&gt;
valid JSON, oversized requests (§2), or a package name typo.&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=797</id>
		<title>Welcome to Legend</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=797"/>
		<updated>2021-03-28T21:48:17Z</updated>

		<summary type="html">&lt;p&gt;Rufus: /* Play Legend */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Lm graphic final eval.png|Welcome To LegendMud!]]&lt;br /&gt;
= Play Legend =&lt;br /&gt;
[[Play Now!|Click here to learn how to play right now!]] or if you already know how, connect your client up to mud.legendmud.org on port 9999!&lt;br /&gt;
&lt;br /&gt;
To try the new (beta) web version, click here: [http://legendmud.org:19999/ PLAY NOW].&lt;br /&gt;
&lt;br /&gt;
Returning player? Take a look at the [[Major Updates|Major Updates]] page.&lt;br /&gt;
&lt;br /&gt;
Visit our [https://discord.gg/M2RYT5E Discord]!&lt;br /&gt;
&lt;br /&gt;
Vote for Legend at [http://www.topmudsites.com/vote-legend.html The Mud Connector]!&lt;br /&gt;
&lt;br /&gt;
[https://www.legendhub.org/ LegendHub] is a player-run website with an equipment set builder, quest walk-through's and more.&lt;br /&gt;
(Note: we do not have any editorial control of LegendHub and their views do not necessarily match those of the MUD administration)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= What Is Legend =&lt;br /&gt;
{{:What Is Legend}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;1&amp;quot;&amp;gt;Legend uses [http://www.mxguarddog.com/ anti spam] software - to keep it free this link is here.&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=796</id>
		<title>Welcome to Legend</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=796"/>
		<updated>2021-03-28T21:46:57Z</updated>

		<summary type="html">&lt;p&gt;Rufus: /* Play Legend */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Lm graphic final eval.png|Welcome To LegendMud!]]&lt;br /&gt;
= Play Legend =&lt;br /&gt;
[[Play Now!|Click here to learn how to play right now!]] or if you already know how, connect your client up to mud.legendmud.org on port 9999!&lt;br /&gt;
&lt;br /&gt;
To try the new (beta) web version, click here: &amp;lt;span class=&amp;quot;NewWindow&amp;quot;&amp;gt;http://legendmud.org:19999&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Returning player? Take a look at the [[Major Updates|Major Updates]] page.&lt;br /&gt;
&lt;br /&gt;
Visit our [https://discord.gg/M2RYT5E Discord]!&lt;br /&gt;
&lt;br /&gt;
Vote for Legend at [http://www.topmudsites.com/vote-legend.html The Mud Connector]!&lt;br /&gt;
&lt;br /&gt;
[https://www.legendhub.org/ LegendHub] is a player-run website with an equipment set builder, quest walk-through's and more.&lt;br /&gt;
(Note: we do not have any editorial control of LegendHub and their views do not necessarily match those of the MUD administration)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= What Is Legend =&lt;br /&gt;
{{:What Is Legend}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;1&amp;quot;&amp;gt;Legend uses [http://www.mxguarddog.com/ anti spam] software - to keep it free this link is here.&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=795</id>
		<title>Welcome to Legend</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=Welcome_to_Legend&amp;diff=795"/>
		<updated>2021-03-28T21:26:37Z</updated>

		<summary type="html">&lt;p&gt;Rufus: /* Play Legend */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Lm graphic final eval.png|Welcome To LegendMud!]]&lt;br /&gt;
= Play Legend =&lt;br /&gt;
[[Play Now!|Click here to learn how to play right now!]] or if you already know how, connect your client up to mud.legendmud.org on port 9999!&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;span class=&amp;quot;NewWindow&amp;quot;&amp;gt;http://legendmud.org:19999&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Returning player? Take a look at the [[Major Updates|Major Updates]] page.&lt;br /&gt;
&lt;br /&gt;
Visit our [https://discord.gg/M2RYT5E Discord]!&lt;br /&gt;
&lt;br /&gt;
Vote for Legend at [http://www.topmudsites.com/vote-legend.html The Mud Connector]!&lt;br /&gt;
&lt;br /&gt;
[https://www.legendhub.org/ LegendHub] is a player-run website with an equipment set builder, quest walk-through's and more.&lt;br /&gt;
(Note: we do not have any editorial control of LegendHub and their views do not necessarily match those of the MUD administration)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= What Is Legend =&lt;br /&gt;
{{:What Is Legend}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;1&amp;quot;&amp;gt;Legend uses [http://www.mxguarddog.com/ anti spam] software - to keep it free this link is here.&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=732</id>
		<title>The Coding Proposal</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=732"/>
		<updated>2020-08-05T01:04:17Z</updated>

		<summary type="html">&lt;p&gt;Rufus: /* Part II */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Preface =&lt;br /&gt;
Before continuing, ensure that you have read and follow [[The Immortal Proposal Process]].&lt;br /&gt;
&lt;br /&gt;
Coders on Legend are responsible for the maintenance of the current server code for the mud and the addition of new features. All coders are expected to maintain and fix minor bugs and typos as well as comment code where possible. Full coders are expected to implement and support larger projects.&lt;br /&gt;
&lt;br /&gt;
= Basic Information on the Mud Base =&lt;br /&gt;
Much of the invisible stuff that keeps Legend running has been redone from the original diku/merc base. One of the driving philosophies behind much of the coding that has gone into Legend is to make it a game for all types of players. It's not strictly one type of mud. It is not just for role players, it is not just for hack-n-slashers, it is not just for pkillers, etc.&lt;br /&gt;
In any case, the thing to keep in mind is that configurability and customizability of the code base implies that code design needs to be modular, APIs and interfaces to it need to be simple and clean, and all associated data files and the like need to be intuitive, flexible, and easy to use. The code is currently all in C.&lt;br /&gt;
&lt;br /&gt;
= The Coding Proposal =&lt;br /&gt;
Remember that your proposal is voted on by coders and non-coders alike. It is your job to make sure that both coders and non-coders can understand your answers and can get a good enough sense of your skills, sense of balance, and style to make an informed decision when voting on your application.&lt;br /&gt;
&lt;br /&gt;
Make sure that your application is legibly formatted and coherently written. Submit answers to the following sections.&lt;br /&gt;
&lt;br /&gt;
== General Knowledge ==&lt;br /&gt;
# What programming languages do you have experience with?&lt;br /&gt;
## How much experience in each?&lt;br /&gt;
# Currently, all mud development is done under Linux/Unix. While this may change in the future, there are no plans to change it in the short term. What experience do you have with Linux/Unix?&lt;br /&gt;
# Do you have access to a Linux/Unix machine where you can develop and compile software?&lt;br /&gt;
#* If so:&lt;br /&gt;
## Does it have git, gcc, gnu make?&lt;br /&gt;
## Can you use it to test code changes?&lt;br /&gt;
## What version of Linux/Unix does it run?&lt;br /&gt;
# Have you ever done any programming on a large project before?&lt;br /&gt;
#* If so:&lt;br /&gt;
## What?&lt;br /&gt;
## How many programmers were there?&lt;br /&gt;
## What did the program do?&lt;br /&gt;
# Have you ever coded on a MUD or any other type of game before?&lt;br /&gt;
&lt;br /&gt;
== Design and Miscellaneous Questions ==&lt;br /&gt;
# Describe a coding project that you would like to undertake. (Examples might include a new skill or spell, automatic description generation at character creation time, or something else). Include details about implementation, but also game balance issues.&lt;br /&gt;
# Seemingly out of nowhere, players start complaining loudly about something that you know is low down on the coder priority list. You're pretty sure that you know how to make the change players want, but your own project, though longer, is a higher priority. Would you stop work on your own project to go make this change?&lt;br /&gt;
# Design the skill. Write up a design spec for three of the following skills, remembering that the design spec will be read and evaluated by both coders and non-coders. Your ideas should provide for interesting, flexible skills without being out of bounds (the mud isn't based around any one skill or set of skills).&lt;br /&gt;
#* Autopsy&lt;br /&gt;
#* Embroidery&lt;br /&gt;
#* Falconry&lt;br /&gt;
#* Hiking&lt;br /&gt;
#* Hunt&lt;br /&gt;
#* Locate Herb&lt;br /&gt;
#* Make Pills&lt;br /&gt;
#* Smelting&lt;br /&gt;
#* Speed Draw&lt;br /&gt;
#* Tackle&lt;br /&gt;
#* Tailor&lt;br /&gt;
#* Vanish&lt;br /&gt;
# A player reports that after calming a mob they were killed by it in combat. They report this as a bug and ask for a reimbursement. You talk to the head PR who tells you that a reimbursement is fair if there is a bug. What do you do?&lt;br /&gt;
## What steps do you take to try to track down the bug?&lt;br /&gt;
# Write a new question (and give an answer to it) that you think would be a useful addition to the Coder proposal questions.&lt;br /&gt;
&lt;br /&gt;
== Coding Questions ==&lt;br /&gt;
Not having experience with particular tools is not necessarily a problem. Many of the questions are asked so that when/if you become an immortal we have a better idea of your experience level and which tools you are comfortable with.&lt;br /&gt;
&lt;br /&gt;
# What is your favorite programming language?&lt;br /&gt;
## Why?&lt;br /&gt;
#* Keep it brief, we are not looking for religious war type argument.&lt;br /&gt;
# What experience do you have with gdb (the GNU debugger)?# What are the advantages and disadvantages of storing the object database as an array of OBJ_TYPE? As a linked list of OBJ_TYPE? (OBJ_TYPE is the struct used for objects.)&lt;br /&gt;
# Explain how you would implement the three skills that you selected above. Include details about the data structures and algorithms that you plan on using, explain how the code would work, etc. We realize that you don't have much information about how the code is designed, but do your best without this information.&lt;br /&gt;
# What effects does changing a function call to a macro have on the performance of the code?&lt;br /&gt;
#* What are the advantages to using a function call instead of a macro, and vice versa?&lt;br /&gt;
&lt;br /&gt;
=== Code Commenting ===&lt;br /&gt;
# Comment the following code as you would normally comment code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char *&lt;br /&gt;
multi_check (char *argument, int *numtimes) {&lt;br /&gt;
char *arg_ptr;&lt;br /&gt;
char *temp_ptr;&lt;br /&gt;
int temptimes;&lt;br /&gt;
&lt;br /&gt;
icheckptr(numtimes,argument);&lt;br /&gt;
if (argument == NULL) {&lt;br /&gt;
  /* special handling for null argument pointer so that we can&lt;br /&gt;
     set numtimes to zero so that whatever it is that called &lt;br /&gt;
     multi_check will, god willing, not use the returned null pointer */&lt;br /&gt;
  _checkptr(&amp;quot;argument&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  *numtimes=0;&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*numtimes = 1;&lt;br /&gt;
&lt;br /&gt;
while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
if (*argument == '\0')&lt;br /&gt;
  return argument;&lt;br /&gt;
for (arg_ptr = argument; *arg_ptr != '\0'; arg_ptr++)&lt;br /&gt;
  if (isdigit (*arg_ptr) &amp;amp;&amp;amp; (arg_ptr == argument || *(arg_ptr - 1) == ' ')) {&lt;br /&gt;
    temptimes = MAX (1, MIN (atoi (arg_ptr), 30));&lt;br /&gt;
    temp_ptr = arg_ptr;&lt;br /&gt;
    while (isdigit (*temp_ptr))&lt;br /&gt;
      temp_ptr++;&lt;br /&gt;
    if (*temp_ptr == '*') {&lt;br /&gt;
      while (*(++temp_ptr) != '\0')&lt;br /&gt;
        *arg_ptr++ = *temp_ptr;&lt;br /&gt;
      *arg_ptr = '\0';&lt;br /&gt;
      *numtimes = temptimes;&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
  return argument;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Coding Exercise: Triangle ===&lt;br /&gt;
Coding question... you may use any language with which you feel comfortable, however during part 2, assume that the function you are testing is in a strongly typed language.&lt;br /&gt;
&lt;br /&gt;
==== Part I: ====&lt;br /&gt;
&lt;br /&gt;
Write a function that does the following:&lt;br /&gt;
&lt;br /&gt;
* Given the lengths of three sides, determine if the three sides can make a triangle based on their length&lt;br /&gt;
* takes 3 integers as arguments &lt;br /&gt;
* returns one of the following values (be they enums, integers, whatever):&lt;br /&gt;
      TRIANGLE_NONE&lt;br /&gt;
      TRIANGLE_EQUILATERAL&lt;br /&gt;
      TRIANGLE_ISOSCELES&lt;br /&gt;
      TRIANGLE_SCALENE&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
If I were to call this function can_be_triangle(4, 4, 4) It would return the value TRIANGLE_EQUILATERAL&lt;br /&gt;
&lt;br /&gt;
==== Part II ====&lt;br /&gt;
&lt;br /&gt;
How would you test the above function? &lt;br /&gt;
&lt;br /&gt;
Provide the following:&lt;br /&gt;
&lt;br /&gt;
* sets of numbers you would use as input values (4, 4, 4), (1, 2, 3) and their associated expected outcomes&lt;br /&gt;
* an estimation of the number of test cases it would take to fully test the function&lt;br /&gt;
&lt;br /&gt;
=== Optional ===&lt;br /&gt;
Show us some code that you've written. Anything at all. It can be any size 10 lines, 100 lines, whatever. (Well, try to keep it on the smaller side of things, we don't have time to look at thousands of lines of code).&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=731</id>
		<title>The Coding Proposal</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=731"/>
		<updated>2020-08-05T00:58:34Z</updated>

		<summary type="html">&lt;p&gt;Rufus: /* Coding Exercise */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Preface =&lt;br /&gt;
Before continuing, ensure that you have read and follow [[The Immortal Proposal Process]].&lt;br /&gt;
&lt;br /&gt;
Coders on Legend are responsible for the maintenance of the current server code for the mud and the addition of new features. All coders are expected to maintain and fix minor bugs and typos as well as comment code where possible. Full coders are expected to implement and support larger projects.&lt;br /&gt;
&lt;br /&gt;
= Basic Information on the Mud Base =&lt;br /&gt;
Much of the invisible stuff that keeps Legend running has been redone from the original diku/merc base. One of the driving philosophies behind much of the coding that has gone into Legend is to make it a game for all types of players. It's not strictly one type of mud. It is not just for role players, it is not just for hack-n-slashers, it is not just for pkillers, etc.&lt;br /&gt;
In any case, the thing to keep in mind is that configurability and customizability of the code base implies that code design needs to be modular, APIs and interfaces to it need to be simple and clean, and all associated data files and the like need to be intuitive, flexible, and easy to use. The code is currently all in C.&lt;br /&gt;
&lt;br /&gt;
= The Coding Proposal =&lt;br /&gt;
Remember that your proposal is voted on by coders and non-coders alike. It is your job to make sure that both coders and non-coders can understand your answers and can get a good enough sense of your skills, sense of balance, and style to make an informed decision when voting on your application.&lt;br /&gt;
&lt;br /&gt;
Make sure that your application is legibly formatted and coherently written. Submit answers to the following sections.&lt;br /&gt;
&lt;br /&gt;
== General Knowledge ==&lt;br /&gt;
# What programming languages do you have experience with?&lt;br /&gt;
## How much experience in each?&lt;br /&gt;
# Currently, all mud development is done under Linux/Unix. While this may change in the future, there are no plans to change it in the short term. What experience do you have with Linux/Unix?&lt;br /&gt;
# Do you have access to a Linux/Unix machine where you can develop and compile software?&lt;br /&gt;
#* If so:&lt;br /&gt;
## Does it have git, gcc, gnu make?&lt;br /&gt;
## Can you use it to test code changes?&lt;br /&gt;
## What version of Linux/Unix does it run?&lt;br /&gt;
# Have you ever done any programming on a large project before?&lt;br /&gt;
#* If so:&lt;br /&gt;
## What?&lt;br /&gt;
## How many programmers were there?&lt;br /&gt;
## What did the program do?&lt;br /&gt;
# Have you ever coded on a MUD or any other type of game before?&lt;br /&gt;
&lt;br /&gt;
== Design and Miscellaneous Questions ==&lt;br /&gt;
# Describe a coding project that you would like to undertake. (Examples might include a new skill or spell, automatic description generation at character creation time, or something else). Include details about implementation, but also game balance issues.&lt;br /&gt;
# Seemingly out of nowhere, players start complaining loudly about something that you know is low down on the coder priority list. You're pretty sure that you know how to make the change players want, but your own project, though longer, is a higher priority. Would you stop work on your own project to go make this change?&lt;br /&gt;
# Design the skill. Write up a design spec for three of the following skills, remembering that the design spec will be read and evaluated by both coders and non-coders. Your ideas should provide for interesting, flexible skills without being out of bounds (the mud isn't based around any one skill or set of skills).&lt;br /&gt;
#* Autopsy&lt;br /&gt;
#* Embroidery&lt;br /&gt;
#* Falconry&lt;br /&gt;
#* Hiking&lt;br /&gt;
#* Hunt&lt;br /&gt;
#* Locate Herb&lt;br /&gt;
#* Make Pills&lt;br /&gt;
#* Smelting&lt;br /&gt;
#* Speed Draw&lt;br /&gt;
#* Tackle&lt;br /&gt;
#* Tailor&lt;br /&gt;
#* Vanish&lt;br /&gt;
# A player reports that after calming a mob they were killed by it in combat. They report this as a bug and ask for a reimbursement. You talk to the head PR who tells you that a reimbursement is fair if there is a bug. What do you do?&lt;br /&gt;
## What steps do you take to try to track down the bug?&lt;br /&gt;
# Write a new question (and give an answer to it) that you think would be a useful addition to the Coder proposal questions.&lt;br /&gt;
&lt;br /&gt;
== Coding Questions ==&lt;br /&gt;
Not having experience with particular tools is not necessarily a problem. Many of the questions are asked so that when/if you become an immortal we have a better idea of your experience level and which tools you are comfortable with.&lt;br /&gt;
&lt;br /&gt;
# What is your favorite programming language?&lt;br /&gt;
## Why?&lt;br /&gt;
#* Keep it brief, we are not looking for religious war type argument.&lt;br /&gt;
# What experience do you have with gdb (the GNU debugger)?# What are the advantages and disadvantages of storing the object database as an array of OBJ_TYPE? As a linked list of OBJ_TYPE? (OBJ_TYPE is the struct used for objects.)&lt;br /&gt;
# Explain how you would implement the three skills that you selected above. Include details about the data structures and algorithms that you plan on using, explain how the code would work, etc. We realize that you don't have much information about how the code is designed, but do your best without this information.&lt;br /&gt;
# What effects does changing a function call to a macro have on the performance of the code?&lt;br /&gt;
#* What are the advantages to using a function call instead of a macro, and vice versa?&lt;br /&gt;
&lt;br /&gt;
=== Code Commenting ===&lt;br /&gt;
# Comment the following code as you would normally comment code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char *&lt;br /&gt;
multi_check (char *argument, int *numtimes) {&lt;br /&gt;
char *arg_ptr;&lt;br /&gt;
char *temp_ptr;&lt;br /&gt;
int temptimes;&lt;br /&gt;
&lt;br /&gt;
icheckptr(numtimes,argument);&lt;br /&gt;
if (argument == NULL) {&lt;br /&gt;
  /* special handling for null argument pointer so that we can&lt;br /&gt;
     set numtimes to zero so that whatever it is that called &lt;br /&gt;
     multi_check will, god willing, not use the returned null pointer */&lt;br /&gt;
  _checkptr(&amp;quot;argument&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  *numtimes=0;&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*numtimes = 1;&lt;br /&gt;
&lt;br /&gt;
while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
if (*argument == '\0')&lt;br /&gt;
  return argument;&lt;br /&gt;
for (arg_ptr = argument; *arg_ptr != '\0'; arg_ptr++)&lt;br /&gt;
  if (isdigit (*arg_ptr) &amp;amp;&amp;amp; (arg_ptr == argument || *(arg_ptr - 1) == ' ')) {&lt;br /&gt;
    temptimes = MAX (1, MIN (atoi (arg_ptr), 30));&lt;br /&gt;
    temp_ptr = arg_ptr;&lt;br /&gt;
    while (isdigit (*temp_ptr))&lt;br /&gt;
      temp_ptr++;&lt;br /&gt;
    if (*temp_ptr == '*') {&lt;br /&gt;
      while (*(++temp_ptr) != '\0')&lt;br /&gt;
        *arg_ptr++ = *temp_ptr;&lt;br /&gt;
      *arg_ptr = '\0';&lt;br /&gt;
      *numtimes = temptimes;&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
  return argument;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Coding Exercise: Triangle ===&lt;br /&gt;
Coding question... you may use any language with which you feel comfortable, however during part 2, assume that the function you are testing is in a strongly typed language.&lt;br /&gt;
&lt;br /&gt;
==== Part I: ====&lt;br /&gt;
&lt;br /&gt;
Write a function that does the following:&lt;br /&gt;
&lt;br /&gt;
* Given the lengths of three sides, determine if the three sides can make a triangle based on their length&lt;br /&gt;
* takes 3 integers as arguments &lt;br /&gt;
* returns one of the following values (be they enums, integers, whatever):&lt;br /&gt;
      TRIANGLE_NONE&lt;br /&gt;
      TRIANGLE_EQUILATERAL&lt;br /&gt;
      TRIANGLE_ISOSCELES&lt;br /&gt;
      TRIANGLE_SCALENE&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
If I were to call this function can_be_triangle(4, 4, 4) It would return the value TRIANGLE_EQUILATERAL&lt;br /&gt;
&lt;br /&gt;
==== Part II ====&lt;br /&gt;
&lt;br /&gt;
How would you test the above function? &lt;br /&gt;
&lt;br /&gt;
Provide the following:&lt;br /&gt;
&lt;br /&gt;
* sets of numbers you would use as input values (4, 4, 4), (1, 2, 3)&lt;br /&gt;
* an estimation of the number of test cases it would take to fully test the function&lt;br /&gt;
&lt;br /&gt;
=== Optional ===&lt;br /&gt;
Show us some code that you've written. Anything at all. It can be any size 10 lines, 100 lines, whatever. (Well, try to keep it on the smaller side of things, we don't have time to look at thousands of lines of code).&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
	<entry>
		<id>https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=730</id>
		<title>The Coding Proposal</title>
		<link rel="alternate" type="text/html" href="https://www.legendmud.org/index.php?title=The_Coding_Proposal&amp;diff=730"/>
		<updated>2020-08-05T00:58:01Z</updated>

		<summary type="html">&lt;p&gt;Rufus: replaces bug tracking with new question&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Preface =&lt;br /&gt;
Before continuing, ensure that you have read and follow [[The Immortal Proposal Process]].&lt;br /&gt;
&lt;br /&gt;
Coders on Legend are responsible for the maintenance of the current server code for the mud and the addition of new features. All coders are expected to maintain and fix minor bugs and typos as well as comment code where possible. Full coders are expected to implement and support larger projects.&lt;br /&gt;
&lt;br /&gt;
= Basic Information on the Mud Base =&lt;br /&gt;
Much of the invisible stuff that keeps Legend running has been redone from the original diku/merc base. One of the driving philosophies behind much of the coding that has gone into Legend is to make it a game for all types of players. It's not strictly one type of mud. It is not just for role players, it is not just for hack-n-slashers, it is not just for pkillers, etc.&lt;br /&gt;
In any case, the thing to keep in mind is that configurability and customizability of the code base implies that code design needs to be modular, APIs and interfaces to it need to be simple and clean, and all associated data files and the like need to be intuitive, flexible, and easy to use. The code is currently all in C.&lt;br /&gt;
&lt;br /&gt;
= The Coding Proposal =&lt;br /&gt;
Remember that your proposal is voted on by coders and non-coders alike. It is your job to make sure that both coders and non-coders can understand your answers and can get a good enough sense of your skills, sense of balance, and style to make an informed decision when voting on your application.&lt;br /&gt;
&lt;br /&gt;
Make sure that your application is legibly formatted and coherently written. Submit answers to the following sections.&lt;br /&gt;
&lt;br /&gt;
== General Knowledge ==&lt;br /&gt;
# What programming languages do you have experience with?&lt;br /&gt;
## How much experience in each?&lt;br /&gt;
# Currently, all mud development is done under Linux/Unix. While this may change in the future, there are no plans to change it in the short term. What experience do you have with Linux/Unix?&lt;br /&gt;
# Do you have access to a Linux/Unix machine where you can develop and compile software?&lt;br /&gt;
#* If so:&lt;br /&gt;
## Does it have git, gcc, gnu make?&lt;br /&gt;
## Can you use it to test code changes?&lt;br /&gt;
## What version of Linux/Unix does it run?&lt;br /&gt;
# Have you ever done any programming on a large project before?&lt;br /&gt;
#* If so:&lt;br /&gt;
## What?&lt;br /&gt;
## How many programmers were there?&lt;br /&gt;
## What did the program do?&lt;br /&gt;
# Have you ever coded on a MUD or any other type of game before?&lt;br /&gt;
&lt;br /&gt;
== Design and Miscellaneous Questions ==&lt;br /&gt;
# Describe a coding project that you would like to undertake. (Examples might include a new skill or spell, automatic description generation at character creation time, or something else). Include details about implementation, but also game balance issues.&lt;br /&gt;
# Seemingly out of nowhere, players start complaining loudly about something that you know is low down on the coder priority list. You're pretty sure that you know how to make the change players want, but your own project, though longer, is a higher priority. Would you stop work on your own project to go make this change?&lt;br /&gt;
# Design the skill. Write up a design spec for three of the following skills, remembering that the design spec will be read and evaluated by both coders and non-coders. Your ideas should provide for interesting, flexible skills without being out of bounds (the mud isn't based around any one skill or set of skills).&lt;br /&gt;
#* Autopsy&lt;br /&gt;
#* Embroidery&lt;br /&gt;
#* Falconry&lt;br /&gt;
#* Hiking&lt;br /&gt;
#* Hunt&lt;br /&gt;
#* Locate Herb&lt;br /&gt;
#* Make Pills&lt;br /&gt;
#* Smelting&lt;br /&gt;
#* Speed Draw&lt;br /&gt;
#* Tackle&lt;br /&gt;
#* Tailor&lt;br /&gt;
#* Vanish&lt;br /&gt;
# A player reports that after calming a mob they were killed by it in combat. They report this as a bug and ask for a reimbursement. You talk to the head PR who tells you that a reimbursement is fair if there is a bug. What do you do?&lt;br /&gt;
## What steps do you take to try to track down the bug?&lt;br /&gt;
# Write a new question (and give an answer to it) that you think would be a useful addition to the Coder proposal questions.&lt;br /&gt;
&lt;br /&gt;
== Coding Questions ==&lt;br /&gt;
Not having experience with particular tools is not necessarily a problem. Many of the questions are asked so that when/if you become an immortal we have a better idea of your experience level and which tools you are comfortable with.&lt;br /&gt;
&lt;br /&gt;
# What is your favorite programming language?&lt;br /&gt;
## Why?&lt;br /&gt;
#* Keep it brief, we are not looking for religious war type argument.&lt;br /&gt;
# What experience do you have with gdb (the GNU debugger)?# What are the advantages and disadvantages of storing the object database as an array of OBJ_TYPE? As a linked list of OBJ_TYPE? (OBJ_TYPE is the struct used for objects.)&lt;br /&gt;
# Explain how you would implement the three skills that you selected above. Include details about the data structures and algorithms that you plan on using, explain how the code would work, etc. We realize that you don't have much information about how the code is designed, but do your best without this information.&lt;br /&gt;
# What effects does changing a function call to a macro have on the performance of the code?&lt;br /&gt;
#* What are the advantages to using a function call instead of a macro, and vice versa?&lt;br /&gt;
&lt;br /&gt;
=== Code Commenting ===&lt;br /&gt;
# Comment the following code as you would normally comment code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char *&lt;br /&gt;
multi_check (char *argument, int *numtimes) {&lt;br /&gt;
char *arg_ptr;&lt;br /&gt;
char *temp_ptr;&lt;br /&gt;
int temptimes;&lt;br /&gt;
&lt;br /&gt;
icheckptr(numtimes,argument);&lt;br /&gt;
if (argument == NULL) {&lt;br /&gt;
  /* special handling for null argument pointer so that we can&lt;br /&gt;
     set numtimes to zero so that whatever it is that called &lt;br /&gt;
     multi_check will, god willing, not use the returned null pointer */&lt;br /&gt;
  _checkptr(&amp;quot;argument&amp;quot;,__FILE__,__LINE__);&lt;br /&gt;
  *numtimes=0;&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*numtimes = 1;&lt;br /&gt;
&lt;br /&gt;
while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
if (*argument == '\0')&lt;br /&gt;
  return argument;&lt;br /&gt;
for (arg_ptr = argument; *arg_ptr != '\0'; arg_ptr++)&lt;br /&gt;
  if (isdigit (*arg_ptr) &amp;amp;&amp;amp; (arg_ptr == argument || *(arg_ptr - 1) == ' ')) {&lt;br /&gt;
    temptimes = MAX (1, MIN (atoi (arg_ptr), 30));&lt;br /&gt;
    temp_ptr = arg_ptr;&lt;br /&gt;
    while (isdigit (*temp_ptr))&lt;br /&gt;
      temp_ptr++;&lt;br /&gt;
    if (*temp_ptr == '*') {&lt;br /&gt;
      while (*(++temp_ptr) != '\0')&lt;br /&gt;
        *arg_ptr++ = *temp_ptr;&lt;br /&gt;
      *arg_ptr = '\0';&lt;br /&gt;
      *numtimes = temptimes;&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (isspace (*argument))&lt;br /&gt;
  argument++;&lt;br /&gt;
&lt;br /&gt;
  return argument;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Coding Exercise ===&lt;br /&gt;
Coding question... you may use any language with which you feel comfortable, however during part 2, assume that the function you are testing is in a strongly typed language.&lt;br /&gt;
&lt;br /&gt;
==== Part I: ====&lt;br /&gt;
&lt;br /&gt;
Write a function that does the following:&lt;br /&gt;
&lt;br /&gt;
* Given the lengths of three sides, determine if the three sides can make a triangle based on their length&lt;br /&gt;
* takes 3 integers as arguments &lt;br /&gt;
* returns one of the following values (be they enums, integers, whatever):&lt;br /&gt;
      TRIANGLE_NONE&lt;br /&gt;
      TRIANGLE_EQUILATERAL&lt;br /&gt;
      TRIANGLE_ISOSCELES&lt;br /&gt;
      TRIANGLE_SCALENE&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
If I were to call this function can_be_triangle(4, 4, 4) It would return the value TRIANGLE_EQUILATERAL&lt;br /&gt;
&lt;br /&gt;
==== Part II ====&lt;br /&gt;
&lt;br /&gt;
How would you test the above function? &lt;br /&gt;
&lt;br /&gt;
Provide the following:&lt;br /&gt;
&lt;br /&gt;
* sets of numbers you would use as input values (4, 4, 4), (1, 2, 3)&lt;br /&gt;
* an estimation of the number of test cases it would take to fully test the function&lt;br /&gt;
&lt;br /&gt;
=== Optional ===&lt;br /&gt;
Show us some code that you've written. Anything at all. It can be any size 10 lines, 100 lines, whatever. (Well, try to keep it on the smaller side of things, we don't have time to look at thousands of lines of code).&lt;/div&gt;</summary>
		<author><name>Rufus</name></author>
	</entry>
</feed>