<h1><spanclass="section-number">3. </span>Player Characters<aclass="headerlink"href="#player-characters"title="Permalink to this headline">¶</a></h1>
<p>In the <aclass="reference internal"href="Beginner-Tutorial-Rules.html"><spanclass="doc std std-doc">previous lesson about rules and dice rolling</span></a> we made some
assumptions about the “Player Character” entity:</p>
<ulclass="simple">
<li><p>It should store Abilities on itself as <codeclass="docutils literal notranslate"><spanclass="pre">character.strength</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">character.constitution</span></code> etc.</p></li>
<li><p>It should have a <codeclass="docutils literal notranslate"><spanclass="pre">.heal(amount)</span></code> method.</p></li>
</ul>
<p>So we have some guidelines of how it should look! A Character is a database entity with values that
should be able to be changed over time. It makes sense to base it off Evennia’s
<aclass="reference internal"href="../../../Components/Typeclasses.html"><spanclass="doc std std-doc">DefaultCharacter Typeclass</span></a>. The Character class is like a ‘character sheet’ in a tabletop
RPG, it will hold everything relevant to that PC.</p>
<sectionid="inheritance-structure">
<h2><spanclass="section-number">3.1. </span>Inheritance structure<aclass="headerlink"href="#inheritance-structure"title="Permalink to this headline">¶</a></h2>
<p>Player Characters (PCs) are not the only “living” things in our world. We also have <em>NPCs</em>
(like shopkeepers and other friendlies) as well as <em>monsters</em> (mobs) that can attack us.</p>
<p>In code, there are a few ways we could structure this. If NPCs/monsters were just special cases of PCs,
<p>All code we put on the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class would now be inherited to <codeclass="docutils literal notranslate"><spanclass="pre">NPC</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">Mob</span></code> automatically.</p>
<p>However, in <em>Knave</em>, NPCs and particularly monsters are <em>not</em> using the same rules as PCs - they are
simplified to use a Hit-Die (HD) concept. So while still character-like, NPCs should be separate from
<p>Above, the <codeclass="docutils literal notranslate"><spanclass="pre">LivingMixin</span></code> class cannot work on its own - it just ‘patches’ the other classes with some
extra functionality all living things should be able to do. This is an example of
<em>multiple inheritance</em>. It’s useful to know about, but one should not over-do multiple inheritance
since it can also get confusing to follow the code.</p>
</section>
<sectionid="living-mixin-class">
<h2><spanclass="section-number">3.2. </span>Living mixin class<aclass="headerlink"href="#living-mixin-class"title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><p>Create a new module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/evadventure/characters.py</span></code></p>
</div></blockquote>
<p>Let’s get some useful common methods all living things should have in our game.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/evadventure/characters.py </span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You heal for </span><spanclass="si">{</span><spanclass="n">healed</span><spanclass="si">}</span><spanclass="s2"> HP."</span><spanclass="p">)</span>
<p>Most of these are empty since they will behave differently for characters and npcs. But having them in the mixin means we can expect these methods to be available for all living things.</p>
<p>Once we create more of our game, we will need to remember to actually call these hook methods so they serve a purpose. For example, once we implement combat, we must remember to call <codeclass="docutils literal notranslate"><spanclass="pre">at_attacked</span></code> as well as the other methods involving taking damage, getting defeated or dying.</p>
<p>We make an assumption about our rooms here - that they have a property <codeclass="docutils literal notranslate"><spanclass="pre">.allow_death</span></code>. We need to make a note to actually add such a property to rooms later!</p>
<p>In our <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class we implement all attributes we want to simulate from the <em>Knave</em> ruleset.
The <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> is one way to add an Attribute in a field-like way; these will be accessible on every character in several ways:</p>
<p>See <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> for seeing how Attributes work.</p>
<p>Unlike in base <em>Knave</em>, we store <codeclass="docutils literal notranslate"><spanclass="pre">coins</span></code> as a separate Attribute rather than as items in the inventory, this makes it easier to handle barter and trading later.</p>
<p>We implement the Player Character versions of <codeclass="docutils literal notranslate"><spanclass="pre">at_defeat</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">at_death</span></code>. We also make use of <codeclass="docutils literal notranslate"><spanclass="pre">.heal()</span></code> from the <codeclass="docutils literal notranslate"><spanclass="pre">LivingMixin</span></code> class.</p>
<h3><spanclass="section-number">3.3.1. </span>Funcparser inlines<aclass="headerlink"href="#funcparser-inlines"title="Permalink to this headline">¶</a></h3>
<p>This piece of code is worth some more explanation:</p>
<p>Remember that <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> is the Character instance here. So <codeclass="docutils literal notranslate"><spanclass="pre">self.location.msg_contents</span></code> means “send a message to everything inside my current location”. In other words, send a message to everyone in the same place as the character.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">$You()</span><spanclass="pre">$conj(collapse)</span></code> are <aclass="reference internal"href="../../../Components/FuncParser.html"><spanclass="doc std std-doc">FuncParser inlines</span></a>. These are functions that
execute in the string. The resulting string may look different for different audiences. The <codeclass="docutils literal notranslate"><spanclass="pre">$You()</span></code> inline function will use <codeclass="docutils literal notranslate"><spanclass="pre">from_obj</span></code> to figure out who ‘you’ are and either show your name or ‘You’. The <codeclass="docutils literal notranslate"><spanclass="pre">$conj()</span></code> (verb conjugator) will tweak the (English) verb to match.</p>
<li><p>You will see: <codeclass="docutils literal notranslate"><spanclass="pre">"You</span><spanclass="pre">collapse</span><spanclass="pre">in</span><spanclass="pre">a</span><spanclass="pre">heap,</span><spanclass="pre">alive</span><spanclass="pre">but</span><spanclass="pre">beaten."</span></code></p></li>
<li><p>Others in the room will see: <codeclass="docutils literal notranslate"><spanclass="pre">"Thomas</span><spanclass="pre">collapses</span><spanclass="pre">in</span><spanclass="pre">a</span><spanclass="pre">heap,</span><spanclass="pre">alive</span><spanclass="pre">but</span><spanclass="pre">beaten."</span></code></p></li>
</ul>
<p>Note how <codeclass="docutils literal notranslate"><spanclass="pre">$conj()</span></code> chose <codeclass="docutils literal notranslate"><spanclass="pre">collapse/collapses</span></code> to make the sentences grammatically correct.</p>
</section>
<sectionid="backtracking">
<h3><spanclass="section-number">3.3.2. </span>Backtracking<aclass="headerlink"href="#backtracking"title="Permalink to this headline">¶</a></h3>
<p>We make our first use of the <codeclass="docutils literal notranslate"><spanclass="pre">rules.dice</span></code> roller to roll on the death table! As you may recall, in the previous lesson, we didn’t know just what to do when rolling ‘dead’ on this table. Now we know - we should be calling <codeclass="docutils literal notranslate"><spanclass="pre">at_death</span></code> on the character. So let’s add that where we had TODOs before:</p>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">at_death</span><spanclass="p">()</span><spanclass="c1"># <------ TODO no more</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">at_death</span><spanclass="p">()</span><spanclass="c1"># <------- TODO no more</span>
<h2><spanclass="section-number">3.4. </span>Connecting the Character with Evennia<aclass="headerlink"href="#connecting-the-character-with-evennia"title="Permalink to this headline">¶</a></h2>
<p>You can easily make yourself an <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureCharacter</span></code> in-game by using the
<p>You can now do <codeclass="docutils literal notranslate"><spanclass="pre">examine</span><spanclass="pre">self</span></code> to check your type updated.</p>
<p>If you want <em>all</em> new Characters to be of this type you need to tell Evennia about it. Evennia
uses a global setting <codeclass="docutils literal notranslate"><spanclass="pre">BASE_CHARACTER_TYPECLASS</span></code> to know which typeclass to use when creating
Characters (when logging in, for example). This defaults to <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.characters.Character</span></code> (that is,
the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code>).</p>
<p>There are thus two ways to weave your new Character class into Evennia:</p>
<li><p>Or, change <codeclass="docutils literal notranslate"><spanclass="pre">typeclasses.characters.Character</span></code> to inherit from <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureCharacter</span></code>.</p></li>
</ol>
<p>You must always reload the server for changes like this to take effect.</p>
<divclass="admonition important">
<pclass="admonition-title">Important</p>
<p>In this tutorial we are making all changes in a folder <codeclass="docutils literal notranslate"><spanclass="pre">mygame/evadventure/</span></code>. This means we can isolate
our code but means we need to do some extra steps to tie the character (and other objects) into Evennia.
For your own game it would be just fine to start editing <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code> directly
instead.</p>
</div>
</section>
<sectionid="unit-testing">
<h2><spanclass="section-number">3.5. </span>Unit Testing<aclass="headerlink"href="#unit-testing"title="Permalink to this headline">¶</a></h2>
<blockquote>
<div><p>Create a new module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/evadventure/tests/test_characters.py</span></code></p>
</div></blockquote>
<p>For testing, we just need to create a new EvAdventure character and check
that calling the methods on it doesn’t error out.</p>
<spanclass="c1"># tests for other methods ... </span>
</pre></div>
</div>
<p>If you followed the previous lessons, these tests should look familiar. Consider adding
tests for other methods as practice. Refer to previous lessons for details.</p>
<p>For running the tests you do:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span> evennia test --settings settings.py .evadventure.tests.test_character
</pre></div>
</div>
</section>
<sectionid="about-races-and-classes">
<h2><spanclass="section-number">3.6. </span>About races and classes<aclass="headerlink"href="#about-races-and-classes"title="Permalink to this headline">¶</a></h2>
<p><em>Knave</em> doesn’t have any D&D-style <em>classes</em> (like Thief, Fighter etc). It also does not bother with
<em>races</em> (like dwarves, elves etc). This makes the tutorial shorter, but you may ask yourself how you’d
add these functions.</p>
<p>In the framework we have sketched out for <em>Knave</em>, it would be simple - you’d add your race/class as
<p>We use <codeclass="docutils literal notranslate"><spanclass="pre">charclass</span></code> rather than <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> here, because <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> is a reserved Python keyword. Naming
<codeclass="docutils literal notranslate"><spanclass="pre">race</span></code> as <codeclass="docutils literal notranslate"><spanclass="pre">charrace</span></code> thus matches in style.</p>
<p>We’d then need to expand our <aclass="reference internal"href="Beginner-Tutorial-Rules.html"><spanclass="doc std std-doc">rules module</span></a> (and later
<aclass="reference internal"href="Beginner-Tutorial-Chargen.html"><spanclass="doc std std-doc">character generation</span></a> to check and include what these classes mean.</p>
</section>
<sectionid="summary">
<h2><spanclass="section-number">3.7. </span>Summary<aclass="headerlink"href="#summary"title="Permalink to this headline">¶</a></h2>
<p>With the <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureCharacter</span></code> class in place, we have a better understanding of how our PCs will look
like under <em>Knave</em>.</p>
<p>For now, we only have bits and pieces and haven’t been testing this code in-game. But if you want
you can swap yourself into <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureCharacter</span></code> right now. Log into your game and run
<p>If all went well, <codeclass="docutils literal notranslate"><spanclass="pre">ex</span><spanclass="pre">self</span></code> will now show your typeclass as being <codeclass="docutils literal notranslate"><spanclass="pre">EvAdventureCharacter</span></code>.
<p>When doing <codeclass="docutils literal notranslate"><spanclass="pre">ex</span><spanclass="pre">self</span></code> you will <em>not</em> see all your Abilities listed yet. That’s because
Attributes added with <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> are not available until they have been accessed at
least once. So once you set (or look at) <codeclass="docutils literal notranslate"><spanclass="pre">.strength</span></code> above, <codeclass="docutils literal notranslate"><spanclass="pre">strength</span></code> will show in <codeclass="docutils literal notranslate"><spanclass="pre">examine</span></code> from