<p><aclass="reference internal"href="Python-basic-introduction.html"><spanclass="doc std std-doc">In the first part</span></a> of this Python-for-Evennia basic tutorial we learned
<p>To learn about functions and imports we also passed that <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code> on to a function <codeclass="docutils literal notranslate"><spanclass="pre">hello_world</span></code> in
another module.</p>
<p>Let’s learn some more about this <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code> thing we are passing around all over the place. In the
following we assume that we named our superuser Character “Christine”.</p>
<div><p>Note: In some MU clients, such as Mudlet and MUSHclient simply returning <codeclass="docutils literal notranslate"><spanclass="pre">type(me)</span></code>, you may not
see the proper return from the above commands. This is likely due to the HTML-like tags <codeclass="docutils literal notranslate"><spanclass="pre"><...></span></code>,
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">type</span></code> function is, like <codeclass="docutils literal notranslate"><spanclass="pre">print</span></code>, another in-built function in Python. It
tells us that we (<codeclass="docutils literal notranslate"><spanclass="pre">me</span></code>) are of the <em>class</em><codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.characters.Character</span></code>.
Meanwhile <codeclass="docutils literal notranslate"><spanclass="pre">me.key</span></code> is a <em>property</em> on us, a string. It holds the name of this
<div><p>When you do <codeclass="docutils literal notranslate"><spanclass="pre">py</span><spanclass="pre">me</span></code>, the <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code> is defined in such a way that it will use its <codeclass="docutils literal notranslate"><spanclass="pre">.key</span></code> property to
represent itself. That is why the result is the same as when doing <codeclass="docutils literal notranslate"><spanclass="pre">py</span><spanclass="pre">me.key</span></code>. Also, remember that
as noted in the first part of the tutorial, the <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code> is <em>not</em> a reserved Python word; it was just
defined by the Evennia developers as a convenient short-hand when creating the <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> command. So
don’t expect <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code> to be available elsewhere.</p>
<p>A <em>class</em> is like a “factory” or blueprint. From a class you then create individual <em>instances</em>. So
if class is<codeclass="docutils literal notranslate"><spanclass="pre">Dog</span></code>, an instance of <codeclass="docutils literal notranslate"><spanclass="pre">Dog</span></code> might be <codeclass="docutils literal notranslate"><spanclass="pre">fido</span></code>. Our in-game persona is of a class
<codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>. The superuser <codeclass="docutils literal notranslate"><spanclass="pre">christine</span></code> is an <em>instance</em> of the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class (an instance is
also often referred to as an <em>object</em>). This is an important concept in <em>object oriented
programming</em>. You are wise to <aclass="reference external"href="https://en.wikipedia.org/wiki/Class-based_programming">familiarize yourself with it</a> a little.</p>
<p>The string <codeclass="docutils literal notranslate"><spanclass="pre">'typeclasses.characters.Character'</span></code> we got from the <codeclass="docutils literal notranslate"><spanclass="pre">type()</span></code> function is not arbitrary.
You’ll recognize this from when we <em>imported</em><codeclass="docutils literal notranslate"><spanclass="pre">world.test</span></code> in part one. This is a <em>path</em> exactly
describing where to find the python code describing this class. Python treats source code files on
your hard drive (known as <em>modules</em>) as well as folders (known as <em>packages</em>) as objects that you
access with the <codeclass="docutils literal notranslate"><spanclass="pre">.</span></code> operator. It starts looking at a place that Evennia has set up for you - namely
the root of your own game directory.</p>
<p>Open and look at your game folder (named <codeclass="docutils literal notranslate"><spanclass="pre">mygame</span></code> if you exactly followed the Getting Started
instructions) in a file editor or in a new terminal/console. Locate the file
<p>This represents the first part of the python path - <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.characters</span></code> (the <codeclass="docutils literal notranslate"><spanclass="pre">.py</span></code> file ending
is never included in the python path). The last bit, <codeclass="docutils literal notranslate"><spanclass="pre">.Character</span></code> is the actual class name inside
the <codeclass="docutils literal notranslate"><spanclass="pre">characters.py</span></code> module. Open that file in a text editor and you will see something like this:</p>
<p>There is <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>, the last part of the path. Note how empty this file is. At first glance one
would think a Character had no functionality at all. But from what we have used already we know it
has at least the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> property and the method <codeclass="docutils literal notranslate"><spanclass="pre">msg</span></code>! Where is the code? The answer is that this
‘emptiness’ is an illusion caused by something called <em>inheritance</em>. Read on.</p>
<p>Firstly, in the same way as the little <codeclass="docutils literal notranslate"><spanclass="pre">hello.py</span></code> we did in the first part of the tutorial, this is
an example of full, multi-line Python code. Those triple-quoted strings are used for strings that
have line breaks in them. When they appear on their own like this, at the top of a python module,
class or similar they are called <em>doc strings</em>. Doc strings are read by Python and is used for
producing online help about the function/method/class/module. By contrast, a line starting with <codeclass="docutils literal notranslate"><spanclass="pre">#</span></code>
is a <em>comment</em>. It is ignored completely by Python and is only useful to help guide a human to
<p>means that the class <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> is a <em>child</em> of the class <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>. This is called
<em>inheritance</em> and is another fundamental concept. The answer to the question “where is the code?” is
that the code is <em>inherited</em> from its parent, <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>. And that in turn may inherit code
from <em>its</em> parent(s) and so on. Since our child, <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> is empty, its functionality is <em>exactly
identical</em> to that of its parent. The moment we add new things to Character, these will take
precedence. And if we add something that already existed in the parent, our child-version will
<em>override</em> the version in the parent. This is very practical: It means that we can let the parent do
the heavy lifting and only tweak the things we want to change. It also means that we could easily
have many different Character classes, all inheriting from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> but changing different
things. And those can in turn also have children …</p>
<p>Let’s figure out how to tweak <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>. Right now we don’t know much about <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>
though. Without knowing that we won’t know what to override. At the top of the file you find</p>
<p>This is an <codeclass="docutils literal notranslate"><spanclass="pre">import</span></code> statement again, but on a different form to what we’ve seen before. <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">...</span><spanclass="pre">import</span><spanclass="pre">...</span></code> is very commonly used and allows you to precisely dip into a module to extract just the
component you need to use. In this case we head into the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> package to get
<p>Where is <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code>? To find it you need to go to the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> folder (repository) you originally
cloned from us. If you open it, this is how it looks:</p>
<p>There are lots of things in there. There are some docs but most of those have to do with the
distribution of Evennia and does not concern us right now. The <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> subfolder is what we are
looking for. <em>This</em> is what you are accessing when you do <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">evennia</span><spanclass="pre">import</span><spanclass="pre">...</span></code>. It’s set up by
Evennia as a good place to find modules when the server starts. The exact layout of the Evennia
library <aclass="reference internal"href="Directory-Overview.html#evennia-library-layout"><spanclass="std std-doc">is covered by our directory overview</span></a>. You can
<li><p>To, for example, import <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/utils/utils.py#L201">the text justify function</a> from
<codeclass="docutils literal notranslate"><spanclass="pre">evennia/utils/utils.py</span></code> you would do <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">evennia.utils.utils</span><spanclass="pre">import</span><spanclass="pre">justify</span></code>. In your code you
could then just call <codeclass="docutils literal notranslate"><spanclass="pre">justify(...)</span></code> to access its functionality.</p></li>
<li><p>You could also do <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">evennia.utils</span><spanclass="pre">import</span><spanclass="pre">utils</span></code>. In code you would then have to write
<codeclass="docutils literal notranslate"><spanclass="pre">utils.justify(...)</span></code>. This is practical if want a lot of stuff from that <codeclass="docutils literal notranslate"><spanclass="pre">utils.py</span></code> module and don’t
want to import each component separately.</p></li>
<li><p>You could also do <codeclass="docutils literal notranslate"><spanclass="pre">import</span><spanclass="pre">evennia</span></code>. You would then have to enter the full
<codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.utils.justify(...)</span></code> every time you use it. Using <codeclass="docutils literal notranslate"><spanclass="pre">from</span></code> to only import the things you
need is usually easier and more readable.</p></li>
<li><p>See <aclass="reference external"href="http://effbot.org/zone/import-confusion.htm">this overview</a> about the different ways to
<p>Now, remember that our <codeclass="docutils literal notranslate"><spanclass="pre">characters.py</span></code> module did <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">evennia</span><spanclass="pre">import</span><spanclass="pre">DefaultCharacter</span></code>. But if we
look at the contents of the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> folder, there is no <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> anywhere! This is
because Evennia gives a large number of optional “shortcuts”, known as <aclass="reference internal"href="Evennia-API.html"><spanclass="doc std std-doc">the “flat” API</span></a>. The intention is to make it easier to remember where to find stuff. The flat API is defined in
that weirdly named <codeclass="docutils literal notranslate"><spanclass="pre">__init__.py</span></code> file. This file just basically imports useful things from all over
Evennia so you can more easily find them in one place.</p>
<p>We could <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia#typeclasses">just look at the documenation</a> to find out where we can look
at our <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> parent. But for practice, let’s figure it out. Here is where
<p>The period at the start means that it imports beginning from the same location this module sits(i.e.
the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> folder). The full python-path accessible from the outside is thus
<codeclass="docutils literal notranslate"><spanclass="pre">evennia.objects.objects.DefaultCharacter</span></code>. So to import this into our game it’d be perfectly valid
<p>is the same thing, just a little easier to remember.</p>
<blockquote>
<div><p>To access the shortcuts of the flat API you <em>must</em> use <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">evennia</span><spanclass="pre">import</span><spanclass="pre">...</span></code>. Using something like <codeclass="docutils literal notranslate"><spanclass="pre">import</span><spanclass="pre">evennia.DefaultCharacter</span></code> will not work.
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">locks</span><spanclass="o">.</span><spanclass="n">add</span><spanclass="p">(</span><spanclass="s2">";"</span><spanclass="o">.</span><spanclass="n">join</span><spanclass="p">([</span><spanclass="s2">"get:false()"</span><spanclass="p">,</span><spanclass="c1"># noone can pick up the character</span>
<p>… And so on (you can see the full <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1915">class online here</a>). Here we
have functional code! These methods may not be directly visible in <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> back in our game dir,
but they are still available since <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> is a child of <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> above. Here is a
brief summary of the methods we find in <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> (follow in the code to see if you can see
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">basetype_setup</span></code> is called by Evennia only once, when a Character is first created. In the
<codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> class it sets some particular <aclass="reference internal"href="Locks.html"><spanclass="doc std std-doc">Locks</span></a> so that people can’t pick up and
puppet Characters just like that. It also adds the <aclass="reference internal"href="Command-Sets.html"><spanclass="doc std std-doc">Character Cmdset</span></a> so that
Characters always can accept command-input (this should usually not be modified - the normal hook to
override is <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code>, which is called after <codeclass="docutils literal notranslate"><spanclass="pre">basetype_setup</span></code> (it’s in the parent)).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_after_move</span></code> makes it so that every time the Character moves, the <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command is
automatically fired (this would not make sense for just any regular Object).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_pre_puppet</span></code> is called when an Account begins to puppet this Character. When not puppeted, the
Character is hidden away to a <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> location. This brings it back to the location it was in before.
Without this, “headless” Characters would remain in the game world just standing around.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_post_puppet</span></code> is called when puppeting is complete. It echoes a message to the room that his
Character has now connected.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_post_unpuppet</span></code> is called once stopping puppeting of the Character. This hides away the
Character to a <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> location again.</p></li>
<li><p>There are also some utility properties which makes it easier to get some time stamps from the
<p>This means that <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> is in <em>itself</em> a child of something called <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>! Let’s
see what this parent class provides. It’s in the same module as <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>, you just need to
<p>This is a really big class where the bulk of code defining an in-game object resides. It consists of
a large number of methods, all of which thus also becomes available on the <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> class
below <em>and</em> by extension in your <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class over in your game dir. In this class you can for
example find the <codeclass="docutils literal notranslate"><spanclass="pre">msg</span></code> method we have been using before.</p>
<div><p>As seen, <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> actually has multiple parents. In one of those the basic <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> property
is defined, but we won’t travel further up the inheritance tree in this tutorial. If you are
interested to see them, you can find <codeclass="docutils literal notranslate"><spanclass="pre">TypeclassBase</span></code> in <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/typeclasses/models.py#L93">evennia/typeclasses/models.py</a> and <codeclass="docutils literal notranslate"><spanclass="pre">ObjectDB</span></code> in <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/objects/models.py#L121">evennia/obj
will also not go into the details of <aclass="reference external"href="https://docs.python.org/2/tutorial/classes.html#multiple-inheritance">Multiple Inheritance</a> or
<p>Remember the <codeclass="docutils literal notranslate"><spanclass="pre">at_pre_puppet</span></code> method we looked at in <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code>? If you look at the
<codeclass="docutils literal notranslate"><spanclass="pre">at_pre_puppet</span></code> hook as defined in <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> you’ll find it to be completely empty (just a
<codeclass="docutils literal notranslate"><spanclass="pre">pass</span></code>). So if you puppet a regular object it won’t be hiding/retrieving the object when you
unpuppet it. The <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> class <em>overrides</em> its parent’s functionality with a version of
its own. And since it’s <codeclass="docutils literal notranslate"><spanclass="pre">DefaultCharacter</span></code> that our <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class inherits back in our game dir,
it’s <em>that</em> version of <codeclass="docutils literal notranslate"><spanclass="pre">at_pre_puppet</span></code> we’ll get. Anything not explicitly overridden will be passed
down as-is.</p>
<p>While it’s useful to read the code, we should never actually modify anything inside the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code>
folder. Only time you would want that is if you are planning to release a bug fix or new feature for
Evennia itself. Instead you <em>override</em> the default functionality inside your game dir.</p>
<p>So to conclude our little foray into classes, objects and inheritance, locate the simple little
<codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code> method in the <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> class:</p>
<p>If you read the doc string you’ll find that this can be used to modify the output of <codeclass="docutils literal notranslate"><spanclass="pre">say</span></code> before it
goes out. You can think of it like this: Evennia knows the name of this method, and when someone
speaks, Evennia will make sure to redirect the outgoing message through this method. It makes it
ripe for us to replace with a version of our own.</p>
<p>As you can see, the first argument to <codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code>. In Python, the first argument of a
method is <em>always a back-reference to the object instance on which the method is defined</em>. By
convention this argument is always called <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> but it could in principle be named anything. The
<codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> is very useful. If you wanted to, say, send a message to the same object from inside
<codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code>, you would do <codeclass="docutils literal notranslate"><spanclass="pre">self.msg(...)</span></code>.</p>
<p>What can trip up newcomers is that you <em>don’t</em> include <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> when you <em>call</em> the method. Try:</p>
<p>Note that we don’t send <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> but only the <codeclass="docutils literal notranslate"><spanclass="pre">message</span></code> argument. Python will automatically add <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code>
for us. In this case, <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> will become equal to the Character instance <codeclass="docutils literal notranslate"><spanclass="pre">me</span></code>.</p>
<p>By default the <codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code> method doesn’t do anything. It just takes the <codeclass="docutils literal notranslate"><spanclass="pre">message</span></code> input and
<codeclass="docutils literal notranslate"><spanclass="pre">return</span></code>s it just the way it was (the <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code> is another reserved Python word).</p>
<div><p>We won’t go into <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> here, but it (and its sibling <codeclass="docutils literal notranslate"><spanclass="pre">*args</span></code>) is also important to
understand, extra reading is <aclass="reference external"href="https://stackoverflow.com/questions/1769403/understanding-kwargs-in-python">here for <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code></a>.</p>
<p>Now, open your game folder and edit <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code>. Locate your <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>
<p>So we add our own version of <codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code>, duplicating the <codeclass="docutils literal notranslate"><spanclass="pre">def</span></code> line from the parent but putting
new code in it. All we do in this tutorial is to add an ellipsis (<codeclass="docutils literal notranslate"><spanclass="pre">...</span></code>) to the message as it passes
through the method.</p>
<p>Note that <codeclass="docutils literal notranslate"><spanclass="pre">f</span></code> in front of the string, it means we turned the string into a ‘formatted string’. We
can now easily inject stuff directly into the string by wrapping them in curly brackets <codeclass="docutils literal notranslate"><spanclass="pre">{</span><spanclass="pre">}</span></code>. In
this example, we put the incoming <codeclass="docutils literal notranslate"><spanclass="pre">message</span></code> into the string, followed by an ellipsis. This is only
one way to format a string. Python has very powerful <aclass="reference external"href="https://docs.python.org/2/library/string.html#format-specification-mini-language">string formatting</a> and
<div><p>You could also copy & paste the relevant method from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> here to get the full doc
string. For more complex methods, or if you only want to change some small part of the default
behavior, copy & pasting will eliminate the need to constantly look up the original method and keep
<p>An ellipsis <codeclass="docutils literal notranslate"><spanclass="pre">...</span></code> is added to what you said! This is a silly example but you have just made your
first code change to core functionality - without touching any of Evennia’s original code! We just
plugged in our own version of the <codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code> method and it replaced the default one. Evennia
happily redirected the message through our version and we got a different output.</p>
<p>Now on to some generally useful tools as you continue learning Python and Evennia. We have so far
explored using <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> and have inserted Python code directly in-game. We have also modified Evennia’s
behavior by overriding default functionality with our own. There is a third way to conveniently
explore Evennia and Python - the Evennia shell.</p>
<p>Outside of your game, <codeclass="docutils literal notranslate"><spanclass="pre">cd</span></code> to your mygame folder and make sure any needed virtualenv is running.
<p>The <aclass="reference external"href="https://en.wikipedia.org/wiki/IPython"><codeclass="docutils literal notranslate"><spanclass="pre">IPython</span></code></a> program is just a nicer interface to the
Python interpreter - you only need to install it once, after which Evennia will use it
<p>That is, write <codeclass="docutils literal notranslate"><spanclass="pre">evennia.</span></code> and press the Tab key. You will be presented with a list of all available
resources in the Evennia Flat API. We looked at the <codeclass="docutils literal notranslate"><spanclass="pre">__init__.py</span></code> file in the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> folder
earlier, so some of what you see should be familiar. From the IPython prompt, do:</p>
<p>Don’t forget that you can use <codeclass="docutils literal notranslate"><spanclass="pre"><TAB></span></code> to auto-complete code as you write. Appending a single <codeclass="docutils literal notranslate"><spanclass="pre">?</span></code> to
the end will show you the doc-string for <codeclass="docutils literal notranslate"><spanclass="pre">at_before_say</span></code> we looked at earlier. Use <codeclass="docutils literal notranslate"><spanclass="pre">??</span></code> to get the
whole source code.</p>
<p>Let’s look at our over-ridden version instead. Since we started the <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">shell</span></code> from our game
of the beginning-level <aclass="reference internal"href="Tutorials.html"><spanclass="doc std std-doc">Evennia tutorials</span></a> to gradually build up your understanding.</p>