<p>When you are sitting in a chair you can’t just walk off without first standing up.
This requires a change to our Character typeclass. Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code>:</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You can't go anywhere while resting."</span><spanclass="p">)</span>
<p>When moving somewhere, <aclass="reference internal"href="../../../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.move_to"title="evennia.objects.objects.DefaultObject.move_to"><spanclass="xref myst py py-meth">character.move_to</span></a> is called. This in turn
will call <codeclass="docutils literal notranslate"><spanclass="pre">character.at_pre_move</span></code>. Here we look for an Attribute <codeclass="docutils literal notranslate"><spanclass="pre">is_resting</span></code> (which we will assign below)
<h2>Making the Chair itself<aclass="headerlink"href="#making-the-chair-itself"title="Permalink to this headline">¶</a></h2>
<p>Next we need the Chair itself, or rather a whole family of “things you can sit on” that we will call
<em>sittables</em>. We can’t just use a default Object since we want a sittable to contain some custom code. We need
a new, custom Typeclass. Create a new module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/sittables.py</span></code> with the following content:</p>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You are already sitting on </span><spanclass="si">{self.key}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You can't sit on </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span>
<spanclass="sa">f</span><spanclass="s2">"- </span><spanclass="si">{</span><spanclass="n">current</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is already sitting there!"</span><spanclass="p">)</span>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You sit on </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You are not sitting on </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You stand up from </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<p>Here we have a small Typeclass that handles someone trying to sit on it. It has two methods that we can simply
call from a Command later. We set the <codeclass="docutils literal notranslate"><spanclass="pre">is_resting</span></code> Attribute on the one sitting down.</p>
<p>One could imagine that one could have the future <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> command check if someone is already sitting in the
chair instead. This would work too, but letting the <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> class handle the logic around who can sit on it makes
logical sense.</p>
<p>We let the typeclass handle the logic, and also let it do all the return messaging. This makes it easy to churn out
a bunch of chairs for people to sit on. But it’s not perfect. The <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> class is general. What if you want to
make an armchair. You sit “in” an armchair rather than “on” it. We <em>could</em> make a child class of <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> named
<codeclass="docutils literal notranslate"><spanclass="pre">SittableIn</span></code> that makes this change, but that feels excessive. Instead we will make it so that Sittables can
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You are already sitting </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="sa">f</span><spanclass="s2">"You can't sit </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span>
<spanclass="sa">f</span><spanclass="s2">"- </span><spanclass="si">{</span><spanclass="n">current</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is already sitting there!"</span><spanclass="p">)</span>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You sit </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You are not sitting </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You stand up from </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<p>We added a new Attribute <codeclass="docutils literal notranslate"><spanclass="pre">adjective</span></code> which will probably usually be <codeclass="docutils literal notranslate"><spanclass="pre">in</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">on</span></code> but could also be <codeclass="docutils literal notranslate"><spanclass="pre">at</span></code> if you
want to be able to sit <em>at a desk</em> for example. A regular builder would use it like this:</p>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You are already sitting </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You can't sit </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span>
<spanclass="sa">f</span><spanclass="s2">"- </span><spanclass="si">{</span><spanclass="n">current</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is already sitting there!"</span><spanclass="p">)</span>
<spanclass="n">sitter</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You sit </span><spanclass="si">{</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You are not sitting </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">adjective</span><spanclass="si">}</span><spanclass="s2"></span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<spanclass="n">stander</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You stand up from </span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<p>Here we really went all out with flexibility. If you need this much is up to you.
We added a bunch of optional Attributes to hold alternative versions of all the messages.
There are some things to note:</p>
<ul>
<li><p>We don’t actually initiate those Attributes in <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code>. This is a simple
optimization. The assumption is that <em>most</em> chairs will probably not be this customized.
So initiating a bunch of Attributes to, say, empty strings would be a lot of useless database calls.
The drawback is that the available Attributes become less visible when reading the code. So we add a long
describing docstring to the end to explain all you can use.</p></li>
<li><p>We use <codeclass="docutils literal notranslate"><spanclass="pre">.format</span></code> to inject formatting-tokens in the text. The good thing about such formatting
markers is that they are <em>optional</em>. They are there if you want them, but Python will not complain
if you don’t include some or any of them. Let’s see an example:</p>
<blockquote>
<div><p>reload # if you have new code
create/drop armchair : sittables.Sittable
set armchair/adjective = in
set armchair/msg_sitting_down = As you sit down {adjective} {key}, life feels easier.
set armchair/msg_standing_up = You stand up from {key}. Life resumes.</p>
</div></blockquote>
</li>
</ul>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">{key}</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">{adjective}</span></code> are examples of optional formatting markers. Whenever the message is
returned, the format-tokens within will be replaced with <codeclass="docutils literal notranslate"><spanclass="pre">armchair</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">in</span></code> respectively. Should we
rename the chair later, this will show in the messages automatically (since <codeclass="docutils literal notranslate"><spanclass="pre">{key}</span></code> will change).</p>
<p>We have no Command to use this chair yet. But we can try it out with <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code>:</p>
<h2>Command variant 1: Commands on the chair<aclass="headerlink"href="#command-variant-1-commands-on-the-chair"title="Permalink to this headline">¶</a></h2>
<p>This way to implement <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> puts new cmdsets on the Sittable itself.
As we’ve learned before, commands on objects are made available to others in the room.
This makes the command easy but instead adds some complexity in the management of the CmdSet.</p>
<p>This is how it will look if <codeclass="docutils literal notranslate"><spanclass="pre">armchair</span></code> is in the room:</p>
<p>What happens if there are sittables <codeclass="docutils literal notranslate"><spanclass="pre">sofa</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">barstool</span></code> also in the room? Evennia will automatically
handle this for us and allow us to specify which one we want:</p>
<p>To keep things separate we’ll make a new module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/sittables.py</span></code>:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>You can organize these things as you like. If you wanted you could put the sit-command + cmdset
together with the `Sittable` typeclass in `mygame/typeclasses/sittables.py`. That has the advantage of
<p>As seen, the commands are nearly trivial. <codeclass="docutils literal notranslate"><spanclass="pre">self.obj</span></code> is the object to which we added the cmdset with this
Command (so for example a chair). We just call the <codeclass="docutils literal notranslate"><spanclass="pre">do_sit/stand</span></code> on that object and the <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> will
do the rest.</p>
<p>Why that <codeclass="docutils literal notranslate"><spanclass="pre">priority</span><spanclass="pre">=</span><spanclass="pre">1</span></code> on <codeclass="docutils literal notranslate"><spanclass="pre">CmdSetSit</span></code>? This makes same-named Commands from this cmdset merge with a bit higher
priority than Commands from the Character-cmdset. Why this is a good idea will become clear shortly.</p>
<p>We also need to make a change to our <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> typeclass. Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/sittables.py</span></code>:</p>
<p>Any <em>new</em> Sittables will now have your <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> Command. Your existing <codeclass="docutils literal notranslate"><spanclass="pre">armchair</span></code> will not,
since <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> will not re-run for already existing objects. We can update it manually:</p>
<p>One issue with placing the <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> (or <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code>) Command “on” the chair is that it will not be available when in a
<p>This is practical but not so good-looking; it makes it harder for the user to know a <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> action is at all
possible. Here is a trick for fixing this. Let’s add <em>another</em> Command to the bottom
of <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/sittables.py</span></code>:</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You have nothing to sit on."</span><spanclass="p">)</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You are not sitting down."</span><spanclass="p">)</span>
<p>Here we have a Command that is actually two - it will answer to both <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> since we
added <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> to its <codeclass="docutils literal notranslate"><spanclass="pre">aliases</span></code>. In the command we look at <codeclass="docutils literal notranslate"><spanclass="pre">self.cmdname</span></code>, which is the string
<em>actually used</em> to call this command. We use this to return different messages.</p>
<p>We don’t need a separate CmdSet for this, instead we will add this
to the default Character cmdset. Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/default_cmdsets.py</span></code>:</p>
<p>We now have a fully functioning <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> action that is contained with the chair itself. When no chair is around, a
default error message is shown.</p>
<p>How does this work? There are two cmdsets at play, both of which have a <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> Command. As you may remember we
set the chair’s cmdset to <codeclass="docutils literal notranslate"><spanclass="pre">priority</span><spanclass="pre">=</span><spanclass="pre">1</span></code>. This is where that matters. The default Character cmdset has a
priority of 0. This means that whenever we enter a room with a Sittable thing, the <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> command
from <em>its</em> cmdset will take <em>precedence</em> over the Character cmdset’s version. So we are actually picking
<em>different</em><codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> commands depending on circumstance! The user will never be the wiser.</p>
<p>So this handles <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code>. What about <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code>? That will work just fine:</p>
<p>We have one remaining problem with <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> though - what happens when you are sitting down and try to
<codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> in a room with more than one chair:</p>
<p>Since all the sittables have the <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> Command on them, you’ll get a multi-match error. This <em>works</em> … but
you could pick <em>any</em> of those sittables to “stand up from”. That’s really weird and non-intuitive. With <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> it
was okay to get a choice - Evennia can’t know which chair we intended to sit on. But we know which chair we
sit on so we should only get <em>its</em><codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> command.</p>
<p>We will fix this with a <codeclass="docutils literal notranslate"><spanclass="pre">lock</span></code> and a custom <codeclass="docutils literal notranslate"><spanclass="pre">lock</span><spanclass="pre">function</span></code>. We want a lock on the <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> Command that only
makes it available when the caller is actually sitting on the chair the <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> command is on.</p>
<p>First let’s add the lock so we see what we want. Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/sittables.py</span></code>:</p>
<p>We define a <aclass="reference internal"href="../../../Components/Locks.html"><spanclass="doc std std-doc">Lock</span></a> on the command. The <codeclass="docutils literal notranslate"><spanclass="pre">cmd:</span></code> is in what situation Evennia will check
the lock. The <codeclass="docutils literal notranslate"><spanclass="pre">cmd</span></code> means that it will check the lock when determining if a user has access to this command or not.
What will be checked is the <codeclass="docutils literal notranslate"><spanclass="pre">sitsonthis</span></code><em>lock function</em> which doesn’t exist yet.</p>
<p>Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/lockfuncs.py</span></code> to add it!</p>
<p>Evennia knows that all functions in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/lockfuncs</span></code> should be possible to use in a lock definition.
The arguments are required and Evennia will pass all relevant objects to them:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>Evennia provides a large number of default lockfuncs, such as checking permission-levels,
if you are carrying or are inside the accessed object etc. There is no concept of 'sitting'
in default Evennia however, so this we need to specify ourselves.
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">accessing_obj</span></code> is the one trying to access the lock. So us, in this case.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">accessed_obj</span></code> is the entity we are trying to gain a particular type of access to. So the chair.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> is a tuple holding any arguments passed to the lockfunc. Since we use <codeclass="docutils literal notranslate"><spanclass="pre">sitsondthis()</span></code> this will
be empty (and if we add anything, it will be ignored).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> is a tuple of keyword arguments passed to the lockfuncs. This will be empty as well in our example.</p></li>
</ul>
<p>If you are superuser, it’s important that you <codeclass="docutils literal notranslate"><spanclass="pre">quell</span></code> yourself before trying this out. This is because the superuser
bypasses all locks - it can never get locked out, but it means it will also not see the effects of a lock like this.</p>
<p>None of the other sittables’<codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> commands passed the lock and only the one we are actually sitting on did.</p>
<p>Adding a Command to the chair object like this is powerful and a good technique to know. It does come with some
caveats though that one needs to keep in mind.</p>
<p>We’ll now try another way to add the <codeclass="docutils literal notranslate"><spanclass="pre">sit/stand</span></code> commands.</p>
<h2>Command variant 2: Command on Character<aclass="headerlink"href="#command-variant-2-command-on-character"title="Permalink to this headline">¶</a></h2>
<p>Before we start with this, delete the chairs you’ve created (<codeclass="docutils literal notranslate"><spanclass="pre">del</span><spanclass="pre">armchair</span></code> etc) and then do the following
changes:</p>
<ulclass="simple">
<li><p>In <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/sittables.py</span></code>, comment out the line <codeclass="docutils literal notranslate"><spanclass="pre">self.cmdset.add_default(CmdSetSit)</span></code>.</p></li>
<li><p>In <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands/default_cmdsets.py</span></code>, comment out the line <codeclass="docutils literal notranslate"><spanclass="pre">self.add(sittables.CmdNoSitStand)</span></code>.</p></li>
</ul>
<p>This disables the on-object command solution so we can try an alternative. Make sure to <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code> so the
changes are known to Evennia.</p>
<p>In this variation we will put the <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> commands on the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> instead of on the chair. This
makes some things easier, but makes the Commands themselves more complex because they will not know which
chair to sit on. We can’t just do <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> anymore. This is how it will work.</p>
<p>Open <codeclass="docutils literal notranslate"><spanclass="pre">mygame/commands.sittables.py</span></code> again. We’ll add a new sit-command. We name the class <codeclass="docutils literal notranslate"><spanclass="pre">CmdSit2</span></code> since
we already have <codeclass="docutils literal notranslate"><spanclass="pre">CmdSit</span></code> from the previous example. We put everything at the end of the module to
<spanclass="kn">from</span><spanclass="nn">evennia</span><spanclass="kn">import</span><spanclass="n">InterruptCommand</span><spanclass="c1"># <- this is new</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Sit on what?"</span><spanclass="p">)</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You can't sit on that!"</span><spanclass="p">)</span>
<p>With this Command-variation we need to search for the sittable. A series of methods on the Command
are run in sequence:</p>
<olclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">Command.at_pre_command</span></code> - this is not used by default</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">Command.parse</span></code> - this should parse the input</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">Command.func</span></code> - this should implement the actual Command functionality</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">Command.at_post_func</span></code> - this is not used by default</p></li>
</ol>
<p>So if we just <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code> in <codeclass="docutils literal notranslate"><spanclass="pre">.parse</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">.func</span></code> will still run, which is not what we want. To immediately
abort this sequence we need to <codeclass="docutils literal notranslate"><spanclass="pre">raise</span><spanclass="pre">InterruptCommand</span></code>.</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>Raising an exception allows for immediately interrupting the current program flow. Python
<p><codeclass="docutils literal notranslate"><spanclass="pre">InterruptCommand</span></code> is an <em>exception</em> that the Command-system catches with the understanding that we want
to do a clean abort. In the <codeclass="docutils literal notranslate"><spanclass="pre">.parse</span></code> method we strip any whitespaces from the argument and
sure there actuall <em>is</em> an argument. We abort immediately if there isn’t.</p>
<p>We we get to <codeclass="docutils literal notranslate"><spanclass="pre">.func</span></code> at all, we know that we have an argument. We search for this and abort if we there was
a problem finding the target.</p>
<blockquote>
<div><p>We could have done <codeclass="docutils literal notranslate"><spanclass="pre">raise</span><spanclass="pre">InterruptCommand</span></code> in <codeclass="docutils literal notranslate"><spanclass="pre">.func</span></code> as well, but <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code> is a little shorter to write
and there is no harm done if <codeclass="docutils literal notranslate"><spanclass="pre">at_post_func</span></code> runs since it’s empty.</p>
</div></blockquote>
<p>Next we call the found sittable’s <codeclass="docutils literal notranslate"><spanclass="pre">do_sit</span></code> method. Note that we wrap this call like this:</p>
<p>The reason is that <codeclass="docutils literal notranslate"><spanclass="pre">caller.search</span></code> has no idea we are looking for a Sittable. The user could have tried
<codeclass="docutils literal notranslate"><spanclass="pre">sit</span><spanclass="pre">wall</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">sit</span><spanclass="pre">sword</span></code>. These don’t have a <codeclass="docutils literal notranslate"><spanclass="pre">do_sit</span></code> method <em>but we call it anyway and handle the error</em>.
This is a very “Pythonic” thing to do. The concept is often called “leap before you look” or “it’s easier to
ask for forgiveness than for permission”. If <codeclass="docutils literal notranslate"><spanclass="pre">sittable.do_sit</span></code> does not exist, Python will raise an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeError</span></code>.
We catch this with <codeclass="docutils literal notranslate"><spanclass="pre">try</span><spanclass="pre">...</span><spanclass="pre">except</span><spanclass="pre">AttributeError</span></code> and convert it to a proper error message.</p>
<p>While it’s useful to learn about <codeclass="docutils literal notranslate"><spanclass="pre">try</span><spanclass="pre">...</span><spanclass="pre">except</span></code>, there is also a way to leverage Evennia to do this without
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>Note how the `.search()` method's arguments are spread out over multiple
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">caller.search</span></code> method has an keyword argument <codeclass="docutils literal notranslate"><spanclass="pre">typeclass</span></code> that can take either a python-path to a
typeclass, the typeclass itself, or a list of either to widen the allowed options. In this case we know
for sure that the <codeclass="docutils literal notranslate"><spanclass="pre">sittable</span></code> we get is actually a <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> class and we can call <codeclass="docutils literal notranslate"><spanclass="pre">sittable.do_sit</span></code> without
needing to worry about catching errors.</p>
<p>Let’s do the <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> command while we are at it. Again, since the Command is external to the chair we don’t
know which object we are sitting in and have to search for it.</p>
<p>This forced us to to use the full power of the <codeclass="docutils literal notranslate"><spanclass="pre">caller.search</span></code> method. If we wanted to search for something
more complex we would likely need to break out a <aclass="reference internal"href="../Part1/Django-queries.html"><spanclass="doc std std-doc">Django query</span></a> to do it. The key here is that
we know that the object we are looking for is a <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> and that it must have an Attribute named <codeclass="docutils literal notranslate"><spanclass="pre">sitter</span></code>
which should be set to us, the one sitting on/in the thing. Once we have that we just call <codeclass="docutils literal notranslate"><spanclass="pre">.do_stand</span></code> on it
and let the Typeclass handle the rest.</p>
<p>All that is left now is to make this available to us. This type of Command should be available to us all the time
so we can put it in the default Cmdset<codeclass="docutils literal notranslate"><spanclass="pre">on</span><spanclass="pre">the</span><spanclass="pre">Character.</span><spanclass="pre">Open</span></code>mygame/default_cmdsets.py`</p>
<h2>Conclusions<aclass="headerlink"href="#conclusions"title="Permalink to this headline">¶</a></h2>
<p>In this lesson we accomplished quite a bit:</p>
<ulclass="simple">
<li><p>We modified our <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class to avoid moving when sitting down.</p></li>
<li><p>We made a new <codeclass="docutils literal notranslate"><spanclass="pre">Sittable</span></code> typeclass</p></li>
<li><p>We tried two ways to allow a user to interact with sittables using <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> commands.</p></li>
</ul>
<p>Eagle-eyed readers will notice that the <codeclass="docutils literal notranslate"><spanclass="pre">stand</span></code> command sitting “on” the chair (variant 1) would work just fine
together with the <codeclass="docutils literal notranslate"><spanclass="pre">sit</span></code> command sitting “on” the Character (variant 2). There is nothing stopping you from
mixing them, or even try a third solution that better fits what you have in mind.</p>