<li><p>Put everything you would need to look up in a rule book into a module in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/world</span></code>. Hide away
as much as you can. Think of it as a black box (or maybe the code representation of an all-knowing
game master). The rest of your game will ask this black box questions and get answers back. Exactly
how it arrives at those results should not need to be known outside the box. Doing it this way
makes it easier to change and update things in one place later.</p></li>
<li><p>Store only the minimum stuff you need with each game object. That is, if your Characters need
values for Health, a list of skills etc, store those things on the Character - don’t store how to
roll or change them.</p></li>
<li><p>Next is to determine just how you want to store things on your Objects and Characters. You can
choose to either store things as individual <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc">Attributes</span></a>, like <codeclass="docutils literal notranslate"><spanclass="pre">character.db.STR=34</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">character.db.Hunting_skill=20</span></code>. But you could also use some custom storage method, like a
dictionary <codeclass="docutils literal notranslate"><spanclass="pre">character.db.skills</span><spanclass="pre">=</span><spanclass="pre">{"Hunting":34,</span><spanclass="pre">"Fishing":20,</span><spanclass="pre">...}</span></code>. A much more fancy solution is
to look at the Ainneve <aclass="reference external"href="https://github.com/evennia/ainneve/blob/master/world/traits.py">Trait
with a <aclass="reference internal"href="../../../Concepts/New-Models.html"><spanclass="doc">custom django model</span></a>. Which is the better depends on your game and the
<p>Inspired by tabletop role playing games, most game systems mimic some sort of die mechanic. To this
end Evennia offers a full <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py">dice
roller</a> in its <codeclass="docutils literal notranslate"><spanclass="pre">contrib</span></code>
folder. For custom implementations, Python offers many ways to randomize a result using its in-built
<codeclass="docutils literal notranslate"><spanclass="pre">random</span></code> module. No matter how it’s implemented, we will in this text refer to the action of
determining an outcome as a “roll”.</p>
<p>In a freeform system, the result of the roll is just compared with values and people (or the game
master) just agree on what it means. In a coded system the result now needs to be processed somehow.
There are many things that may happen as a result of rule enforcement:</p>
<li><p>A skill <codeclass="docutils literal notranslate"><spanclass="pre">combat</span></code>, which determines how good they are at hitting things. Starts between 5 and</p></li>
<li><p>Their Strength, <codeclass="docutils literal notranslate"><spanclass="pre">STR</span></code>, which determine how much damage they do. Starts between 1 and 10.</p></li>
<li><p>Their Health points, <codeclass="docutils literal notranslate"><spanclass="pre">HP</span></code>, which starts at 100.</p></li>
<li><p>When a Character reaches <codeclass="docutils literal notranslate"><spanclass="pre">HP</span><spanclass="pre">=</span><spanclass="pre">0</span></code>, they are presumed “defeated”. Their HP is reset and they get a
failure message (as a stand-in for death code).</p></li>
<li><p>“Rolls” are done by rolling a 100-sided die. If the result is below the <codeclass="docutils literal notranslate"><spanclass="pre">combat</span></code> value, it’s a
success and damage is rolled. Damage is rolled as a six-sided die + the value of <codeclass="docutils literal notranslate"><spanclass="pre">STR</span></code> (for this
example we ignore weapons and assume <codeclass="docutils literal notranslate"><spanclass="pre">STR</span></code> is all that matters).</p></li>
<li><p>Every successful <codeclass="docutils literal notranslate"><spanclass="pre">attack</span></code> roll gives 1-3 experience points (<codeclass="docutils literal notranslate"><spanclass="pre">XP</span></code>). Every time the number of <codeclass="docutils literal notranslate"><spanclass="pre">XP</span></code>
reaches <codeclass="docutils literal notranslate"><spanclass="pre">(level</span><spanclass="pre">+</span><spanclass="pre">1)</span><spanclass="pre">**</span><spanclass="pre">2</span></code>, the Character levels up. When leveling up, the Character’s <codeclass="docutils literal notranslate"><spanclass="pre">combat</span></code>
value goes up by 2 points and <codeclass="docutils literal notranslate"><spanclass="pre">STR</span></code> by one (this is a stand-in for a real progression system).</p></li>
<p>The Character typeclass is simple. It goes in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/characters.py</span></code>. There is already
an empty <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> class there that Evennia will look to and use.</p>
<p><codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code> the server to load up the new code. Doing <codeclass="docutils literal notranslate"><spanclass="pre">examine</span><spanclass="pre">self</span></code> will however <em>not</em> show the new
Attributes on yourself. This is because the <codeclass="docutils literal notranslate"><spanclass="pre">at_object_creation</span></code> hook is only called on <em>new</em>
Characters. Your Character was already created and will thus not have them. To force a reload, use
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">examine</span><spanclass="pre">self</span></code> command will now show the new Attributes.</p>
</div>
<divclass="section"id="rule-module">
<h3>Rule module<aclass="headerlink"href="#rule-module"title="Permalink to this headline">¶</a></h3>
<p>This is a module <codeclass="docutils literal notranslate"><spanclass="pre">mygame/world/rules.py</span></code>.</p>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You fall down, defeated!"</span><spanclass="p">)</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You are now level </span><spanclass="si">%i</span><spanclass="s2">!"</span><spanclass="o">%</span><spanclass="n">character</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">level</span><spanclass="p">)</span>
<spanclass="n">failtext</span><spanclass="o">=</span><spanclass="s2">"You are hit by </span><spanclass="si">%s</span><spanclass="s2"> for </span><spanclass="si">%i</span><spanclass="s2"> damage!"</span>
<spanclass="n">wintext</span><spanclass="o">=</span><spanclass="s2">"You hit </span><spanclass="si">%s</span><spanclass="s2"> for </span><spanclass="si">%i</span><spanclass="s2"> damage!"</span>
<spanclass="k">raise</span><spanclass="n">RunTimeError</span><spanclass="p">(</span><spanclass="s2">"Skillname </span><spanclass="si">%s</span><spanclass="s2"> not found."</span><spanclass="o">%</span><spanclass="n">skillname</span><spanclass="p">)</span>
<p>These few functions implement the entirety of our simple rule system. We have a function to check
the “defeat” condition and reset the <codeclass="docutils literal notranslate"><spanclass="pre">HP</span></code> back to 100 again. We define a generic “skill” function.
Multiple skills could all be added with the same signature; our <codeclass="docutils literal notranslate"><spanclass="pre">SKILLS</span></code> dictionary makes it easy to
look up the skills regardless of what their actual functions are called. Finally, the access
function <codeclass="docutils literal notranslate"><spanclass="pre">roll_challenge</span></code> just picks the skill and gets the result.</p>
<p>In this example, the skill function actually does a lot - it not only rolls results, it also informs
everyone of their results via <codeclass="docutils literal notranslate"><spanclass="pre">character.msg()</span></code> calls.</p>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You need to pick a target to attack."</span><spanclass="p">)</span>
<p>Note how simple the command becomes and how generic you can make it. It becomes simple to offer any
number of Combat commands by just extending this functionality - you can easily roll challenges and
pick different skills to check. And if you ever decided to, say, change how to determine hit chance,
you don’t have to change every command, but need only change the single <codeclass="docutils literal notranslate"><spanclass="pre">roll_hit</span></code> function inside
your <codeclass="docutils literal notranslate"><spanclass="pre">rules</span></code> module.</p>