Updated HTML docs

This commit is contained in:
Griatch 2021-10-26 21:41:11 +02:00
parent 66d0ad0bc9
commit 7900aad365
2073 changed files with 32986 additions and 41197 deletions

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,7 +49,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="our-own-commands">
<section class="tex2jax_ignore mathjax_ignore" id="our-own-commands">
<h1>Our own commands<a class="headerlink" href="#our-own-commands" title="Permalink to this headline"></a></h1>
<p>In this lesson well learn how to create our own Evennia <em>Commands</em>. If you are new to Python youll
also learn some more basics about how to manipulate strings and get information out of Evennia.</p>
@ -56,9 +58,11 @@ An example is <code class="docutils literal notranslate"><span class="pre">look<
what is in it.</p>
<aside class="sidebar">
<p class="sidebar-title">Commands are not typeclassed</p>
<p>If you just came from the previous lesson, you might want to know that Commands and
CommandSets are not <cite>typeclassed</cite>. That is, instances of them are not saved to the
database. They are “just” normal Python classes.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>If you just came from the previous lesson, you might want to know that Commands and
CommandSets are not `typeclassed`. That is, instances of them are not saved to the
database. They are &quot;just&quot; normal Python classes.
</pre></div>
</div>
</aside>
<p>In Evennia, a Command is a Python <em>class</em>. If you are unsure about what a class is, review the
previous lessons! A Command inherits from <code class="docutils literal notranslate"><span class="pre">evennia.Command</span></code> or from one of the alternative command-
@ -77,21 +81,7 @@ commands in that cmdset available to the object. So, to summarize:</p>
<section id="creating-a-custom-command">
<h2>Creating a custom command<a class="headerlink" href="#creating-a-custom-command" title="Permalink to this headline"></a></h2>
<p>Open <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">(module docstring)</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -107,7 +97,7 @@ commands in that cmdset available to the object. So, to summarize:</p>
<span class="c1"># (lots of commented-out stuff)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Ignoring the docstrings (which you can read if you want), this is the only really active code in the module.</p>
<p>We can see that we import <code class="docutils literal notranslate"><span class="pre">Command</span></code> from <code class="docutils literal notranslate"><span class="pre">evennia</span></code> and use the <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span> <span class="pre">...</span> <span class="pre">as</span> <span class="pre">...</span></code> form to rename it
to <code class="docutils literal notranslate"><span class="pre">BaseCommand</span></code>. This is so we can let our child class also be named <code class="docutils literal notranslate"><span class="pre">Command</span></code> for reference. The class
@ -119,32 +109,18 @@ that a little later.</p>
</div></blockquote>
<p>We could modify this module directly, but to train imports well work in a separate module. Open a new file
<code class="docutils literal notranslate"><span class="pre">mygame/commands/mycommands.py</span></code> and add the following code:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">Command</span>
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;echo&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This is the simplest form of command you can imagine. It just gives itself a name, “echo”. This is
what you will use to call this command later.</p>
<p>Next we need to put this in a CmdSet. It will be a one-command CmdSet for now! Change your file as such:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="kn">from</span> <span class="nn">commands.command</span> <span class="kn">import</span> <span class="n">Command</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
@ -156,19 +132,20 @@ what you will use to call this command later.</p>
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdEcho</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Our <code class="docutils literal notranslate"><span class="pre">EchoCmdSet</span></code> class must have an <code class="docutils literal notranslate"><span class="pre">at_cmdset_creation</span></code> method, named exactly
like this - this is what Evennia will be looking for when setting up the cmdset later, so
if you didnt set it up, it will use the parents version, which is empty. Inside we add the
command class to the cmdset by <code class="docutils literal notranslate"><span class="pre">self.add()</span></code>. If you wanted to add more commands to this CmdSet you
could just add more lines of <code class="docutils literal notranslate"><span class="pre">self.add</span></code> after this.</p>
<p>Finally, lets add this command to ourselves so we can try it out. In-game you can experiment with <code class="docutils literal notranslate"><span class="pre">py</span></code> again:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;commands.mycommands.MyCmdSet&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.cmdset.add(&quot;commands.mycommands.MyCmdSet&quot;)
</pre></div>
</div>
<p>Now try</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; echo
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; echo
Command echo has no defined `func()` - showing on-command variables:
...
...
@ -177,7 +154,7 @@ Command echo has no defined `func()` - showing on-command variables:
<p>You should be getting a long list of outputs. The reason for this is that your <code class="docutils literal notranslate"><span class="pre">echo</span></code> function is not really
“doing” anything yet and the default function is then to show all useful resources available to you when you
use your Command. Lets look at some of those listed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Command echo has no defined `func()` - showing on-command variables:
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Command echo has no defined `func()` - showing on-command variables:
obj (&lt;class &#39;typeclasses.characters.Character&#39;&gt;): YourName
lockhandler (&lt;class &#39;evennia.locks.lockhandler.LockHandler&#39;&gt;): cmd:all()
caller (&lt;class &#39;typeclasses.characters.Character&#39;&gt;): YourName
@ -219,22 +196,7 @@ that this would be <code class="docutils literal notranslate"><span class="pre">
</ul>
<p>The reason our command doesnt do anything yet is because its missing a <code class="docutils literal notranslate"><span class="pre">func</span></code> method. This is what Evennia
looks for to figure out what a Command actually does. Modify your <code class="docutils literal notranslate"><span class="pre">CmdEcho</span></code> class:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -251,50 +213,35 @@ looks for to figure out what a Command actually does. Modify your <code class="d
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>First we added a docstring. This is always a good thing to do in general, but for a Command class, it will also
automatically become the in-game help entry! Next we add the <code class="docutils literal notranslate"><span class="pre">func</span></code> method. It has one active line where it
makes use of some of those variables we found the Command offers to us. If you did the
<a class="reference internal" href="Python-basic-introduction.html"><span class="doc">basic Python tutorial</span></a>, you will recognize <code class="docutils literal notranslate"><span class="pre">.msg</span></code> - this will send a message
<a class="reference internal" href="Python-basic-introduction.html"><span class="doc std std-doc">basic Python tutorial</span></a>, you will recognize <code class="docutils literal notranslate"><span class="pre">.msg</span></code> - this will send a message
to the object it is attached to us - in this case <code class="docutils literal notranslate"><span class="pre">self.caller</span></code>, that is, us. We grab <code class="docutils literal notranslate"><span class="pre">self.args</span></code> and includes
that in the message.</p>
<p>Since we havent changed <code class="docutils literal notranslate"><span class="pre">MyCmdSet</span></code>, that will work as before. Reload and re-add this command to ourselves to
try out the new version:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;commands.mycommands.MyCmdSet&quot;</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">echo</span>
<span class="n">Echo</span><span class="p">:</span> <span class="s1">&#39;&#39;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.cmdset.add(&quot;commands.mycommands.MyCmdSet&quot;)
&gt; echo
Echo: &#39;&#39;
</pre></div>
</div>
<p>Try to pass an argument:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; echo Woo Tang!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; echo Woo Tang!
Echo: &#39; Woo Tang!&#39;
</pre></div>
</div>
<p>Note that there is an extra space before <code class="docutils literal notranslate"><span class="pre">Woo!</span></code>. That is because self.args contains the <em>everything</em> after
the command name, including spaces. Evennia will happily understand if you skip that space too:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; echoWoo Tang!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; echoWoo Tang!
Echo: &#39;Woo Tang!&#39;
</pre></div>
</div>
<p>There are ways to force Evennia to <em>require</em> an initial space, but right now we want to just ignore it since
it looks a bit weird for our echo example. Tweak the code:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="k">class</span> <span class="nc">CmdEcho</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -311,18 +258,18 @@ it looks a bit weird for our echo example. Tweak the code:</p>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The only difference is that we called <code class="docutils literal notranslate"><span class="pre">.strip()</span></code> on <code class="docutils literal notranslate"><span class="pre">self.args</span></code>. This is a helper method available on all
strings - it strips out all whitespace before and after the string. Now the Command-argument will no longer
have any space in front of it.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; reload
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.cmdset.add(&quot;commands.mycommands.MyCmdSet&quot;)
&gt; echo Woo Tang!
Echo: &#39;Woo Tang!&#39;
</pre></div>
</div>
<p>Dont forget to look at the help for the echo command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">help</span> <span class="n">echo</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; help echo
</pre></div>
</div>
<p>You will get the docstring you put in your Command-class.</p>
@ -330,12 +277,12 @@ Echo: &#39;Woo Tang!&#39;
<h3>Making our cmdset persistent<a class="headerlink" href="#making-our-cmdset-persistent" title="Permalink to this headline"></a></h3>
<p>Its getting a little annoying to have to re-add our cmdset every time we reload, right? Its simple
enough to make <code class="docutils literal notranslate"><span class="pre">echo</span></code> a <em>persistent</em> change though:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;commands.mycommands.MyCmdSet&quot;</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.cmdset.add(&quot;commands.mycommands.MyCmdSet&quot;, persistent=True)
</pre></div>
</div>
<p>Now you can <code class="docutils literal notranslate"><span class="pre">reload</span></code> as much as you want and your code changes will be available directly without
needing to re-add the MyCmdSet again. To remove the cmdset again, do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;commands.mycommands.MyCmdSet&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.cmdset.remove(&quot;commands.mycommands.MyCmdSet&quot;)
</pre></div>
</div>
<p>But for now, keep it around, well expand it with some more examples.</p>
@ -344,39 +291,17 @@ needing to re-add the MyCmdSet again. To remove the cmdset again, do</p>
<h3>Figuring out who to hit<a class="headerlink" href="#figuring-out-who-to-hit" title="Permalink to this headline"></a></h3>
<p>Lets try something a little more exciting than just echo. Lets make a <code class="docutils literal notranslate"><span class="pre">hit</span></code> command, for punching
someone in the face! This is how we want it to work:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; hit &lt;target&gt;
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hit &lt;target&gt;
You hit &lt;target&gt; with full force!
</pre></div>
</div>
<p>Not only that, we want the <target> to see</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>You got hit by &lt;hitter&gt; with full force!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>You got hit by &lt;hitter&gt; with full force!
</pre></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">&lt;hitter&gt;</span></code> would be the one using the <code class="docutils literal notranslate"><span class="pre">hit</span></code> command and <code class="docutils literal notranslate"><span class="pre">&lt;target&gt;</span></code> is the one doing the punching.</p>
<p>Still in <code class="docutils literal notranslate"><span class="pre">mygame/commands/mycommands.py</span></code>, add a new class, between <code class="docutils literal notranslate"><span class="pre">CmdEcho</span></code> and <code class="docutils literal notranslate"><span class="pre">MyCmdSet</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="k">class</span> <span class="nc">CmdHit</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -399,8 +324,9 @@ You hit &lt;target&gt; with full force!
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You hit </span><span class="si">{</span><span class="n">target</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> with full force!&quot;</span><span class="p">)</span>
<span class="n">target</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You got hit by </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> with full force!&quot;</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>A lot of things to dissect here:</p>
<ul class="simple">
<li><p><strong>Line 4</strong>: The normal <code class="docutils literal notranslate"><span class="pre">class</span></code> header. We inherit from <code class="docutils literal notranslate"><span class="pre">Command</span></code> which we imported at the top of this file.</p></li>
@ -413,20 +339,20 @@ have the whitespace and is not the same as <code class="docutils literal notrans
</ul>
<aside class="sidebar">
<p class="sidebar-title">if-statements</p>
<p>The full form of the if statement is</p>
<blockquote>
<div><dl class="simple">
<dt>if condition:</dt><dd><p></p>
</dd>
<dt>elif othercondition:</dt><dd><p></p>
</dd>
<dt>else:</dt><dd><p></p>
</dd>
</dl>
</div></blockquote>
<p>There can be any number of <cite>elifs</cite> to mark when different branches of the code should run. If
the <cite>else</cite> condition is given, it will run if none of the other conditions was truthy. In Python
the <cite>if..elif..else</cite> structure also serves the same function as <cite>case</cite> in some other languages.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The full form of the if statement is
if condition:
...
elif othercondition:
...
else:
...
There can be any number of `elifs` to mark when different branches of the code should run. If
the `else` condition is given, it will run if none of the other conditions was truthy. In Python
the `if..elif..else` structure also serves the same function as `case` in some other languages.
</pre></div>
</div>
</aside>
<ul>
<li><p><strong>Line 16</strong> has our first <em>conditional</em>, an <code class="docutils literal notranslate"><span class="pre">if</span></code> statement. This is written on the form <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">&lt;condition&gt;:</span></code> and only
@ -451,32 +377,29 @@ In that case, <code class="docutils literal notranslate"><span class="pre">targe
<li><p><strong>Lines 22-23</strong>: At this point we have a suitable target and can send our punching strings to each.</p></li>
</ul>
<p>Finally we must also add this to a CmdSet. Lets add it to <code class="docutils literal notranslate"><span class="pre">MyCmdSet</span></code> which we made persistent earlier.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="k">class</span> <span class="nc">MyCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdEcho</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdHit</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Errors in your code</p>
<p>With longer code snippets to try, it gets more and more likely youll
make an error and get a <cite>traceback</cite> when you reload. This will either appear
directly in-game or in your log (view it with <cite>evennia -l</cite> in a terminal).
Dont panic; tracebacks are your friends - they are to be read bottom-up and usually describe
exactly where your problem is. Refer to <a class="reference external" href="Python-basic-introduction.html">The Python intro</a> for
more hints. If you get stuck, reach out to the Evennia community for help.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>With longer code snippets to try, it gets more and more likely you&#39;ll
make an error and get a `traceback` when you reload. This will either appear
directly in-game or in your log (view it with `evennia -l` in a terminal).
Don&#39;t panic; tracebacks are your friends - they are to be read bottom-up and usually describe
exactly where your problem is. Refer to `The Python intro &lt;Python-basic-introduction.html&gt;`_ for
more hints. If you get stuck, reach out to the Evennia community for help.
</pre></div>
</div>
</aside>
<p>Next we reload to let Evennia know of these code changes and try it out:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; reload
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
hit
Who do you want to hit?
hit me
@ -486,7 +409,7 @@ You got hit by YourName with full force!
</div>
<p>Lacking a target, we hit ourselves. If you have one of the dragons still around from the previous lesson
you could try to hit it (if you dare):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>hit smaug
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>hit smaug
You hit Smaug with full force!
</pre></div>
</div>
@ -561,7 +484,7 @@ get into how we replace and extend Evennias default Commands.</p>
<h3>Versions</h3>
<ul>
<li><a href="Adding-Commands.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,19 +49,19 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="using-the-game-and-building-stuff">
<section class="tex2jax_ignore mathjax_ignore" id="using-the-game-and-building-stuff">
<h1>Using the game and building stuff<a class="headerlink" href="#using-the-game-and-building-stuff" title="Permalink to this headline"></a></h1>
<p>In this lesson we will test out what we can do in-game out-of-the-box. Evennia ships with
<a class="reference external" href="../../../api/evennia.commands.default.html#modules">around 90 default commands</a>, and while you can override those as you please,
<a class="reference internal" href="../../../Components/Default-Commands.html"><span class="doc std std-doc">around 90 default commands</span></a>, and while you can override those as you please,
they can be quite useful.</p>
<p>Connect and log into your new game and you will end up in the “Limbo” location. This
is the only room in the game at this point. Lets explore the commands a little.</p>
<p>The default commands has syntax <a class="reference internal" href="../../../Concepts/Using-MUX-as-a-Standard.html"><span class="doc">similar to MUX</span></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">command</span><span class="p">[</span><span class="o">/</span><span class="n">switch</span><span class="o">/</span><span class="n">switch</span><span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">arguments</span> <span class="o">...</span><span class="p">]</span>
<p>The default commands has syntax <a class="reference internal" href="../../../Concepts/Using-MUX-as-a-Standard.html"><span class="doc std std-doc">similar to MUX</span></a>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> command[/switch/switch...] [arguments ...]
</pre></div>
</div>
<p>An example would be</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> create/drop box
</pre></div>
</div>
<p>A <em>/switch</em> is a special, optional flag to the command to make it behave differently. It is always
@ -72,11 +74,11 @@ the preceeding &#64;.</p>
</div></blockquote>
<section id="getting-help">
<h2>Getting help<a class="headerlink" href="#getting-help" title="Permalink to this headline"></a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">help</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>help
</pre></div>
</div>
<p>Will give you a list of all commands available to you. Use</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">help</span> <span class="o">&lt;</span><span class="n">commandname</span><span class="o">&gt;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>help &lt;commandname&gt;
</pre></div>
</div>
<p>to see the in-game help for that command.</p>
@ -84,13 +86,13 @@ the preceeding &#64;.</p>
<section id="looking-around">
<h2>Looking around<a class="headerlink" href="#looking-around" title="Permalink to this headline"></a></h2>
<p>The most common comman is</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">look</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>look
</pre></div>
</div>
<p>This will show you the description of the current location. <code class="docutils literal notranslate"><span class="pre">l</span></code> is an alias.</p>
<p>When targeting objects in commands you have two special labels you can use, <code class="docutils literal notranslate"><span class="pre">here</span></code> for the current
room or <code class="docutils literal notranslate"><span class="pre">me</span></code>/<code class="docutils literal notranslate"><span class="pre">self</span></code> to point back to yourself. So</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">look</span> <span class="n">me</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>look me
</pre></div>
</div>
<p>will give you your own description. <code class="docutils literal notranslate"><span class="pre">look</span> <span class="pre">here</span></code> is, in this case, the same as plain <code class="docutils literal notranslate"><span class="pre">look</span></code>.</p>
@ -102,14 +104,14 @@ room or <code class="docutils literal notranslate"><span class="pre">me</span></
restrictions such as locks. This can be useful, but it also hides some functionality that you might
want to test.</p>
<p>To temporarily step down from your superuser position you can use the <code class="docutils literal notranslate"><span class="pre">quell</span></code> command in-game:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">quell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>quell
</pre></div>
</div>
<p>This will make you start using the permission of your current characters level instead of your
superuser level. If you didnt change any settings your game Character should have an <em>Developer</em>
level permission - high as can be without bypassing locks like the superuser does. This will work
fine for the examples on this page. Use</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">unquell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>unquell
</pre></div>
</div>
<p>to get superuser status again when you are done.</p>
@ -118,20 +120,22 @@ fine for the examples on this page. Use</p>
<h2>Creating an Object<a class="headerlink" href="#creating-an-object" title="Permalink to this headline"></a></h2>
<p>Basic objects can be anything swords, flowers and non-player characters. They are created using
the <code class="docutils literal notranslate"><span class="pre">create</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">create</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>create box
</pre></div>
</div>
<p>This created a new box (of the default object type) in your inventory. Use the command <code class="docutils literal notranslate"><span class="pre">inventory</span></code>
(or <code class="docutils literal notranslate"><span class="pre">i</span></code>) to see it. Now, box is a rather short name, lets rename it and tack on a few aliases.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">name</span> <span class="n">box</span> <span class="o">=</span> <span class="n">very</span> <span class="n">large</span> <span class="n">box</span><span class="p">;</span><span class="n">box</span><span class="p">;</span><span class="n">very</span><span class="p">;</span><span class="n">crate</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>name box = very large box;box;very;crate
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>MUD clients and semi-colon</p>
<p>Some traditional MUD clients use the semi-colon <cite>;</cite> to separate client inputs. If so,
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Some traditional MUD clients use the semi-colon `;` to separate client inputs. If so,
the above line will give an error. You need to change your client to use another command-separator
or to put it in verbatim mode. If you still have trouble, use the Evennia web client instead.</p>
or to put it in &#39;verbatim&#39; mode. If you still have trouble, use the Evennia web client instead.
</pre></div>
</div>
</div>
<p>We now renamed the box to <em>very large box</em> (and this is what we will see when looking at it), but we
will also recognize it by any of the other names we give - like <em>crate</em> or simply <em>box</em> as before.
@ -141,64 +145,64 @@ new object. If you had wanted to not change the name itself, but to only add ali
used the <code class="docutils literal notranslate"><span class="pre">alias</span></code> command.</p>
<p>We are currently carrying the box. Lets drop it (there is also a short cut to create and drop in
one go by using the <code class="docutils literal notranslate"><span class="pre">/drop</span></code> switch, for example <code class="docutils literal notranslate"><span class="pre">create/drop</span> <span class="pre">box</span></code>).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">drop</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>drop box
</pre></div>
</div>
<p>Hey presto - there it is on the ground, in all its normality.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">examine</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>examine box
</pre></div>
</div>
<p>This will show some technical details about the box object. For now we will ignore what this
information means.</p>
<p>Try to <code class="docutils literal notranslate"><span class="pre">look</span></code> at the box to see the (default) description.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">look</span> <span class="n">box</span>
<span class="n">You</span> <span class="n">see</span> <span class="n">nothing</span> <span class="n">special</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>look box
You see nothing special.
</pre></div>
</div>
<p>The description you get is not very exciting. Lets add some flavor.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">describe</span> <span class="n">box</span> <span class="o">=</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">large</span> <span class="ow">and</span> <span class="n">very</span> <span class="n">heavy</span> <span class="n">box</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>describe box = This is a large and very heavy box.
</pre></div>
</div>
<p>If you try the <code class="docutils literal notranslate"><span class="pre">get</span></code> command we will pick up the box. So far so good, but if we really want this to
be a large and heavy box, people should <em>not</em> be able to run off with it that easily. To prevent
this we need to lock it down. This is done by assigning a <em>Lock</em> to it. Make sure the box was
dropped in the room, then try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lock</span> <span class="n">box</span> <span class="o">=</span> <span class="n">get</span><span class="p">:</span><span class="n">false</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>lock box = get:false()
</pre></div>
</div>
<p>Locks represent a rather <a class="reference internal" href="../../../Components/Locks.html"><span class="doc">big topic</span></a>, but for now that will do what we want. This will lock
<p>Locks represent a rather <a class="reference internal" href="../../../Components/Locks.html"><span class="doc std std-doc">big topic</span></a>, but for now that will do what we want. This will lock
the box so noone can lift it. The exception is superusers, they override all locks and will pick it
up anyway. Make sure you are quelling your superuser powers and try to get the box now:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">get</span> <span class="n">box</span>
<span class="n">You</span> <span class="n">can</span><span class="s1">&#39;t get that.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; get box
You can&#39;t get that.
</pre></div>
</div>
<p>Think thís default error message looks dull? The <code class="docutils literal notranslate"><span class="pre">get</span></code> command looks for an <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attribute</span></a>
<p>Think thís default error message looks dull? The <code class="docutils literal notranslate"><span class="pre">get</span></code> command looks for an <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a>
named <code class="docutils literal notranslate"><span class="pre">get_err_msg</span></code> for returning a nicer error message (we just happen to know this, you would need
to peek into the
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/commands/default/general.py#L235">code</a> for
the <code class="docutils literal notranslate"><span class="pre">get</span></code> command to find out.). You set attributes using the <code class="docutils literal notranslate"><span class="pre">set</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">set</span> <span class="n">box</span><span class="o">/</span><span class="n">get_err_msg</span> <span class="o">=</span> <span class="n">It</span><span class="s1">&#39;s way too heavy for you to lift. </span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>set box/get_err_msg = It&#39;s way too heavy for you to lift.
</pre></div>
</div>
<p>Try to get it now and you should see a nicer error message echoed back to you. To see what this
message string is in the future, you can use examine.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">examine</span> <span class="n">box</span><span class="o">/</span><span class="n">get_err_msg</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>examine box/get_err_msg
</pre></div>
</div>
<p>Examine will return the value of attributes, including color codes. <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">here/desc</span></code> would return
the raw description of your current room (including color codes), so that you can copy-and-paste to
set its description to something else.</p>
<p>You create new Commands (or modify existing ones) in Python outside the game. We will get to that
later, in the <a class="reference internal" href="Adding-Commands.html"><span class="doc">Commands tutorial</span></a>.</p>
later, in the <a class="reference internal" href="Adding-Commands.html"><span class="doc std std-doc">Commands tutorial</span></a>.</p>
</section>
<section id="get-a-personality">
<h2>Get a Personality<a class="headerlink" href="#get-a-personality" title="Permalink to this headline"></a></h2>
<p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Scripts</span></a> are powerful out-of-character objects useful for many “under the hood” things.
<p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a> are powerful out-of-character objects useful for many “under the hood” things.
One of their optional abilities is to do things on a timer. To try out a first script, lets put one
on ourselves. There is an example script in <code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/bodyfunctions.py</span></code>
that is called <code class="docutils literal notranslate"><span class="pre">BodyFunctions</span></code>. To add this to us we will use the <code class="docutils literal notranslate"><span class="pre">script</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">script</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">tutorial_examples</span><span class="o">.</span><span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>script self = tutorial_examples.bodyfunctions.BodyFunctions
</pre></div>
</div>
<p>This string will tell Evennia to dig up the Python code at the place we indicate. It already knows
@ -210,7 +214,7 @@ Python code <em>inside</em> files, like the <code class="docutils literal notran
These “Python-paths” are used extensively throughout Evennia.</p>
</div></blockquote>
<p>Wait a while and you will notice yourself starting making random observations …</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">script</span> <span class="bp">self</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>script self
</pre></div>
</div>
<p>This will show details about scripts on yourself (also <code class="docutils literal notranslate"><span class="pre">examine</span></code> works). You will see how long it is
@ -218,32 +222,32 @@ until it “fires” next. Dont be alarmed if nothing happens when the countd
particular script has a randomizer to determine if it will say something or not. So you will not see
output every time it fires.</p>
<p>When you are tired of your characters “insights”, kill the script with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">script</span><span class="o">/</span><span class="n">stop</span> <span class="bp">self</span> <span class="o">=</span> <span class="n">tutorial_examples</span><span class="o">.</span><span class="n">bodyfunctions</span><span class="o">.</span><span class="n">BodyFunctions</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>script/stop self = tutorial_examples.bodyfunctions.BodyFunctions
</pre></div>
</div>
<p>You create your own scripts in Python, outside the game; the path you give to <code class="docutils literal notranslate"><span class="pre">script</span></code> is literally
the Python path to your script file. The <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Scripts</span></a> page explains more details.</p>
the Python path to your script file. The <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a> page explains more details.</p>
</section>
<section id="pushing-your-buttons">
<h2>Pushing Your Buttons<a class="headerlink" href="#pushing-your-buttons" title="Permalink to this headline"></a></h2>
<p>If we get back to the box we made, there is only so much fun you can have with it at this point. Its
just a dumb generic object. If you renamed it to <code class="docutils literal notranslate"><span class="pre">stone</span></code> and changed its description, noone would be
the wiser. However, with the combined use of custom <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc">Typeclasses</span></a>, <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Scripts</span></a>
and object-based <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Commands</span></a>, you could expand it and other items to be as unique, complex
the wiser. However, with the combined use of custom <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>, <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a>
and object-based <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Commands</span></a>, you could expand it and other items to be as unique, complex
and interactive as you want.</p>
<p>Lets take an example. So far we have only created objects that use the default object typeclass
named simply <code class="docutils literal notranslate"><span class="pre">Object</span></code>. Lets create an object that is a little more interesting. Under
<code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples</span></code> there is a module <code class="docutils literal notranslate"><span class="pre">red_button.py</span></code>. It contains the enigmatic
<code class="docutils literal notranslate"><span class="pre">RedButton</span></code> class.</p>
<p>Lets make us one of <em>those</em>!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">button</span><span class="p">:</span><span class="n">tutorial_examples</span><span class="o">.</span><span class="n">red_button</span><span class="o">.</span><span class="n">RedButton</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>create/drop button:tutorial_examples.red_button.RedButton
</pre></div>
</div>
<p>The same way we did with the Script Earler, we specify a “Python-path” to the Python code we want Evennia
to use for creating the object. There you go - one red button.</p>
<p>The RedButton is an example object intended to show off a few of Evennias features. You will find
that the <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc">Typeclass</span></a> and <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Commands</span></a> controlling it are
inside <a class="reference external" href="../../../api/evennia.contrib.tutorial_examples.html">evennia/contrib/tutorial_examples</a></p>
that the <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc std std-doc">Typeclass</span></a> and <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Commands</span></a> controlling it are
inside <a class="reference internal" href="../../../api/evennia.contrib.tutorial_examples.html"><span class="doc std std-doc">evennia/contrib/tutorial_examples</span></a></p>
<p>If you wait for a while (make sure you dropped it!) the button will blink invitingly.</p>
<p>Why dont you try to push it …?</p>
<p>Surely a big red button is meant to be pushed.</p>
@ -257,7 +261,7 @@ inside <a class="reference external" href="../../../api/evennia.contrib.tutorial
<h2>Making Yourself a House<a class="headerlink" href="#making-yourself-a-house" title="Permalink to this headline"></a></h2>
<p>The main command for shaping the game world is <code class="docutils literal notranslate"><span class="pre">dig</span></code>. For example, if you are standing in Limbo you
can dig a route to your new house location like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dig</span> <span class="n">house</span> <span class="o">=</span> <span class="n">large</span> <span class="n">red</span> <span class="n">door</span><span class="p">;</span><span class="n">door</span><span class="p">;</span><span class="ow">in</span><span class="p">,</span><span class="n">to</span> <span class="n">the</span> <span class="n">outside</span><span class="p">;</span><span class="n">out</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dig house = large red door;door;in,to the outside;out
</pre></div>
</div>
<p>This will create a new room named house. Spaces at the start/end of names and aliases are ignored
@ -268,28 +272,28 @@ the full thing all the time.</p>
<p>If you wanted to use normal compass directions (north, west, southwest etc), you could do that with
<code class="docutils literal notranslate"><span class="pre">dig</span></code> too. But Evennia also has a limited version of <code class="docutils literal notranslate"><span class="pre">dig</span></code> that helps for compass directions (and
also up/down and in/out). Its called <code class="docutils literal notranslate"><span class="pre">tunnel</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tunnel</span> <span class="n">sw</span> <span class="o">=</span> <span class="n">cliff</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>tunnel sw = cliff
</pre></div>
</div>
<p>This will create a new room “cliff” with an exit “southwest” leading there and a path “northeast”
leading back from the cliff to your current location.</p>
<p>You can create new exits from where you are, using the <code class="docutils literal notranslate"><span class="pre">open</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">open</span> <span class="n">north</span><span class="p">;</span><span class="n">n</span> <span class="o">=</span> <span class="n">house</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>open north;n = house
</pre></div>
</div>
<p>This opens an exit <code class="docutils literal notranslate"><span class="pre">north</span></code> (with an alias <code class="docutils literal notranslate"><span class="pre">n</span></code>) to the previously created room <code class="docutils literal notranslate"><span class="pre">house</span></code>.</p>
<p>If you have many rooms named <code class="docutils literal notranslate"><span class="pre">house</span></code> you will get a list of matches and have to select which one you
want to link to.</p>
<p>Follow the north exit to your house or <code class="docutils literal notranslate"><span class="pre">teleport</span></code> to it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">north</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>north
</pre></div>
</div>
<p>or:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">teleport</span> <span class="n">house</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>teleport house
</pre></div>
</div>
<p>To manually open an exit back to Limbo (if you didnt do so with the <code class="docutils literal notranslate"><span class="pre">dig</span></code> command):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">open</span> <span class="n">door</span> <span class="o">=</span> <span class="n">limbo</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>open door = limbo
</pre></div>
</div>
<p>(You can also us the #dbref of limbo, which you can find by using <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">here</span></code> when in limbo).</p>
@ -298,25 +302,25 @@ want to link to.</p>
<h2>Reshuffling the World<a class="headerlink" href="#reshuffling-the-world" title="Permalink to this headline"></a></h2>
<p>You can find things using the <code class="docutils literal notranslate"><span class="pre">find</span></code> command. Assuming you are back at <code class="docutils literal notranslate"><span class="pre">Limbo</span></code>, lets teleport the
<em>large box</em> to our house.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">teleport</span> <span class="n">box</span> <span class="o">=</span> <span class="n">house</span>
<span class="n">very</span> <span class="n">large</span> <span class="n">box</span> <span class="ow">is</span> <span class="n">leaving</span> <span class="n">Limbo</span><span class="p">,</span> <span class="n">heading</span> <span class="k">for</span> <span class="n">house</span><span class="o">.</span>
<span class="n">Teleported</span> <span class="n">very</span> <span class="n">large</span> <span class="n">box</span> <span class="o">-&gt;</span> <span class="n">house</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>teleport box = house
very large box is leaving Limbo, heading for house.
Teleported very large box -&gt; house.
</pre></div>
</div>
<p>We can still find the box by using find:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">find</span> <span class="n">box</span>
<span class="n">One</span> <span class="n">Match</span><span class="p">(</span><span class="c1">#1-#8):</span>
<span class="n">very</span> <span class="n">large</span> <span class="n">box</span><span class="p">(</span><span class="c1">#8) - src.objects.objects.Object</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>find box
One Match(#1-#8):
very large box(#8) - src.objects.objects.Object
</pre></div>
</div>
<p>Knowing the <code class="docutils literal notranslate"><span class="pre">#dbref</span></code> of the box (#8 in this example), you can grab the box and get it back here
without actually yourself going to <code class="docutils literal notranslate"><span class="pre">house</span></code> first:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">teleport</span> <span class="c1">#8 = here</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>teleport #8 = here
</pre></div>
</div>
<p>As mentioned, <code class="docutils literal notranslate"><span class="pre">here</span></code> is an alias for your current location. The box should now be back in Limbo with you.</p>
<p>We are getting tired of the box. Lets destroy it.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">destroy</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>destroy box
</pre></div>
</div>
<p>It will ask you for confirmation. Once you give it, the box will be gone.</p>
@ -328,7 +332,7 @@ of #dbrefs, if they are not in the same location) to the command.</p>
<p>The Command-help is something you modify in Python code. Well get to that when we get to how to
add Commands. But you can also add regular help entries, for example to explain something about
the history of your game world:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sethelp</span><span class="o">/</span><span class="n">add</span> <span class="n">History</span> <span class="o">=</span> <span class="n">At</span> <span class="n">the</span> <span class="n">dawn</span> <span class="n">of</span> <span class="n">time</span> <span class="o">...</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>sethelp/add History = At the dawn of time ...
</pre></div>
</div>
<p>You will now find your new <code class="docutils literal notranslate"><span class="pre">History</span></code> entry in the <code class="docutils literal notranslate"><span class="pre">help</span></code> list and read your help-text with <code class="docutils literal notranslate"><span class="pre">help</span> <span class="pre">History</span></code>.</p>
@ -403,7 +407,7 @@ example. Evennia comes with a tutorial world for you to explore. We will try tha
<h3>Versions</h3>
<ul>
<li><a href="Building-Quickstart.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,31 +49,31 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="creating-things">
<section class="tex2jax_ignore mathjax_ignore" id="creating-things">
<h1>Creating things<a class="headerlink" href="#creating-things" title="Permalink to this headline"></a></h1>
<p>We have already created some things - dragons for example. There are many different things to create
in Evennia though. In the last lesson we learned about typeclasses, the way to make objects persistent in the database.</p>
<p>Given the path to a Typeclass, there are three ways to create an instance of it:</p>
<ul>
<li><p>Firstly, you can call the class directly, and then <code class="docutils literal notranslate"><span class="pre">.save()</span></code> it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span> <span class="o">=</span> <span class="n">SomeTypeClass</span><span class="p">(</span><span class="n">db_key</span><span class="o">=...</span><span class="p">)</span>
<span class="n">obj</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> obj = SomeTypeClass(db_key=...)
obj.save()
</pre></div>
</div>
<p>This has the drawback of being two operations; you must also import the class and have to pass
the actual database field names, such as <code class="docutils literal notranslate"><span class="pre">db_key</span></code> instead of <code class="docutils literal notranslate"><span class="pre">key</span></code> as keyword arguments.</p>
</li>
<li><p>Secondly you can use the Evennia creation helpers:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="n">SomeTypeClass</span><span class="p">,</span> <span class="n">key</span><span class="o">=...</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> obj = evennia.create_object(SomeTypeClass, key=...)
</pre></div>
</div>
<p>This is the recommended way if you are trying to create things in Python. The first argument can either be
the class <em>or</em> the python-path to the typeclass, like <code class="docutils literal notranslate"><span class="pre">&quot;path.to.SomeTypeClass&quot;</span></code>. It can also be <code class="docutils literal notranslate"><span class="pre">None</span></code> in which
case the Evennia default will be used. While all the creation methods
are available on <code class="docutils literal notranslate"><span class="pre">evennia</span></code>, they are actually implemented in <a class="reference external" href="../../../api/evennia.utils.create.html">evennia/utils/create.py</a>.</p>
are available on <code class="docutils literal notranslate"><span class="pre">evennia</span></code>, they are actually implemented in <a class="reference internal" href="../../../api/evennia.utils.create.html"><span class="doc std std-doc">evennia/utils/create.py</span></a>.</p>
</li>
<li><p>Finally, you can create objects using an in-game command, such as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">obj</span><span class="p">:</span><span class="n">path</span><span class="o">.</span><span class="n">to</span><span class="o">.</span><span class="n">SomeTypeClass</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> create/drop obj:path.to.SomeTypeClass
</pre></div>
</div>
<p>As a developer you are usually best off using the two other methods, but a command is usually the only way
@ -82,9 +84,9 @@ to let regular players or builders without Python-access help build the game wor
<h2>Creating Objects<a class="headerlink" href="#creating-objects" title="Permalink to this headline"></a></h2>
<p>This is one of the most common creation-types. These are entities that inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> at any distance.
They have an existence in the game world and includes rooms, characters, exits, weapons, flower pots and castles.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span>
<span class="o">&gt;</span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="o">&gt;</span> <span class="n">rose</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; import evennia
&gt; rose = evennia.create_object(key=&quot;rose&quot;)
</pre></div>
</div>
<p>Since we didnt specify the <code class="docutils literal notranslate"><span class="pre">typeclass</span></code> as the first argument, the default given by <code class="docutils literal notranslate"><span class="pre">settings.BASE_OBJECT_TYPECLASS</span></code>
@ -153,7 +155,7 @@ You can find the parent class for Accounts in <code class="docutils literal notr
<h3>Versions</h3>
<ul>
<li><a href="Creating-Things.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,15 +49,17 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="django-database-queries">
<section class="tex2jax_ignore mathjax_ignore" id="django-database-queries">
<h1>Django Database queries<a class="headerlink" href="#django-database-queries" title="Permalink to this headline"></a></h1>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>More advanced lesson!</p>
<p>Learning about Djangos queryset language is very useful once you start doing more advanced things
in Evennia. But its not strictly needed out the box and can be a little overwhelming for a first
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Learning about Django&#39;s queryset language is very useful once you start doing more advanced things
in Evennia. But it&#39;s not strictly needed out the box and can be a little overwhelming for a first
reading. So if you are new to Python and Evennia, feel free to just skim this lesson and refer
back to it later when youve gained more experience.</p>
back to it later when you&#39;ve gained more experience.
</pre></div>
</div>
</div>
<p>The search functions and methods we used in the previous lesson are enough for most cases.
But sometimes you need to be more specific:</p>
@ -74,12 +78,12 @@ a database query. One can add querysets together to build ever-more complicated
you are trying to use the results of the queryset will it actually call the database.</p>
<p>The normal way to build a queryset is to define what class of entity you want to search by getting its
<code class="docutils literal notranslate"><span class="pre">.objects</span></code> resource, and then call various methods on that. Weve seen this one before:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_weapons</span> <span class="o">=</span> <span class="n">Weapon</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_weapons = Weapon.objects.all()
</pre></div>
</div>
<p>This is now a queryset representing all instances of <code class="docutils literal notranslate"><span class="pre">Weapon</span></code>. If <code class="docutils literal notranslate"><span class="pre">Weapon</span></code> had a subclass <code class="docutils literal notranslate"><span class="pre">Cannon</span></code> and we
only wanted the cannons, we would do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_cannons</span> <span class="o">=</span> <span class="n">Cannon</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_cannons = Cannon.objects.all()
</pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">Weapon</span></code> and <code class="docutils literal notranslate"><span class="pre">Cannon</span></code> are different typeclasses. You wont find any <code class="docutils literal notranslate"><span class="pre">Cannon</span></code> instances in
@ -87,35 +91,37 @@ the <code class="docutils literal notranslate"><span class="pre">all_weapon</spa
instances of all its children classes you need to use <code class="docutils literal notranslate"><span class="pre">_family</span></code>:</p>
<aside class="sidebar">
<p class="sidebar-title">_family</p>
<p>The all_family, filter_family etc is an Evennia-specific
thing. Its not part of regular Django.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The all_family, filter_family etc is an Evennia-specific
thing. It&#39;s not part of regular Django.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">really_all_weapons</span> <span class="o">=</span> <span class="n">Weapon</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all_family</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>really_all_weapons = Weapon.objects.all_family()
</pre></div>
</div>
<p>This result now contains both <code class="docutils literal notranslate"><span class="pre">Weapon</span></code> and <code class="docutils literal notranslate"><span class="pre">Cannon</span></code> instances.</p>
<p>To limit your search by other criteria than the Typeclass you need to use <code class="docutils literal notranslate"><span class="pre">.filter</span></code>
(or <code class="docutils literal notranslate"><span class="pre">.filter_family</span></code>) instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">roses</span> <span class="o">=</span> <span class="n">Flower</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>roses = Flower.objects.filter(db_key=&quot;rose&quot;)
</pre></div>
</div>
<p>This is a queryset representing all objects having a <code class="docutils literal notranslate"><span class="pre">db_key</span></code> equal to <code class="docutils literal notranslate"><span class="pre">&quot;rose&quot;</span></code>.
Since this is a queryset you can keep adding to it; this will act as an <code class="docutils literal notranslate"><span class="pre">AND</span></code> condition.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">local_roses</span> <span class="o">=</span> <span class="n">roses</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_location</span><span class="o">=</span><span class="n">myroom</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>local_roses = roses.filter(db_location=myroom)
</pre></div>
</div>
<p>We could also have written this in one statement:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">local_roses</span> <span class="o">=</span> <span class="n">Flower</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">,</span> <span class="n">db_location</span><span class="o">=</span><span class="n">myroom</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>local_roses = Flower.objects.filter(db_key=&quot;rose&quot;, db_location=myroom)
</pre></div>
</div>
<p>We can also <code class="docutils literal notranslate"><span class="pre">.exclude</span></code> something from results</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">local_non_red_roses</span> <span class="o">=</span> <span class="n">local_roses</span><span class="o">.</span><span class="n">exclude</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;red_rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>local_non_red_roses = local_roses.exclude(db_key=&quot;red_rose&quot;)
</pre></div>
</div>
<p>Only until we actually try to examine the result will the database be called. Here its called when we
try to loop over the queryset:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">rose</span> <span class="ow">in</span> <span class="n">local_non_red_roses</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">rose</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>for rose in local_non_red_roses:
print(rose)
</pre></div>
</div>
<p>From now on, the queryset is <em>evaluated</em> and we cant keep adding more queries to it - wed need to
@ -143,35 +149,35 @@ return querysets, which means you could in principle keep adding queries to thei
<h2>Queryset field lookups<a class="headerlink" href="#queryset-field-lookups" title="Permalink to this headline"></a></h2>
<p>Above we found roses with exactly the <code class="docutils literal notranslate"><span class="pre">db_key</span></code> <code class="docutils literal notranslate"><span class="pre">&quot;rose&quot;</span></code>. This is an <em>exact</em> match that is <em>case sensitive</em>,
so it would not find <code class="docutils literal notranslate"><span class="pre">&quot;Rose&quot;</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># this is case-sensitive and the same as =</span>
<span class="n">roses</span> <span class="o">=</span> <span class="n">Flower</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key__exact</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># this is case-sensitive and the same as =
roses = Flower.objects.filter(db_key__exact=&quot;rose&quot;
<span class="c1"># the i means it&#39;s case-insensitive</span>
<span class="n">roses</span> <span class="o">=</span> <span class="n">Flower</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key__iexact</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
# the i means it&#39;s case-insensitive
roses = Flower.objects.filter(db_key__iexact=&quot;rose&quot;)
</pre></div>
</div>
<p>The Django field query language uses <code class="docutils literal notranslate"><span class="pre">__</span></code> in the same way as Python uses <code class="docutils literal notranslate"><span class="pre">.</span></code> to access resources. This
is because <code class="docutils literal notranslate"><span class="pre">.</span></code> is not allowed in a function keyword.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">roses</span> <span class="o">=</span> <span class="n">Flower</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key__icontains</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>roses = Flower.objects.filter(db_key__icontains=&quot;rose&quot;)
</pre></div>
</div>
<p>This will find all flowers whose name contains the string <code class="docutils literal notranslate"><span class="pre">&quot;rose&quot;</span></code>, like <code class="docutils literal notranslate"><span class="pre">&quot;roses&quot;</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;wild</span> <span class="pre">rose&quot;</span></code> etc. The
<code class="docutils literal notranslate"><span class="pre">i</span></code> in the beginning makes the search case-insensitive. Other useful variations to use
are <code class="docutils literal notranslate"><span class="pre">__istartswith</span></code> and <code class="docutils literal notranslate"><span class="pre">__iendswith</span></code>. You can also use <code class="docutils literal notranslate"><span class="pre">__gt</span></code>, <code class="docutils literal notranslate"><span class="pre">__ge</span></code> for “greater-than”/greater-or-equal-than”
are <code class="docutils literal notranslate"><span class="pre">__istartswith</span></code> and <code class="docutils literal notranslate"><span class="pre">__iendswith</span></code>. You can also use <code class="docutils literal notranslate"><span class="pre">__gt</span></code>, <code class="docutils literal notranslate"><span class="pre">__ge</span></code> for “greater-than”/greater-or-equal-than”
comparisons (same for <code class="docutils literal notranslate"><span class="pre">__lt</span></code> and <code class="docutils literal notranslate"><span class="pre">__le</span></code>). There is also <code class="docutils literal notranslate"><span class="pre">__in</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">swords</span> <span class="o">=</span> <span class="n">Weapons</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key__in</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;rapier&quot;</span><span class="p">,</span> <span class="s2">&quot;two-hander&quot;</span><span class="p">,</span> <span class="s2">&quot;shortsword&quot;</span><span class="p">))</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>swords = Weapons.objects.filter(db_key__in=(&quot;rapier&quot;, &quot;two-hander&quot;, &quot;shortsword&quot;))
</pre></div>
</div>
<p>One also uses <code class="docutils literal notranslate"><span class="pre">__</span></code> to access foreign objects like Tags. Lets for example assume this is how we identify mages:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">char</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;mage&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;profession&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>char.tags.add(&quot;mage&quot;, category=&quot;profession&quot;)
</pre></div>
</div>
<p>Now, in this case we have an Evennia helper to do this search:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mages</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tags</span><span class="p">(</span><span class="s2">&quot;mage&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;profession&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>mages = evennia.search_tags(&quot;mage&quot;, category=&quot;profession&quot;)
</pre></div>
</div>
<p>But this will find all Objects with this tag+category. Maybe you are only looking for Vampire mages:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sparkly_mages</span> <span class="o">=</span> <span class="n">Vampire</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_tags__db_key</span><span class="o">=</span><span class="s2">&quot;mage&quot;</span><span class="p">,</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">&quot;profession&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>sparkly_mages = Vampire.objects.filter(db_tags__db_key=&quot;mage&quot;, db_tags__db_category=&quot;profession&quot;)
</pre></div>
</div>
<p>This looks at the <code class="docutils literal notranslate"><span class="pre">db_tags</span></code> field on the <code class="docutils literal notranslate"><span class="pre">Vampire</span></code> and filters on the values of each tags
@ -184,27 +190,21 @@ comparisons (same for <code class="docutils literal notranslate"><span class="pr
<p>Lets see if we can make a query for the werewolves in the moonlight we mentioned at the beginning
of this section.</p>
<p>Firstly, we make ourselves and our current location match the criteria, so we can test:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">here</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;moonlit&quot;</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="n">me</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">lycantrophy</span> <span class="o">=</span> <span class="mi">3</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py here.tags.add(&quot;moonlit&quot;)
&gt; py me.db.lycantrophy = 3
</pre></div>
</div>
<p>This is an example of a more complex query. Well consider it an example of what is
possible.</p>
<aside class="sidebar">
<p class="sidebar-title">Line breaks</p>
<p>Note the way of writing this code. It would have been very hard to read if we just wrote it in
one long line. But since we wrapped it in <cite>(…)</cite> we can spread it out over multiple lines
without worrying about line breaks!</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Note the way of writing this code. It would have been very hard to read if we just wrote it in
one long line. But since we wrapped it in `(...)` we can spread it out over multiple lines
without worrying about line breaks!
</pre></div>
</div>
</aside>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typeclasses.characters</span> <span class="kn">import</span> <span class="n">Character</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typeclasses.characters</span> <span class="kn">import</span> <span class="n">Character</span>
<span class="n">will_transform</span> <span class="o">=</span> <span class="p">(</span>
<span class="n">Character</span><span class="o">.</span><span class="n">objects</span>
@ -214,7 +214,7 @@ without worrying about line breaks!</p>
<span class="n">db_attributes__db_value__gt</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><strong>Line 3</strong> - We want to find <code class="docutils literal notranslate"><span class="pre">Character</span></code>s, so we access <code class="docutils literal notranslate"><span class="pre">.objects</span></code> on the <code class="docutils literal notranslate"><span class="pre">Character</span></code> typeclass.</p></li>
<li><p><strong>Line 4</strong> - We start to filter …</p></li>
@ -231,7 +231,7 @@ that we can treat like an object for this purpose; it references all Tags on the
</ul>
<p>Running this query makes our newly lycantrrophic Character appear in <code class="docutils literal notranslate"><span class="pre">will_transform</span></code>. Success!</p>
<blockquote>
<div><p>Dont confuse database fields with <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attributes</span></a> you set via <code class="docutils literal notranslate"><span class="pre">obj.db.attr</span> <span class="pre">=</span> <span class="pre">'foo'</span></code> or
<div><p>Dont confuse database fields with <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attributes</span></a> you set via <code class="docutils literal notranslate"><span class="pre">obj.db.attr</span> <span class="pre">=</span> <span class="pre">'foo'</span></code> or
<code class="docutils literal notranslate"><span class="pre">obj.attributes.add()</span></code>. Attributes are custom database entities <em>linked</em> to an object. They are not
separate fields <em>on</em> that object like <code class="docutils literal notranslate"><span class="pre">db_key</span></code> or <code class="docutils literal notranslate"><span class="pre">db_location</span></code> are.</p>
</div></blockquote>
@ -239,28 +239,28 @@ separate fields <em>on</em> that object like <code class="docutils literal notra
<section id="complex-queries">
<h2>Complex queries<a class="headerlink" href="#complex-queries" title="Permalink to this headline"></a></h2>
<p>All examples so far used <code class="docutils literal notranslate"><span class="pre">AND</span></code> relations. The arguments to <code class="docutils literal notranslate"><span class="pre">.filter</span></code> are added together with <code class="docutils literal notranslate"><span class="pre">AND</span></code>
(we want tag room to be “monlit” <em>and</em> lycantrhopy be &gt; 2”).</p>
(we want tag room to be “monlit” <em>and</em> lycantrhopy be &gt; 2”).</p>
<p>For queries using <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">NOT</span></code> we need Djangos
<a class="reference external" href="https://docs.djangoproject.com/en/1.11/topics/db/queries/#complex-lookups-with-q-objects">Q object</a>. It is
imported from Django directly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Q</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from django.db.models import Q
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">Q</span></code> is an object that is created with the same arguments as <code class="docutils literal notranslate"><span class="pre">.filter</span></code>, for example</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Q</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;foo&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Q(db_key=&quot;foo&quot;)
</pre></div>
</div>
<p>You can then use this <code class="docutils literal notranslate"><span class="pre">Q</span></code> instance as argument in a <code class="docutils literal notranslate"><span class="pre">filter</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">q1</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;foo&quot;</span><span class="p">)</span>
<span class="n">Character</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">q1</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>q1 = Q(db_key=&quot;foo&quot;)
Character.objects.filter(q1)
</pre></div>
</div>
<p>The useful thing about <code class="docutils literal notranslate"><span class="pre">Q</span></code> is that these objects can be chained together with special symbols (bit operators):
<code class="docutils literal notranslate"><span class="pre">|</span></code> for <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">&amp;</span></code> for <code class="docutils literal notranslate"><span class="pre">AND</span></code>. A tilde <code class="docutils literal notranslate"><span class="pre">~</span></code> in front negates the expression inside the <code class="docutils literal notranslate"><span class="pre">Q</span></code> and thus
works like <code class="docutils literal notranslate"><span class="pre">NOT</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">q1</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Dalton&quot;</span><span class="p">)</span>
<span class="n">q2</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">db_location</span><span class="o">=</span><span class="n">prison</span><span class="p">)</span>
<span class="n">Character</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">q1</span> <span class="o">|</span> <span class="o">~</span><span class="n">q2</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>q1 = Q(db_key=&quot;Dalton&quot;)
q2 = Q(db_location=prison)
Character.objects.filter(q1 | ~q2)
</pre></div>
</div>
<p>Would get all Characters that are either named “Dalton” <em>or</em> which is <em>not</em> in prison. The result is a mix
@ -270,19 +270,7 @@ with a certain level of <code class="docutils literal notranslate"><span class="
recently bitten, even if their <code class="docutils literal notranslate"><span class="pre">lycantrophy</span></code> level is not yet high enough (more dramatic this way!). Lets say there is
a Tag “recently_bitten” that controls this.</p>
<p>This is how wed change our query:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Q</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Q</span>
<span class="n">will_transform</span> <span class="o">=</span> <span class="p">(</span>
<span class="n">Character</span><span class="o">.</span><span class="n">objects</span>
@ -296,19 +284,9 @@ a Tag “recently_bitten” that controls this.</p>
<span class="o">.</span><span class="n">distinct</span><span class="p">()</span>
<span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Thats quite compact. It may be easier to see whats going on if written this way:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Q</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Q</span>
<span class="n">q_moonlit</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">db_location__db_tags__db_key__iexact</span><span class="o">=</span><span class="s2">&quot;moonlit&quot;</span><span class="p">)</span>
<span class="n">q_lycantropic</span> <span class="o">=</span> <span class="n">Q</span><span class="p">(</span><span class="n">db_attributes__db_key</span><span class="o">=</span><span class="s2">&quot;lycantrophy&quot;</span><span class="p">,</span> <span class="n">db_attributes__db_value__gt</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
@ -320,12 +298,14 @@ a Tag “recently_bitten” that controls this.</p>
<span class="o">.</span><span class="n">distinct</span><span class="p">()</span>
<span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">SQL</p>
<p>These Python structures are internally converted to SQL, the native language of the database.
If you are familiar with SQL, these are many-to-many tables joined with <cite>LEFT OUTER JOIN</cite>,
which may lead to multiple merged rows combining the same object with different relations.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>These Python structures are internally converted to SQL, the native language of the database.
If you are familiar with SQL, these are many-to-many tables joined with `LEFT OUTER JOIN`,
which may lead to multiple merged rows combining the same object with different relations.
</pre></div>
</div>
</aside>
<p>This reads as “Find all Characters in a moonlit room that either has the Attribute <code class="docutils literal notranslate"><span class="pre">lycantrophy</span></code> higher
than two <em>or</em> which has the Tag <code class="docutils literal notranslate"><span class="pre">recently_bitten</span></code>”. With an OR-query like this its possible to find the
@ -337,37 +317,22 @@ one instance of each Character in the result.</p>
<p>What if we wanted to filter on some condition that isnt represented easily by a field on the
object? Maybe we want to find rooms only containing five or more objects?</p>
<p>We <em>could</em> do it like this (dont actually do it this way!):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<span class="n">all_rooms</span> <span class="o">=</span> <span class="n">Rooms</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="n">all_rooms</span> <span class="o">=</span> <span class="n">Rooms</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="n">rooms_with_five_objects</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">room</span> <span class="ow">in</span> <span class="n">all_rooms</span><span class="p">:</span>
<span class="k">for</span> <span class="n">room</span> <span class="ow">in</span> <span class="n">all_rooms</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">room</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">5</span><span class="p">:</span>
<span class="n">rooms_with_five_objects</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">room</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Above we get all rooms and then use <code class="docutils literal notranslate"><span class="pre">list.append()</span></code> to keep adding the right rooms
to an ever-growing list. This is <em>not</em> a good idea, once your database grows this will
be unnecessarily computing-intensive. The database is much more suitable for this.</p>
<p><em>Annotations</em> allow you to set a variable inside the query that you can
then access from other parts of the query. Lets do the same example as before directly in the database:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Count</span>
<span class="n">rooms</span> <span class="o">=</span> <span class="p">(</span>
@ -377,7 +342,7 @@ then access from other parts of the query. Lets do the same example as before
<span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">num_objects__gte</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
<span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">Count</span></code> is a Django class for counting the number of things in the database.</p>
<p>Here we first create an annotation <code class="docutils literal notranslate"><span class="pre">num_objects</span></code> of type <code class="docutils literal notranslate"><span class="pre">Count</span></code>. It creates an in-database function
that will count the number of results inside the database.</p>
@ -396,27 +361,18 @@ instead of having 5 or more objects, we only wanted objects that had a bigger in
tags (silly example, but …)? This can be with Djangos
<a class="reference external" href="https://docs.djangoproject.com/en/1.11/ref/models/expressions/#f-expressions">F objects</a>.
So-called F expressions allow you to do a query that looks at a value of each object in the database.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Count</span><span class="p">,</span> <span class="n">F</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Count</span><span class="p">,</span> <span class="n">F</span>
<span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">(</span>
<span class="n">Room</span><span class="o">.</span><span class="n">objects</span>
<span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
<span class="n">num_objects</span><span class="o">=</span><span class="n">Count</span><span class="p">(</span><span class="s1">&#39;locations_set&#39;</span><span class="p">),</span>
<span class="n">num_objects</span><span class="o">=</span><span class="n">Count</span><span class="p">(</span><span class="s1">&#39;locations_set&#39;</span><span class="p">),</span>
<span class="n">num_tags</span><span class="o">=</span><span class="n">Count</span><span class="p">(</span><span class="s1">&#39;db_tags&#39;</span><span class="p">))</span>
<span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">num_objects__gt</span><span class="o">=</span><span class="n">F</span><span class="p">(</span><span class="s1">&#39;num_tags&#39;</span><span class="p">))</span>
<span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here we used <code class="docutils literal notranslate"><span class="pre">.annotate</span></code> to create two in-query variables <code class="docutils literal notranslate"><span class="pre">num_objects</span></code> and <code class="docutils literal notranslate"><span class="pre">num_tags</span></code>. We then
directly use these results in the filter. Using <code class="docutils literal notranslate"><span class="pre">F()</span></code> allows for also the right-hand-side of the filter
condition to be calculated on the fly, completely within the database.</p>
@ -429,15 +385,7 @@ need to get the membership count of every organization all at once.</p>
you run a <code class="docutils literal notranslate"><span class="pre">.filter</span></code>, what you get back is a bunch of full typeclass instances, like roses or swords.
Using <code class="docutils literal notranslate"><span class="pre">.values_list</span></code> you can instead choose to only get back certain properties on objects.
The <code class="docutils literal notranslate"><span class="pre">.order_by</span></code> method finally allows for sorting the results according to some criterion:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Count</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">Count</span>
<span class="kn">from</span> <span class="nn">typeclasses.rooms</span> <span class="kn">import</span> <span class="n">Room</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">(</span>
@ -447,7 +395,7 @@ The <code class="docutils literal notranslate"><span class="pre">.order_by</span
<span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;-tagcount&#39;</span><span class="p">))</span>
<span class="o">.</span><span class="n">values_list</span><span class="p">(</span><span class="s1">&#39;db_tags__db_key&#39;</span><span class="p">,</span> <span class="s2">&quot;tagcount&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here we fetch all Characters who …</p>
<ul class="simple">
<li><p>… has a tag of category “organization” on them</p></li>
@ -461,8 +409,8 @@ and how many matches we found for that organization.</p></li>
<p>The result queryset will be a list of tuples ordered in descending order by the number of matches,
in a format like the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span>
<span class="p">(</span><span class="s1">&#39;Griatch&#39;</span><span class="n">s</span> <span class="n">poets</span> <span class="n">society</span><span class="s1">&#39;, 3872), </span>
<span class="p">(</span><span class="s2">&quot;Chainsol&#39;s Ainneve Testers&quot;</span><span class="p">,</span> <span class="mi">2076</span><span class="p">),</span>
<span class="p">(</span><span class="s1">&#39;Griatch&#39;</span><span class="n">s</span> <span class="n">poets</span> <span class="n">society</span><span class="s1">&#39;, 3872),</span>
<span class="p">(</span><span class="s2">&quot;Chainsol&#39;s Ainneve Testers&quot;</span><span class="p">,</span> <span class="mi">2076</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;Blaufeuer&#39;s Whitespace Fixers&quot;</span><span class="p">,</span> <span class="mi">1903</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;Volund&#39;s Bikeshed Design Crew&quot;</span><span class="p">,</span> <span class="mi">1764</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;Tehom&#39;s Glorious Misanthropes&quot;</span><span class="p">,</span> <span class="mi">1763</span><span class="p">)</span>
@ -539,7 +487,7 @@ to understand how to plan what our tutorial game will be about.</p>
<h3>Versions</h3>
<ul>
<li><a href="Django-queries.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,14 +49,16 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="overview-of-the-evennia-library">
<section class="tex2jax_ignore mathjax_ignore" id="overview-of-the-evennia-library">
<h1>Overview of the Evennia library<a class="headerlink" href="#overview-of-the-evennia-library" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">API</p>
<p>API stands for <cite>Application Programming Interface</cite>, a description for how to access
the resources of a program or library.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>API stands for `Application Programming Interface`, a description for how to access
the resources of a program or library.
</pre></div>
</div>
</aside>
<p>A good place to start exploring Evennia is the <a class="reference internal" href="../../../Evennia-API.html"><span class="doc">Evenia-API frontpage</span></a>.
<p>A good place to start exploring Evennia is the <a class="reference internal" href="../../../Evennia-API.html"><span class="doc std std-doc">Evenia-API frontpage</span></a>.
This page sums up the main components of Evennia with a short description of each. Try clicking through
to a few entries - once you get deep enough youll see full descriptions
of each component along with their documentation. You can also click <code class="docutils literal notranslate"><span class="pre">[source]</span></code> to see the full Python source
@ -63,101 +67,105 @@ for each thing.</p>
what you can download from us. The github repo is also searchable.</p>
<p>Finally, you can clone the evennia repo to your own computer and read the sources locally. This is necessary
if you want to help with Evennias development itself. See the
<a class="reference internal" href="../../../Setup/Extended-Installation.html"><span class="doc">extended install instructions</span></a> if you want to do this.</p>
<a class="reference internal" href="../../../Setup/Extended-Installation.html"><span class="doc std std-doc">extended install instructions</span></a> if you want to do this.</p>
<section id="where-is-it">
<h2>Where is it?<a class="headerlink" href="#where-is-it" title="Permalink to this headline"></a></h2>
<p>If Evennia is installed, you can import from it simply with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">some_module</span>
<span class="kn">from</span> <span class="nn">evennia.some_module.other_module</span> <span class="kn">import</span> <span class="n">SomeClass</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>import evennia
from evennia import some_module
from evennia.some_module.other_module import SomeClass
</pre></div>
</div>
<p>and so on.</p>
<p>If you installed Evennia with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span></code>, the library folder will be installed deep inside your Python
installation. If you cloned the repo there will be a folder <code class="docutils literal notranslate"><span class="pre">evennia</span></code> on your hard drive there.</p>
<p>If you cloned the repo or read the code on <code class="docutils literal notranslate"><span class="pre">github</span></code> youll find this being the outermost structure:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span><span class="o">/</span>
<span class="nb">bin</span><span class="o">/</span>
<span class="n">CHANGELOG</span><span class="o">.</span><span class="n">md</span>
<span class="o">...</span>
<span class="o">...</span>
<span class="n">docs</span><span class="o">/</span>
<span class="n">evennia</span><span class="o">/</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia/
bin/
CHANGELOG.md
...
...
docs/
evennia/
</pre></div>
</div>
<p>This outer layer is for Evennias installation and package distribution. That internal folder <code class="docutils literal notranslate"><span class="pre">evennia/evennia/</span></code> is
the <em>actual</em> library, the thing covered by the API auto-docs and what you get when you do <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">evennia</span></code>.</p>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">evennia/docs/</span></code> folder contains the sources for this documentation. See
<a class="reference internal" href="../../../Contributing-Docs.html"><span class="doc">contributing to the docs</span></a> if you want to learn more about how this works.</p>
<a class="reference internal" href="../../../Contributing-Docs.html"><span class="doc std std-doc">contributing to the docs</span></a> if you want to learn more about how this works.</p>
</div></blockquote>
<p>This the the structure of the Evennia library:</p>
<ul class="simple">
<li><p>evennia</p>
<ul>
<li><p><a class="reference external" href="../../../Evennia-API#shortcuts"><code class="docutils literal notranslate"><span class="pre">__init__.py</span></code></a> - The “flat API” of Evennia resides here.</p></li>
<li><p><a class="reference external" href="../../../Components/Server-Conf#Settings-file"><code class="docutils literal notranslate"><span class="pre">settings_default.py</span></code></a> - Root settings of Evennia. Copy settings
<li><p><a class="reference internal" href="../../../Evennia-API.html#shortcuts"><span class="std std-doc"><code class="docutils literal notranslate"><span class="pre">__init__.py</span></code></span></a> - The “flat API” of Evennia resides here.</p></li>
<li><p><a class="reference internal" href="../../../Setup/Server-Conf.html#settings-file"><span class="std std-doc"><code class="docutils literal notranslate"><span class="pre">settings_default.py</span></code></span></a> - Root settings of Evennia. Copy settings
from here to <code class="docutils literal notranslate"><span class="pre">mygame/server/settings.py</span></code> file.</p></li>
<li><p><a class="reference internal" href="../../../Components/Commands.html"><span class="doc">commands/</span></a> - The command parser and handler.</p>
<li><p><a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">commands/</span></code></span></a> - The command parser and handler.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">default/</span></code> - The <a class="reference external" href="../../../api/evennia.commands.default.html#modules">default commands</a> and cmdsets.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">default/</span></code> - The <a class="reference internal" href="../../../Components/Default-Commands.html"><span class="doc std std-doc">default commands</span></a> and cmdsets.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="../../../Components/Communications.html"><span class="doc">comms/</span></a> - Systems for communicating in-game.</p></li>
<li><p><a class="reference internal" href="../../../Components/Communications.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">comms/</span></code></span></a> - Systems for communicating in-game.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">contrib/</span></code> - Optional plugins too game-specific for core Evennia.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">game_template/</span></code> - Copied to become the “game directory” when using <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--init</span></code>.</p></li>
<li><p><a class="reference internal" href="../../../Components/Help-System.html"><span class="doc">help/</span></a> - Handles the storage and creation of help entries.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locale/</span></code> - Language files (<a class="reference internal" href="../../../Concepts/Internationalization.html"><span class="doc">i18n</span></a>).</p></li>
<li><p><a class="reference internal" href="../../../Components/Locks.html"><span class="doc">locks/</span></a> - Lock system for restricting access to in-game entities.</p></li>
<li><p><a class="reference internal" href="../../../Components/Objects.html"><span class="doc">objects/</span></a> - In-game entities (all types of items and Characters).</p></li>
<li><p><a class="reference internal" href="../../../Components/Prototypes.html"><span class="doc">prototypes/</span></a> - Object Prototype/spawning system and OLC menu</p></li>
<li><p><a class="reference internal" href="../../../Components/Accounts.html"><span class="doc">accounts/</span></a> - Out-of-game Session-controlled entities (accounts, bots etc)</p></li>
<li><p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">scripts/</span></a> - Out-of-game entities equivalence to Objects, also with timer support.</p></li>
<li><p><a class="reference internal" href="../../../Components/Portal-And-Server.html"><span class="doc">server/</span></a> - Core server code and Session handling.</p>
<li><p><a class="reference internal" href="../../../Components/Help-System.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">help/</span></code></span></a> - Handles the storage and creation of help entries.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">locale/</span></code> - Language files (<a class="reference internal" href="../../../Concepts/Internationalization.html"><span class="doc std std-doc">i18n</span></a>).</p></li>
<li><p><a class="reference internal" href="../../../Components/Locks.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">locks/</span></code></span></a> - Lock system for restricting access to in-game entities.</p></li>
<li><p><a class="reference internal" href="../../../Components/Objects.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">objects/</span></code></span></a> - In-game entities (all types of items and Characters).</p></li>
<li><p><a class="reference internal" href="../../../Components/Prototypes.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">prototypes/</span></code></span></a> - Object Prototype/spawning system and OLC menu</p></li>
<li><p><a class="reference internal" href="../../../Components/Accounts.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">accounts/</span></code></span></a> - Out-of-game Session-controlled entities (accounts, bots etc)</p></li>
<li><p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">scripts/</span></code></span></a> - Out-of-game entities equivalence to Objects, also with timer support.</p></li>
<li><p><a class="reference internal" href="../../../Components/Portal-And-Server.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">server/</span></code></span></a> - Core server code and Session handling.</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">portal/</span></code> - Portal proxy and connection protocols.</p></li>
</ul>
</li>
<li><p><a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc">typeclasses/</span></a> - Abstract classes for the typeclass storage and database system.</p></li>
<li><p><a class="reference internal" href="../../../Components/Coding-Utils.html"><span class="doc">utils/</span></a> - Various miscellaneous useful coding resources.</p></li>
<li><p><a class="reference internal" href="../../../Concepts/Web-Features.html"><span class="doc">web/</span></a> - Web resources and webserver. Partly copied into game directory on initialization.</p></li>
<li><p><a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">typeclasses/</span></code></span></a> - Abstract classes for the typeclass storage and database system.</p></li>
<li><p><a class="reference internal" href="../../../Components/Coding-Utils.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">utils/</span></code></span></a> - Various miscellaneous useful coding resources.</p></li>
<li><p><a class="reference internal" href="../../../Concepts/Web-Features.html"><span class="doc std std-doc"><code class="docutils literal notranslate"><span class="pre">web/</span></code></span></a> - Web resources and webserver. Partly copied into game directory on initialization.</p></li>
</ul>
</li>
</ul>
<aside class="sidebar">
<p class="sidebar-title">__init__.py</p>
<p>The <cite>__init__.py</cite> file is a special Python filename used to represent a Python package.
When you import <cite>evennia</cite> on its own, you import this file. When you do <cite>evennia.foo</cite> Python will
first look for a property <cite>.foo</cite> in <cite>__init__.py</cite> and then for a module or folder of that name
in the same location.</p>
<p class="sidebar-title"><strong>init</strong>.py</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The `__init__.py` file is a special Python filename used to represent a Python &#39;package&#39;.
When you import `evennia` on its own, you import this file. When you do `evennia.foo` Python will
first look for a property `.foo` in `__init__.py` and then for a module or folder of that name
in the same location.
</pre></div>
</div>
</aside>
<p>While all the actual Evennia code is found in the various folders, the <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> represents the entire
package <code class="docutils literal notranslate"><span class="pre">evennia</span></code>. It contains “shortcuts” to code that is actually located elsewhere. Most of these shortcuts
are listed if you <a class="reference internal" href="../../../Evennia-API.html"><span class="doc">scroll down a bit</span></a> on the Evennia-API page.</p>
are listed if you <a class="reference internal" href="../../../Evennia-API.html"><span class="doc std std-doc">scroll down a bit</span></a> on the Evennia-API page.</p>
</section>
<section id="an-example-of-exploring-the-library">
<h2>An example of exploring the library<a class="headerlink" href="#an-example-of-exploring-the-library" title="Permalink to this headline"></a></h2>
<p>In the previous lesson we took a brief look at <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects</span></code> as an example of a Python module. Lets
open it again. Inside is the <code class="docutils literal notranslate"><span class="pre">Object</span></code> class, which inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>.
Near the top of the module is this line:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from evennia import DefaultObject
</pre></div>
</div>
<p>We want to figure out just what this DefaultObject offers. Since this is imported directly from <code class="docutils literal notranslate"><span class="pre">evennia</span></code>, we
are actually importing from <code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code>.</p>
<p><a class="reference external" href="Howto/Starting/Part1/evennia/__init__.py#L189">Look at Line 189</a> of <code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code> and youll find this line:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">.objects.objects</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
<p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/__init__.py#159">Look at Line 159</a> of <code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code> and youll find this line:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from .objects.objects import DefaultObject
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Relative and absolute imports</p>
<p>The first full-stop in <cite>from .objects.objects …</cite> means that
we are importing from the current location. This is called a <cite>relative import</cite>.
By comparison, <cite>from evennia.objects.objects</cite> is an <cite>absolute import</cite>. In this particular
case, the two would give the same result.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The first full-stop in `from .objects.objects ...` means that
we are importing from the current location. This is called a `relative import`.
By comparison, `from evennia.objects.objects` is an `absolute import`. In this particular
case, the two would give the same result.
</pre></div>
</div>
</aside>
<blockquote>
<div><p>You can also look at <a class="reference external" href="Evennia-API.html#typeclasses">the right section of the API frontpage</a> and click through
<div><p>You can also look at <a class="reference internal" href="../../../Evennia-API.html#typeclasses"><span class="std std-doc">the right section of the API frontpage</span></a> and click through
to the code that way.</p>
</div></blockquote>
<p>The fact that <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is imported into <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> here is what makes it possible to also import
@ -165,12 +173,11 @@ it as <code class="docutils literal notranslate"><span class="pre">from</span> <
<p>So to find the code for <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> we need to look in <code class="docutils literal notranslate"><span class="pre">evennia/objects/objects.py</span></code>. Heres how
to look it up in the docs:</p>
<ol class="simple">
<li><p>Open the <a class="reference internal" href="../../../Evennia-API.html"><span class="doc">API frontpage</span></a></p></li>
<li><p>Locate the link to <a class="reference external" href="../../../api/evennia.objects.html">evennia.objects</a> and click on it.</p></li>
<li><p>Click through to <a class="reference external" href="../../../api/evennia.objects.objects.html">evennia.objects.objects</a>.</p></li>
<li><p>You are now in the python module. Scroll down (or search in your web browser) to find the <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> class.</p></li>
<li><p>You can now read what this does and what methods are on it. If you want to see the full source, click the
[<a class="reference external" href="../../../_modules/evennia/objects/objects.html#DefaultObject">source</a>] link.</p></li>
<li><p>Open the <a class="reference internal" href="../../../Evennia-API.html"><span class="doc std std-doc">API frontpage</span></a></p></li>
<li><p>Locate the link to <a class="reference internal" href="../../../api/evennia.objects.objects.html#evennia-objects-objects"><span class="std std-ref">evennia.objects.objects</span></a> and click on it.
3 You are now in the python module. Scroll down (or search in your web browser) to find the <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> class.
4 You can now read what this does and what methods are on it. If you want to see the full source, click the
[source] link next to it.</p></li>
</ol>
</section>
</section>
@ -230,7 +237,7 @@ to look it up in the docs:</p>
<h3>Versions</h3>
<ul>
<li><a href="Evennia-Library-Overview.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,7 +49,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="overview-of-your-new-game-dir">
<section class="tex2jax_ignore mathjax_ignore" id="overview-of-your-new-game-dir">
<h1>Overview of your new Game Dir<a class="headerlink" href="#overview-of-your-new-game-dir" title="Permalink to this headline"></a></h1>
<p>Next we will take a little detour to look at the <em>Tutorial World</em>. This is a little solo adventure
that comes with Evennia, a showcase for some of the things that are possible.</p>
@ -64,15 +66,18 @@ Python package management).</p>
“python paths”, such as</p>
<aside class="sidebar">
<p class="sidebar-title">Python-paths</p>
<p>A python path uses . instead of / or <cite>\</cite> and
skips the <cite>.py</cite> ending of files. It can also point to
the code contents of python files. Since Evennia is already
looking for code in your game dir, your python paths can start
from there.</p>
<p>So a path <cite>/home/foo/devel/mygame/commands/command.py</cite>
would translate to a Python-path <cite>commands.command</cite>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>A &#39;python path&#39; uses &#39;.&#39; instead of &#39;/&#39; or &#39;`\\`&#39; and
skips the `.py` ending of files. It can also point to
the code contents of python files. Since Evennia is already
looking for code in your game dir, your python paths can start
from there.
So a path `/home/foo/devel/mygame/commands/command.py`
would translate to a Python-path `commands.command`.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">button</span><span class="p">:</span><span class="n">tutorial_examples</span><span class="o">.</span><span class="n">red_button</span><span class="o">.</span><span class="n">RedButton</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>create/drop button:tutorial_examples.red_button.RedButton
</pre></div>
</div>
<p>This is a fundamental aspect of coding Evennia - <em>you create code and then you tell Evennia where that
@ -110,13 +115,15 @@ to update Evennias default settings to point to the right places in the new s
</div></blockquote>
<section id="commands">
<h2>commands/<a class="headerlink" href="#commands" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">commands/</span></code> folder holds Python modules related to creating and extending the <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Commands</span></a>
<p>The <code class="docutils literal notranslate"><span class="pre">commands/</span></code> folder holds Python modules related to creating and extending the <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Commands</span></a>
of Evennia. These manifest in game like the server understanding input like <code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">dig</span></code>.</p>
<aside class="sidebar">
<p class="sidebar-title">Classes</p>
<p>A <cite>class</cite> is template for creating object-instances of a particular type
in Python. We will explain classes in more detail in the next
<a class="reference external" href="Python-basic-tutorial-part-two">python overview</a>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>A `class` is template for creating object-instances of a particular type
in Python. We will explain classes in more detail in the next
`python overview &lt;Python-basic-tutorial-part-two&gt;`_.
</pre></div>
</div>
</aside>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/commands/command.py">command.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">commands.command</span></code>) - this contain the
@ -155,11 +162,11 @@ knows where they are and will read them to configure itself at startup.</p>
are expected to copy&amp;paste the changes you need from <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/default_settings.py">evennia/default_settings.py</a>.
The default settings file is extensively documented. Importing/accessing the values in the settings
file is done in a special way, like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> from django.conf import settings
</pre></div>
</div>
<p>To get to the setting <code class="docutils literal notranslate"><span class="pre">TELNET_PORT</span></code> in the settings file youd then do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">telnet_port</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">TELNET_PORT</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> telnet_port = settings.TELNET_PORT
</pre></div>
</div>
<p>You cannot assign to the settings file dynamically; you must change the <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> file directly to
@ -203,28 +210,28 @@ to add them.</p></li>
</section>
<section id="typeclasses">
<h3>typeclasses/<a class="headerlink" href="#typeclasses" title="Permalink to this headline"></a></h3>
<p>The <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc">Typeclasses</span></a> of Evennia are Evennia-specific Python classes whose instances save themselves
<p>The <a class="reference internal" href="../../../Components/Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a> of Evennia are Evennia-specific Python classes whose instances save themselves
to the database. This allows a Character to remain in the same place and your updated strength stat to still
be the same after a server reboot.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/accounts.py">accounts.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.accounts</span></code>) - An
<a class="reference internal" href="../../../Components/Accounts.html"><span class="doc">Account</span></a> represents the player connecting to the game. It holds information like email,
<a class="reference internal" href="../../../Components/Accounts.html"><span class="doc std std-doc">Account</span></a> represents the player connecting to the game. It holds information like email,
password and other out-of-character details.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/channels.py">channels.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.channels</span></code>) -
<a class="reference internal" href="../../../Components/Channels.html"><span class="doc">Channels</span></a> are used to manage in-game communication between players.</p></li>
<a class="reference internal" href="../../../Components/Channels.html"><span class="doc std std-doc">Channels</span></a> are used to manage in-game communication between players.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/objects.py">objects.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.objects</span></code>) -
<a class="reference internal" href="../../../Components/Objects.html"><span class="doc">Objects</span></a> represent all things having a location within the game world.</p></li>
<a class="reference internal" href="../../../Components/Objects.html"><span class="doc std std-doc">Objects</span></a> represent all things having a location within the game world.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/characters.py">characters.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.characters</span></code>) -
The <a class="reference external" href="Components/Objects.html#Characers">Character</a> is a subclass of Objects, controlled by Accounts - they are the players
The <a class="reference internal" href="../../../Components/Objects.html#characters"><span class="std std-doc">Character</span></a> is a subclass of Objects, controlled by Accounts - they are the players
avatars in the game world.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/rooms.py">rooms.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.rooms</span></code>) - A
<a class="reference external" href="Components/Objects.html#Room">Room</a> is also a subclass of Object; describing discrete locations. While the traditional
<a class="reference internal" href="../../../Components/Objects.html#rooms"><span class="std std-doc">Room</span></a> is also a subclass of Object; describing discrete locations. While the traditional
term is room, such a location can be anything and on any scale that fits your game, from a forest glade,
an entire planet or an actual dungeon room.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/exits.py">exits.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.exits</span></code>) -
<a class="reference external" href="Components/Objects.html#Exit">Exits</a> is another subclass of Object. Exits link one Room to another.</p></li>
<a class="reference internal" href="../../../Components/Objects.html#exits"><span class="std std-doc">Exits</span></a> is another subclass of Object. Exits link one Room to another.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/typeclasses/scripts.py">scripts.py</a> (Python-path: <code class="docutils literal notranslate"><span class="pre">typeclasses.scripts</span></code>) -
<a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Scripts</span></a> are out-of-character objects. They have no location in-game and can serve as basis for
<a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a> are out-of-character objects. They have no location in-game and can serve as basis for
anything that needs database persistence, such as combat, weather, or economic systems. They also
have the ability to execute code repeatedly, on a timer.</p></li>
</ul>
@ -256,8 +263,8 @@ people change and re-structure this in various ways to better fit their ideas.</
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/world/batch_cmds.ev">batch_cmds.ev</a> - This is an <code class="docutils literal notranslate"><span class="pre">.ev</span></code> file, which is essentially
just a list of Evennia commands to execute in sequence. This one is empty and ready to expand on. The
<a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc">Tutorial World</span></a> was built with such a batch-file.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/world/prototypes.py">prototypes.py</a> - A <a class="reference internal" href="../../../Components/Prototypes.html"><span class="doc">prototype</span></a> is a way
<a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc std std-doc">Tutorial World</span></a> was built with such a batch-file.</p></li>
<li><p><a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/game_template/world/prototypes.py">prototypes.py</a> - A <a class="reference internal" href="../../../Components/Prototypes.html"><span class="doc std std-doc">prototype</span></a> is a way
to easily vary objects without changing their base typeclass. For example, one could use prototypes to
tell that Two goblins, while both of the class Goblin (so they follow the same code logic), should have different
equipment, stats and looks.</p></li>
@ -328,7 +335,7 @@ equipment, stats and looks.</p></li>
<h3>Versions</h3>
<ul>
<li><a href="Gamedir-Overview.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,40 +49,14 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="persistent-objects-and-typeclasses">
<section class="tex2jax_ignore mathjax_ignore" id="persistent-objects-and-typeclasses">
<h1>Persistent objects and typeclasses<a class="headerlink" href="#persistent-objects-and-typeclasses" title="Permalink to this headline"></a></h1>
<p>Now that we have learned a little about how to find things in the Evennia library, lets use it.</p>
<p>In the <a class="reference internal" href="Python-classes-and-objects.html"><span class="doc">Python classes and objects</span></a> lesson we created the dragons Fluffy, Cuddly
<p>In the <a class="reference internal" href="Python-classes-and-objects.html"><span class="doc std std-doc">Python classes and objects</span></a> lesson we created the dragons Fluffy, Cuddly
and Smaug and made them fly and breathe fire. So far our dragons are short-lived - whenever we <code class="docutils literal notranslate"><span class="pre">restart</span></code>
the server or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> out of python mode they are gone.</p>
<p>This is what you should have in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/monsters.py</span></code> so far:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Monster</span><span class="p">:</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This is a base class for Monsters.</span>
@ -107,22 +83,14 @@ the server or <code class="docutils literal notranslate"><span class="pre">quit(
<span class="sd"> Let our dragon breathe fire.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> breathes fire!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<section id="our-first-persistent-object">
<h2>Our first persistent object<a class="headerlink" href="#our-first-persistent-object" title="Permalink to this headline"></a></h2>
<p>At this point we should know enough to understand what is happening in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects.py</span></code>. Lets
open it:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">module docstring</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
@ -133,7 +101,7 @@ open it:</p>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
</pre></div>
</td></tr></table></div>
</div>
<p>So we have a class <code class="docutils literal notranslate"><span class="pre">Object</span></code> that <em>inherits</em> from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>, which we have imported from Evennia.
The class itself doesnt do anything (it just <code class="docutils literal notranslate"><span class="pre">pass</span></code>es) but that doesnt mean its useless. As weve seen,
it inherits all the functionality of its parent. Its in fact an <em>exact replica</em> of <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> right now.
@ -141,37 +109,13 @@ If we knew what kind of methods and resources were available on <code class="doc
change the way it works!</p>
<blockquote>
<div><p>Hint: We will get back to this, but to learn what resources an Evennia parent like <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> offers,
easiest is to peek at its <a class="reference external" href="../../../api/evennia.objects.objects.html#DefaultObject">API documentation</a>. The docstring for
easiest is to peek at its <a class="reference internal" href="../../../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">API documentation</span></a>. The docstring for
the <code class="docutils literal notranslate"><span class="pre">Object</span></code> class can also help.</p>
</div></blockquote>
<p>One thing that Evennia classes offers and which you dont get with vanilla Python classes is <em>persistence</em>. As
youve found, Fluffy, Cuddly and Smaug are gone once we reload the server. Lets see if we can fix this.</p>
<p>Go back to <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/monsters.py</span></code>. Change it as follows:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="kn">from</span> <span class="nn">typeclasses.objects</span> <span class="kn">import</span> <span class="n">Object</span>
<span class="k">class</span> <span class="nc">Monster</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
@ -196,8 +140,9 @@ youve found, Fluffy, Cuddly and Smaug are gone once we reload the server. Let
<span class="sd"> Let our dragon breathe fire.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> breathes fire!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Dont forget to save. We removed <code class="docutils literal notranslate"><span class="pre">Monster.__init__</span></code> and made <code class="docutils literal notranslate"><span class="pre">Monster</span></code> inherit from Evennias <code class="docutils literal notranslate"><span class="pre">Object</span></code> (which in turn
inherits from Evennias <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>, as we saw). By extension, this means that <code class="docutils literal notranslate"><span class="pre">Dragon</span></code> also inherits
from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>, just from further away!</p>
@ -206,12 +151,14 @@ from <code class="docutils literal notranslate"><span class="pre">DefaultObject<
<p>First reload the server as usual. We will need to create the dragon a little differently this time:</p>
<aside class="sidebar">
<p class="sidebar-title">Keyword arguments</p>
<p>Keyword arguments (like <cite>db_key=”Smaug”</cite>) is a way to
name the input arguments to a function or method. They make
things easier to read but also allows for conveniently setting
defaults for values not given explicitly.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Keyword arguments (like `db_key=&quot;Smaug&quot;`) is a way to
name the input arguments to a function or method. They make
things easier to read but also allows for conveniently setting
defaults for values not given explicitly.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Dragon
&gt; smaug = Dragon(db_key=&quot;Smaug&quot;, db_location=here)
&gt; smaug.save()
@ -222,14 +169,14 @@ The world trembles.
</div>
<p>Smaug works the same as before, but we created him differently: first we used
<code class="docutils literal notranslate"><span class="pre">Dragon(db_key=&quot;Smaug&quot;,</span> <span class="pre">db_location=here)</span></code> to create the object, and then we used <code class="docutils literal notranslate"><span class="pre">smaug.save()</span></code> afterwards.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quit</span><span class="p">()</span>
<span class="n">Python</span> <span class="n">Console</span> <span class="ow">is</span> <span class="n">closing</span><span class="o">.</span>
<span class="o">&gt;</span> <span class="n">look</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Python Console is closing.
&gt; look
</pre></div>
</div>
<p>You should now see that Smaug <em>is in the room with you</em>. Woah!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">look</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; look
</pre></div>
</div>
<p><em>Hes still there</em>… What we just did was to create a new entry in the database for Smaug. We gave the object
@ -237,7 +184,7 @@ its name (key) and set its location to our current location (remember that <code
in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command, you cant use it elsewhere).</p>
<p>To make use of Smaug in code we must first find him in the database. For an object in the current
location we can easily do this in <code class="docutils literal notranslate"><span class="pre">py</span></code> by using <code class="docutils literal notranslate"><span class="pre">me.search()</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py smaug = me.search(&quot;Smaug&quot;) ; smaug.firebreath()
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py smaug = me.search(&quot;Smaug&quot;) ; smaug.firebreath()
Smaug breathes fire!
</pre></div>
</div>
@ -248,14 +195,14 @@ Smaug breathes fire!
bound Python instances before. But you need to use <code class="docutils literal notranslate"><span class="pre">db_key</span></code> instead of <code class="docutils literal notranslate"><span class="pre">key</span></code> and you also have to
remember to call <code class="docutils literal notranslate"><span class="pre">.save()</span></code> afterwards. Evennia has a helper function that is more common to use,
called <code class="docutils literal notranslate"><span class="pre">create_object</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">fluffy</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="s1">&#39;typeclases.monster.Monster&#39;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;Fluffy&quot;</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">here</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">look</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py fluffy = evennia.create_object(&#39;typeclases.monster.Monster&#39;, key=&quot;Fluffy&quot;, location=here)
&gt; look
</pre></div>
</div>
<p>Boom, Fluffy should now be in the room with you, a little less scary than Smaug. You specify the
python-path to the code you want and then set the key and location. Evennia sets things up and saves for you.</p>
<p>If you want to find Fluffy from anywhere, you can use Evennias <code class="docutils literal notranslate"><span class="pre">search_object</span></code> helper:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; fluffy = evennia.search_object(&quot;Fluffy&quot;)[0] ; fluffy.move_around()
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; fluffy = evennia.search_object(&quot;Fluffy&quot;)[0] ; fluffy.move_around()
Fluffy is moving!
</pre></div>
</div>
@ -268,13 +215,13 @@ multiple Fluffies we could get the second one with <code class="docutils literal
<section id="creating-using-create-command">
<h3>Creating using create-command<a class="headerlink" href="#creating-using-create-command" title="Permalink to this headline"></a></h3>
<p>Finally, you can also create a new Dragon using the familiar builder-commands we explored a few lessons ago:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">Cuddly</span><span class="p">:</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">monsters</span><span class="o">.</span><span class="n">Monster</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create/drop Cuddly:typeclasses.monsters.Monster
</pre></div>
</div>
<p>Cuddly is now in the room. After learning about how objects are created youll realize that all this command really
does is to parse your input, figure out that <code class="docutils literal notranslate"><span class="pre">/drop</span></code> means to “give the object the same location as the caller”,
and then do a call akin to</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="s2">&quot;typeclasses.monsters.Monster&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;Cuddly&quot;</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">here</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia.create_object(&quot;typeclasses.monsters.Monster&quot;, key=&quot;Cuddly&quot;, location=here)
</pre></div>
</div>
<p>Thats pretty much all there is to the mighty <code class="docutils literal notranslate"><span class="pre">create</span></code> command! The rest is just parsing for the command
@ -325,31 +272,31 @@ own modules and import the base class.</p>
<section id="examining-and-defaults">
<h3>Examining and defaults<a class="headerlink" href="#examining-and-defaults" title="Permalink to this headline"></a></h3>
<p>When you do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">giantess</span><span class="p">:</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">monsters</span><span class="o">.</span><span class="n">Monster</span>
<span class="n">You</span> <span class="n">create</span> <span class="n">a</span> <span class="n">new</span> <span class="n">Monster</span><span class="p">:</span> <span class="n">giantess</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create/drop giantess:typeclasses.monsters.Monster
You create a new Monster: giantess.
</pre></div>
</div>
<p>or</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">evennia</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="s2">&quot;typeclasses.monsters.Monster&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;Giantess&quot;</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">here</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py evennia.create_object(&quot;typeclasses.monsters.Monster&quot;, key=&quot;Giantess&quot;, location=here)
</pre></div>
</div>
<p>You are specifying exactly which typeclass you want to use to build the Giantess. Lets examine the result:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">examine</span> <span class="n">giantess</span>
<span class="o">-------------------------------------------------------------------------------</span>
<span class="n">Name</span><span class="o">/</span><span class="n">key</span><span class="p">:</span> <span class="n">Giantess</span> <span class="p">(</span><span class="c1">#14)</span>
<span class="n">Typeclass</span><span class="p">:</span> <span class="n">Monster</span> <span class="p">(</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">monsters</span><span class="o">.</span><span class="n">Monster</span><span class="p">)</span>
<span class="n">Location</span><span class="p">:</span> <span class="n">Limbo</span> <span class="p">(</span><span class="c1">#2)</span>
<span class="n">Home</span><span class="p">:</span> <span class="n">Limbo</span> <span class="p">(</span><span class="c1">#2)</span>
<span class="n">Permissions</span><span class="p">:</span> <span class="o">&lt;</span><span class="kc">None</span><span class="o">&gt;</span>
<span class="n">Locks</span><span class="p">:</span> <span class="n">call</span><span class="p">:</span><span class="n">true</span><span class="p">();</span> <span class="n">control</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">);</span> <span class="n">delete</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">);</span>
<span class="n">drop</span><span class="p">:</span><span class="n">holds</span><span class="p">();</span> <span class="n">edit</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">);</span> <span class="n">examine</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Builder</span><span class="p">);</span> <span class="n">get</span><span class="p">:</span><span class="nb">all</span><span class="p">();</span>
<span class="n">puppet</span><span class="p">:</span><span class="n">pperm</span><span class="p">(</span><span class="n">Developer</span><span class="p">);</span> <span class="n">tell</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">);</span> <span class="n">view</span><span class="p">:</span><span class="nb">all</span><span class="p">()</span>
<span class="n">Persistent</span> <span class="n">attributes</span><span class="p">:</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">You</span> <span class="n">see</span> <span class="n">nothing</span> <span class="n">special</span><span class="o">.</span>
<span class="o">-------------------------------------------------------------------------------</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; examine giantess
-------------------------------------------------------------------------------
Name/key: Giantess (#14)
Typeclass: Monster (typeclasses.monsters.Monster)
Location: Limbo (#2)
Home: Limbo (#2)
Permissions: &lt;None&gt;
Locks: call:true(); control:id(1) or perm(Admin); delete:id(1) or perm(Admin);
drop:holds(); edit:perm(Admin); examine:perm(Builder); get:all();
puppet:pperm(Developer); tell:perm(Admin); view:all()
Persistent attributes:
desc = You see nothing special.
-------------------------------------------------------------------------------
</pre></div>
</div>
<p>We used the <code class="docutils literal notranslate"><span class="pre">examine</span></code> command briefly in the <a class="reference internal" href="Building-Quickstart.html"><span class="doc">lesson about building in-game</span></a>. Now these lines
<p>We used the <code class="docutils literal notranslate"><span class="pre">examine</span></code> command briefly in the <a class="reference internal" href="Building-Quickstart.html"><span class="doc std std-doc">lesson about building in-game</span></a>. Now these lines
may be more useful to us:</p>
<ul class="simple">
<li><p><strong>Name/key</strong> - The name of this thing. The value <code class="docutils literal notranslate"><span class="pre">(#14)</span></code> is probably different for you. This is the
@ -368,20 +315,20 @@ to those in the next section.</p></li>
<p>Note how the <strong>Typeclass</strong> line describes exactly where to find the code of this object? This is very useful for
understanding how any object in Evennia works.</p>
<p>What happens if we <em>dont</em> specify the typeclass though?</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box</span>
<span class="n">You</span> <span class="n">create</span> <span class="n">a</span> <span class="n">new</span> <span class="n">Object</span><span class="p">:</span> <span class="n">box</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create/drop box
You create a new Object: box.
</pre></div>
</div>
<p>or</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">create</span><span class="o">.</span><span class="n">create_object</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;box&quot;</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">here</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py create.create_object(None, key=&quot;box&quot;, location=here)
</pre></div>
</div>
<p>Now check it out:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">examine</span> <span class="n">box</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; examine box
</pre></div>
</div>
<p>You will find that the <strong>Typeclass</strong> line now reads</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Typeclass</span><span class="p">:</span> <span class="n">Object</span> <span class="p">(</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">Object</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Typeclass: Object (typeclasses.objects.Object)
</pre></div>
</div>
<p>So when you didnt specify a typeclass, Evennia used a default, more specifically the (so far) empty <code class="docutils literal notranslate"><span class="pre">Object</span></code> class in
@ -392,10 +339,12 @@ in <a class="reference external" href="https://github.com/evennia/evennia/blob/m
with the name <code class="docutils literal notranslate"><span class="pre">BASE_OBJECT_TYPECLASS</span></code>, which is set to <code class="docutils literal notranslate"><span class="pre">typeclasses.objects.Object</span></code>.</p>
<aside class="sidebar">
<p class="sidebar-title">Changing things</p>
<p>While its tempting to change folders around to your liking, this can
make it harder to follow tutorials and may confuse if
you are asking others for help. So dont overdo it unless you really
know what you are doing.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>While it&#39;s tempting to change folders around to your liking, this can
make it harder to follow tutorials and may confuse if
you are asking others for help. So don&#39;t overdo it unless you really
know what you are doing.
</pre></div>
</div>
</aside>
<p>So if you wanted the creation commands and methods to default to some other class you could
add your own <code class="docutils literal notranslate"><span class="pre">BASE_OBJECT_TYPECLASS</span></code> line to <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code>. The same is true for all the other
@ -406,16 +355,7 @@ layout of your game dir considerably if you wanted. You just need to tell Evenni
<section id="modifying-ourselves">
<h2>Modifying ourselves<a class="headerlink" href="#modifying-ourselves" title="Permalink to this headline"></a></h2>
<p>Lets try to modify ourselves a little. Open up <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">(module docstring)</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultCharacter</span>
@ -426,34 +366,34 @@ layout of your game dir considerably if you wanted. You just need to tell Evenni
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This looks quite familiar now - an empty class inheriting from the Evennia base typeclass. As you would expect,
this is also the default typeclass used for creating Characters if you dont specify it. You can verify it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">examine</span> <span class="n">me</span>
<span class="o">------------------------------------------------------------------------------</span>
<span class="n">Name</span><span class="o">/</span><span class="n">key</span><span class="p">:</span> <span class="n">YourName</span> <span class="p">(</span><span class="c1">#1)</span>
<span class="n">Session</span> <span class="nb">id</span><span class="p">(</span><span class="n">s</span><span class="p">):</span> <span class="c1">#1</span>
<span class="n">Account</span><span class="p">:</span> <span class="n">YourName</span>
<span class="n">Account</span> <span class="n">Perms</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">Superuser</span><span class="o">&gt;</span> <span class="p">(</span><span class="n">quelled</span><span class="p">)</span>
<span class="n">Typeclass</span><span class="p">:</span> <span class="n">Character</span> <span class="p">(</span><span class="n">typeclasses</span><span class="o">.</span><span class="n">characters</span><span class="o">.</span><span class="n">Character</span><span class="p">)</span>
<span class="n">Location</span><span class="p">:</span> <span class="n">Limbo</span> <span class="p">(</span><span class="c1">#2)</span>
<span class="n">Home</span><span class="p">:</span> <span class="n">Limbo</span> <span class="p">(</span><span class="c1">#2)</span>
<span class="n">Permissions</span><span class="p">:</span> <span class="n">developer</span><span class="p">,</span> <span class="n">player</span>
<span class="n">Locks</span><span class="p">:</span> <span class="n">boot</span><span class="p">:</span><span class="n">false</span><span class="p">();</span> <span class="n">call</span><span class="p">:</span><span class="n">false</span><span class="p">();</span> <span class="n">control</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Developer</span><span class="p">);</span> <span class="n">delete</span><span class="p">:</span><span class="n">false</span><span class="p">();</span>
<span class="n">drop</span><span class="p">:</span><span class="n">holds</span><span class="p">();</span> <span class="n">edit</span><span class="p">:</span><span class="n">false</span><span class="p">();</span> <span class="n">examine</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Developer</span><span class="p">);</span> <span class="n">get</span><span class="p">:</span><span class="n">false</span><span class="p">();</span>
<span class="n">msg</span><span class="p">:</span><span class="nb">all</span><span class="p">();</span> <span class="n">puppet</span><span class="p">:</span><span class="n">false</span><span class="p">();</span> <span class="n">tell</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">);</span> <span class="n">view</span><span class="p">:</span><span class="nb">all</span><span class="p">()</span>
<span class="n">Stored</span> <span class="n">Cmdset</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="n">commands</span><span class="o">.</span><span class="n">default_cmdsets</span><span class="o">.</span><span class="n">CharacterCmdSet</span> <span class="p">[</span><span class="n">DefaultCharacter</span><span class="p">]</span> <span class="p">(</span><span class="n">Union</span><span class="p">,</span> <span class="n">prio</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Merged</span> <span class="n">Cmdset</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="o">...</span>
<span class="n">Commands</span> <span class="n">available</span> <span class="n">to</span> <span class="n">YourName</span> <span class="p">(</span><span class="n">result</span> <span class="n">of</span> <span class="n">Merged</span> <span class="n">CmdSets</span><span class="p">):</span>
<span class="o">...</span>
<span class="n">Persistent</span> <span class="n">attributes</span><span class="p">:</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">User</span> <span class="c1">#1.</span>
<span class="n">prelogout_location</span> <span class="o">=</span> <span class="n">Limbo</span>
<span class="n">Non</span><span class="o">-</span><span class="n">Persistent</span> <span class="n">attributes</span><span class="p">:</span>
<span class="n">last_cmd</span> <span class="o">=</span> <span class="kc">None</span>
<span class="o">------------------------------------------------------------------------------</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; examine me
------------------------------------------------------------------------------
Name/key: YourName (#1)
Session id(s): #1
Account: YourName
Account Perms: &lt;Superuser&gt; (quelled)
Typeclass: Character (typeclasses.characters.Character)
Location: Limbo (#2)
Home: Limbo (#2)
Permissions: developer, player
Locks: boot:false(); call:false(); control:perm(Developer); delete:false();
drop:holds(); edit:false(); examine:perm(Developer); get:false();
msg:all(); puppet:false(); tell:perm(Admin); view:all()
Stored Cmdset(s):
commands.default_cmdsets.CharacterCmdSet [DefaultCharacter] (Union, prio 0)
Merged Cmdset(s):
...
Commands available to YourName (result of Merged CmdSets):
...
Persistent attributes:
desc = This is User #1.
prelogout_location = Limbo
Non-Persistent attributes:
last_cmd = None
------------------------------------------------------------------------------
</pre></div>
</div>
<p>You got a lot longer output this time. You have a lot more going on than a simple Object. Here are some new fields of note:</p>
@ -461,7 +401,7 @@ this is also the default typeclass used for creating Characters if you dont s
<li><p><strong>Session id(s)</strong>: This identifies the <em>Session</em> (that is, the individual connection to a players game client).</p></li>
<li><p><strong>Account</strong> shows, well the <code class="docutils literal notranslate"><span class="pre">Account</span></code> object associated with this Character and Session.</p></li>
<li><p><strong>Stored/Merged Cmdsets</strong> and <strong>Commands available</strong> is related to which <em>Commands</em> are stored on you. We will
get to them in the <a class="reference internal" href="Adding-Commands.html"><span class="doc">next lesson</span></a>. For now its enough to know these consitute all the
get to them in the <a class="reference internal" href="Adding-Commands.html"><span class="doc std std-doc">next lesson</span></a>. For now its enough to know these consitute all the
commands available to you at a given moment.</p></li>
<li><p><strong>Non-Persistent attributes</strong> are Attributes that are only stored temporarily and will go away on next reload.</p></li>
</ul>
@ -470,21 +410,7 @@ So if we modify this class well also modify ourselves.</p>
<section id="a-method-on-ourselves">
<h3>A method on ourselves<a class="headerlink" href="#a-method-on-ourselves" title="Permalink to this headline"></a></h3>
<p>Lets try something simple first. Back in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> (class docstring)</span>
@ -499,49 +425,50 @@ So if we modify this class well also modify ourselves.</p>
<span class="sd"> Get the main stats of this character</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dex</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">int</span>
</pre></div>
</td></tr></table></div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
</div>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.get_stats()
(10, 12, 15)
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Tuples and lists</p>
<ul class="simple">
<li><p>A <cite>list</cite> is written <cite>[a, b, c, d, …]</cite>. It can be modified after creation.</p></li>
<li><p>A <cite>tuple</cite> is written <cite>(a, b, c, …)</cite>. It cannot be modified once created.</p></li>
</ul>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- A `list` is written `[a, b, c, d, ...]`. It can be modified after creation.
- A `tuple` is written `(a, b, c, ...)`. It cannot be modified once created.
</pre></div>
</div>
</aside>
<p>We made a new method, gave it a docstring and had it <code class="docutils literal notranslate"><span class="pre">return</span></code> the RP-esque values we set. It comes back as a
<em>tuple</em> <code class="docutils literal notranslate"><span class="pre">(10,</span> <span class="pre">12,</span> <span class="pre">15)</span></code>. To get a specific value you could specify the <em>index</em> of the value you want,
starting from zero:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">stats</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span> <span class="p">;</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Strength is </span><span class="si">{</span><span class="n">stats</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">)</span>
<span class="n">Strength</span> <span class="ow">is</span> <span class="mf">10.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py stats = self.get_stats() ; print(f&quot;Strength is {stats[0]}.&quot;)
Strength is 10.
</pre></div>
</div>
</section>
<section id="attributes">
<h3>Attributes<a class="headerlink" href="#attributes" title="Permalink to this headline"></a></h3>
<p>So what happens when we increase our strength? This would be one way:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span> <span class="o">+</span> <span class="mi">1</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span>
<span class="mi">11</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.str = self.str + 1
&gt; py self.str
11
</pre></div>
</div>
<p>Here we set the strength equal to its previous value + 1. A shorter way to write this is to use Pythons <code class="docutils literal notranslate"><span class="pre">+=</span></code>
operator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span>
<span class="mi">12</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.str += 1
&gt; py self.str
12
&gt; py self.get_stats()
(12, 12, 15)
</pre></div>
</div>
<p>This looks correct! Try to change the values for dex and int too; it works fine. However:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.get_stats()
(10, 12, 15)
</pre></div>
</div>
<p>After a reload all our changes were forgotten. When we change properties like this, it only changes in memory,
@ -552,17 +479,7 @@ since we have the stats hardcoded in the class, <em>every</em> character instanc
same <code class="docutils literal notranslate"><span class="pre">str</span></code>, <code class="docutils literal notranslate"><span class="pre">dex</span></code> and <code class="docutils literal notranslate"><span class="pre">int</span></code> now! This is clearly not what we want.</p>
<p>Evennia offers a special, persistent type of property for this, called an <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>. Rework your
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> (class docstring)</span>
@ -574,47 +491,49 @@ same <code class="docutils literal notranslate"><span class="pre">str</span></co
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">dex</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">int</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Spaces in Attribute name?</p>
<p>What if you want spaces in your Attribute name? Or you want to assign the
name of the Attribute on-the fly? Then you can use <cite>.attributes.add(name, value)</cite> instead,
for example <cite>self.attributes.add(“str”, 10)</cite>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>What if you want spaces in your Attribute name? Or you want to assign the
name of the Attribute on-the fly? Then you can use `.attributes.add(name, value)` instead,
for example `self.attributes.add(&quot;str&quot;, 10)`.
</pre></div>
</div>
</aside>
<p>We removed the hard-coded stats and added added <code class="docutils literal notranslate"><span class="pre">.db</span></code> for every stat. The <code class="docutils literal notranslate"><span class="pre">.db</span></code> handler makes the stat
into an an Evennia <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.get_stats()
(None, None, None)
</pre></div>
</div>
<p>Since we removed the hard-coded values, Evennia dont know what they should be (yet). So all we get back
is <code class="docutils literal notranslate"><span class="pre">None</span></code>, which is a Python reserved word to represent nothing, a no-value. This is different from a normal python
property:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">str</span>
<span class="ne">AttributeError</span><span class="p">:</span> <span class="s1">&#39;Character&#39;</span> <span class="nb">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="s1">&#39;str&#39;</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">str</span>
<span class="p">(</span><span class="n">nothing</span> <span class="n">will</span> <span class="n">be</span> <span class="n">displayed</span><span class="p">,</span> <span class="n">because</span> <span class="n">it</span><span class="s1">&#39;s None)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.str
AttributeError: &#39;Character&#39; object has no attribute &#39;str&#39;
&gt; py self.db.str
(nothing will be displayed, because it&#39;s None)
</pre></div>
</div>
<p>Trying to get an unknown normal Python property will give an error. Getting an unknown Evennia <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> will
never give an error, but only result in <code class="docutils literal notranslate"><span class="pre">None</span></code> being returned. This is often very practical.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">dex</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">int</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.db.str, self.db.dex, self.db.int = 10, 12, 15
&gt; py self.get_stats()
(10, 12, 15)
&gt; reload
&gt; py self.get_stats()
(10, 12, 15)
</pre></div>
</div>
<p>Now we set the Attributes to the right values. We can see that things work the same as before, also after a
server reload. Lets modify the strength:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">str</span> <span class="o">+=</span> <span class="mi">2</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.db.str += 2
&gt; py self.get_stats()
(12, 12, 15)
&gt; reload
&gt; py self.get_stats()
(12, 12, 15)
</pre></div>
</div>
<p>Our change now survives a reload since Evennia automatically saves the Attribute to the database for us.</p>
@ -627,30 +546,15 @@ in more detail. For now, lets give every new character some random stats to s
<p>We want those stats to be set only once, when the object is first created. For the Character, this method
is called <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>.</p>
<aside class="sidebar">
<p class="sidebar-title">__init__ vs at_object_creation</p>
<p>For the <cite>Monster</cite> class we used <cite>__init__</cite> to set up the class. We cant use this
<p class="sidebar-title"><strong>init</strong> vs at_object_creation</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>For the `Monster` class we used `__init__` to set up the class. We can&#39;t use this
for a typeclass because it will be called more than once, at the very least after
every reload and maybe more depending on caching. Even if you are familiar with Python,
avoid touching <cite>__init__</cite> for typeclasses, the results will not be what you expect.</p>
avoid touching `__init__` for typeclasses, the results will not be what you expect.
</pre></div>
</div>
</aside>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># up by the other imports</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># up by the other imports</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
@ -669,28 +573,28 @@ avoid touching <cite>__init__</cite> for typeclasses, the results will not be wh
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">dex</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">int</span>
</pre></div>
</td></tr></table></div>
</div>
<p>We imported a new module, <code class="docutils literal notranslate"><span class="pre">random</span></code>. This is part of Pythons standard library. We used <code class="docutils literal notranslate"><span class="pre">random.randint</span></code> to
set a random value from 3 to 18 to each stat. Simple, but for some classical RPGs this is all you need!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py self.get_stats()
(12, 12, 15)
</pre></div>
</div>
<p>Hm, this is the same values we set before. They are not random. The reason for this is of course that, as said,
<code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> only runs <em>once</em>, the very first time a character is created. Our character object was already
created long before, so it will not be called again.</p>
<p>Its simple enough to run it manually though:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">at_object_creation</span><span class="p">()</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; self.at_object_creation()
&gt; py self.get_stats()
(5, 4, 8)
</pre></div>
</div>
<p>Lady luck didnt smile on us for this example; maybe youll fare better. Evennia has a helper command
<code class="docutils literal notranslate"><span class="pre">update</span></code> that re-runs the creation hook and also cleans up any other Attributes not re-created by <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">update</span> <span class="bp">self</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">14</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; update self
&gt; py self.get_stats()
(8, 16, 14)
</pre></div>
</div>
</section>
@ -700,37 +604,39 @@ created long before, so it will not be called again.</p>
before you create a lot of objects (characters in this case). But should it come to that you dont want to have to
go around and re-run the method on everyone manually. For the Python beginner, doing this will also give a chance to
try out Python <em>loops</em>. We try them out in multi-line Python mode:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span>
<span class="o">&gt;</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">&quot;foo&quot;</span><span class="p">]:</span> <span class="o">&gt;</span> <span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="n">foo</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; for a in [1, 2, &quot;foo&quot;]: &gt; print(a)
1
2
foo
</pre></div>
</div>
<p>A python <em>for-loop</em> allows us to loop over something. Above, we made a <em>list</em> of two numbers and a string. In
every iteration of the loop, the variable <code class="docutils literal notranslate"><span class="pre">a</span></code> becomes one element in turn, and we print that.</p>
<p>For our list, we want to loop over all Characters, and want to call <code class="docutils literal notranslate"><span class="pre">.at_object_creation</span></code> on each. This is how
this is done (still in python multi-line mode):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="kn">from</span> <span class="nn">typeclasses.characters</span> <span class="kn">import</span> <span class="n">Character</span>
<span class="o">&gt;</span> <span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">Character</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="o">&gt;</span> <span class="n">char</span><span class="o">.</span><span class="n">at_object_creation</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; from typeclasses.characters import Character
&gt; for char in Character.objects.all()
&gt; char.at_object_creation()
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Database queries</p>
<p><cite>Character.objects.all()</cite> is an example of a database query expressed in Python. This will be converted
into a database query under the hood. This syntax is part of
<a class="reference external" href="https://docs.djangoproject.com/en/3.0/topics/db/queries/">Djangos query language</a>. You dont need to
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>`Character.objects.all()` is an example of a database query expressed in Python. This will be converted
into a database query under the hood. This syntax is part of
`Django&#39;s query language &lt;https://docs.djangoproject.com/en/3.0/topics/db/queries/&gt;`_. You don&#39;t need to
know Django to use Evennia, but if you ever need more specific database queries, this is always available
when you need it.</p>
when you need it.
</pre></div>
</div>
</aside>
<p>We import the <code class="docutils literal notranslate"><span class="pre">Character</span></code> class and then we use <code class="docutils literal notranslate"><span class="pre">.objects.all()</span></code> to get all <code class="docutils literal notranslate"><span class="pre">Character</span></code> instances. Simplified,
<code class="docutils literal notranslate"><span class="pre">.objects</span></code> is a resource from which one can <em>query</em> for all <code class="docutils literal notranslate"><span class="pre">Characters</span></code>. Using <code class="docutils literal notranslate"><span class="pre">.all()</span></code> gets us a listing
of all of them that we then immediately loop over. Boom, we just updated all Characters, including ourselves:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quit</span><span class="p">()</span>
<span class="n">Closing</span> <span class="n">the</span> <span class="n">Python</span> <span class="n">console</span><span class="o">.</span>
<span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_stats</span><span class="p">()</span>
<span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">18</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Closing the Python console.
&gt; self.get_stats()
(3, 18, 10)
</pre></div>
</div>
</section>
@ -825,7 +731,7 @@ this tutorial. But thats enough of them for now. Its time to take some act
<h3>Versions</h3>
<ul>
<li><a href="Learning-Typeclasses.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,7 +49,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="more-about-commands">
<section class="tex2jax_ignore mathjax_ignore" id="more-about-commands">
<h1>More about Commands<a class="headerlink" href="#more-about-commands" title="Permalink to this headline"></a></h1>
<p>In this lesson we learn some basics about parsing the input of Commands. We will
also learn how to add, modify and extend Evennias default commands.</p>
@ -56,61 +58,19 @@ also learn how to add, modify and extend Evennias default commands.</p>
<p>In the last lesson we made a <code class="docutils literal notranslate"><span class="pre">hit</span></code> Command and hit a dragon with it. You should have the code
from that still around.</p>
<p>Lets expand our simple <code class="docutils literal notranslate"><span class="pre">hit</span></code> command to accept a little more complex input:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">hit</span> <span class="o">&lt;</span><span class="n">target</span><span class="o">&gt;</span> <span class="p">[[</span><span class="k">with</span><span class="p">]</span> <span class="o">&lt;</span><span class="n">weapon</span><span class="o">&gt;</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>hit &lt;target&gt; [[with] &lt;weapon&gt;]
</pre></div>
</div>
<p>That is, we want to support all of these forms</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">hit</span> <span class="n">target</span>
<span class="n">hit</span> <span class="n">target</span> <span class="n">weapon</span>
<span class="n">hit</span> <span class="n">target</span> <span class="k">with</span> <span class="n">weapon</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>hit target
hit target weapon
hit target with weapon
</pre></div>
</div>
<p>If you dont specify a weapon youll use your fists. Its also nice to be able to skip “with” if
you are in a hurry. Time to modify <code class="docutils literal notranslate"><span class="pre">mygame/commands/mycommands.py</span></code> again. Let us break out the parsing
a little, in a new method <code class="docutils literal notranslate"><span class="pre">parse</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1">#...</span>
<span class="k">class</span> <span class="nc">CmdHit</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -153,18 +113,19 @@ a little, in a new method <code class="docutils literal notranslate"><span class
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You hit </span><span class="si">{</span><span class="n">target</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> with </span><span class="si">{</span><span class="n">weaponstr</span><span class="si">}</span><span class="s2">!&quot;</span><span class="p">)</span>
<span class="n">target</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You got hit by </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> with </span><span class="si">{</span><span class="n">weaponstr</span><span class="si">}</span><span class="s2">!&quot;</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">parse</span></code> method is called before <code class="docutils literal notranslate"><span class="pre">func</span></code> and has access to all the same on-command variables as in <code class="docutils literal notranslate"><span class="pre">func</span></code>. Using
<code class="docutils literal notranslate"><span class="pre">parse</span></code> not only makes things a little easier to read, it also means you can easily let other Commands <em>inherit</em>
your parsing - if you wanted some other Command to also understand input on the form <code class="docutils literal notranslate"><span class="pre">&lt;arg&gt;</span> <span class="pre">with</span> <span class="pre">&lt;arg&gt;</span></code> youd inherit
from this class and just implement the <code class="docutils literal notranslate"><span class="pre">func</span></code> needed for that command without implementing <code class="docutils literal notranslate"><span class="pre">parse</span></code> anew.</p>
<aside class="sidebar">
<p class="sidebar-title">Tuples and Lists</p>
<ul class="simple">
<li><p>A <cite>list</cite> is written as <cite>[a, b, c, d, …]</cite>. You can add and grow/shrink a list after it was first created.</p></li>
<li><p>A <cite>tuple</cite> is written as <cite>(a, b, c, d, …)</cite>. A tuple cannot be modified once it is created.</p></li>
</ul>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- A `list` is written as `[a, b, c, d, ...]`. You can add and grow/shrink a list after it was first created.
- A `tuple` is written as `(a, b, c, d, ...)`. A tuple cannot be modified once it is created.
</pre></div>
</div>
</aside>
<ul>
<li><p><strong>Line 14</strong> - We do the stripping of <code class="docutils literal notranslate"><span class="pre">self.args</span></code> once and for all here. We also store the stripped version back
@ -215,7 +176,7 @@ use this to create a <code class="docutils literal notranslate"><span class="pre
<li><p><strong>Lines 41-42</strong> - We merge the <code class="docutils literal notranslate"><span class="pre">weaponstr</span></code> with our attack text.</p></li>
</ul>
<p>Lets try it out!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; reload
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; hit smaug with sword
Could not find &#39;sword&#39;.
You hit smaug with bare fists!
@ -224,13 +185,13 @@ You hit smaug with bare fists!
<p>Oops, our <code class="docutils literal notranslate"><span class="pre">self.caller.search(self.weapon)</span></code> is telling us that it found no sword. Since we are not <code class="docutils literal notranslate"><span class="pre">return</span></code>ing
in this situation (like we do if failing to find <code class="docutils literal notranslate"><span class="pre">target</span></code>) we still continue fighting with our bare hands.
This wont do. Lets make ourselves a sword.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">create</span> <span class="n">sword</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create sword
</pre></div>
</div>
<p>Since we didnt specify <code class="docutils literal notranslate"><span class="pre">/drop</span></code>, the sword will end up in our inventory and can seen with the <code class="docutils literal notranslate"><span class="pre">i</span></code> or
<code class="docutils literal notranslate"><span class="pre">inventory</span></code> command. The <code class="docutils literal notranslate"><span class="pre">.search</span></code> helper will still find it there. There is no need to reload to see this
change (no code changed, only stuff in the database).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; hit smaug with sword
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hit smaug with sword
You hit smaug with sword!
</pre></div>
</div>
@ -238,49 +199,51 @@ You hit smaug with sword!
<section id="adding-a-command-to-an-object">
<h2>Adding a Command to an object<a class="headerlink" href="#adding-a-command-to-an-object" title="Permalink to this headline"></a></h2>
<p>The commands of a cmdset attached to an object with <code class="docutils literal notranslate"><span class="pre">obj.cmdset.add()</span></code> will by default be made available to that object
but <em>also to those in the same location as that object</em>. If you did the <a class="reference internal" href="Building-Quickstart.html"><span class="doc">Building introduction</span></a>
youve seen an example of this with the “Red Button” object. The <a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc">Tutorial world</span></a>
but <em>also to those in the same location as that object</em>. If you did the <a class="reference internal" href="Building-Quickstart.html"><span class="doc std std-doc">Building introduction</span></a>
youve seen an example of this with the “Red Button” object. The <a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc std std-doc">Tutorial world</span></a>
also has many examples of objects with commands on them.</p>
<p>To show how this could work, lets put our hit Command on our simple <code class="docutils literal notranslate"><span class="pre">sword</span></code> object from the previous section.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;sword&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;commands.mycommands.MyCmdSet&quot;</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; self.search(&quot;sword&quot;).cmdset.add(&quot;commands.mycommands.MyCmdSet&quot;, persistent=True)
</pre></div>
</div>
<p>We find the sword (its still in our inventory so <code class="docutils literal notranslate"><span class="pre">self.search</span></code> should be able to find it), then
add <code class="docutils literal notranslate"><span class="pre">MyCmdSet</span></code> to it. This actually adds both <code class="docutils literal notranslate"><span class="pre">hit</span></code> and <code class="docutils literal notranslate"><span class="pre">echo</span></code> to the sword, which is fine.</p>
<p>Lets try to swing it!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">hit</span>
<span class="n">More</span> <span class="n">than</span> <span class="n">one</span> <span class="n">match</span> <span class="k">for</span> <span class="s1">&#39;hit&#39;</span> <span class="p">(</span><span class="n">please</span> <span class="n">narrow</span> <span class="n">target</span><span class="p">):</span>
<span class="n">hit</span><span class="o">-</span><span class="mi">1</span> <span class="p">(</span><span class="n">sword</span> <span class="c1">#11)</span>
<span class="n">hit</span><span class="o">-</span><span class="mi">2</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hit
More than one match for &#39;hit&#39; (please narrow target):
hit-1 (sword #11)
hit-2
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Multi-matches</p>
<p>Some game engines will just pick the first hit when finding more than one.
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Some game engines will just pick the first hit when finding more than one.
Evennia will always give you a choice. The reason for this is that Evennia
cannot know if <cite>hit</cite> and <cite>hit</cite> are different or the same - maybe it behaves
cannot know if `hit` and `hit` are different or the same - maybe it behaves
differently depending on the object it sits on? Besides, imagine if you had
a red and a blue button both with the command <cite>push</cite> on it. Now you just write
<cite>push</cite>. Wouldnt you prefer to be asked <cite>which</cite> button you really wanted to push?</p>
a red and a blue button both with the command `push` on it. Now you just write
`push`. Wouldn&#39;t you prefer to be asked `which` button you really wanted to push?
</pre></div>
</div>
</aside>
<p>Woah, that didnt go as planned. Evennia actually found <em>two</em> <code class="docutils literal notranslate"><span class="pre">hit</span></code> commands to didnt know which one to use
(<em>we</em> know they are the same, but Evennia cant be sure of that). As we can see, <code class="docutils literal notranslate"><span class="pre">hit-1</span></code> is the one found on
the sword. The other one is from adding <code class="docutils literal notranslate"><span class="pre">MyCmdSet</span></code> to ourself earlier. Its easy enough to tell Evennia which
one you meant:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; hit-1
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hit-1
Who do you want to hit?
&gt; hit-2
Who do you want to hit?
</pre></div>
</div>
<p>In this case we dont need both command-sets, so lets just keep the one on the sword:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; self.cmdset.remove(&quot;commands.mycommands.MyCmdSet&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; self.cmdset.remove(&quot;commands.mycommands.MyCmdSet&quot;)
&gt; hit
Who do you want to hit?
</pre></div>
</div>
<p>Now try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; tunnel n = kitchen
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; tunnel n = kitchen
&gt; n
&gt; drop sword
&gt; s
@ -300,12 +263,14 @@ for limiting the kind of things you can do with an object, including limiting ju
it.</p>
<aside class="sidebar">
<p class="sidebar-title">Locks</p>
<p>Evennia Locks are defined as a mini-language defined in <cite>lockstrings</cite>. The lockstring
is on a form <cite>&lt;situation&gt;:&lt;lockfuncs&gt;</cite>, where <cite>situation</cite> determines when this
lock applies and the <cite>lockfuncs</cite> (there can be more than one) are run to determine
if the lock-check passes or not depending on circumstance.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Evennia Locks are defined as a mini-language defined in `lockstrings`. The lockstring
is on a form `&lt;situation&gt;:&lt;lockfuncs&gt;`, where `situation` determines when this
lock applies and the `lockfuncs` (there can be more than one) are run to determine
if the lock-check passes or not depending on circumstance.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;sword&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;call:holds()&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.search(&quot;sword&quot;).locks.add(&quot;call:holds()&quot;)
</pre></div>
</div>
<p>We added a new lock to the sword. The <em>lockstring</em> <code class="docutils literal notranslate"><span class="pre">&quot;call:holds()&quot;</span></code> means that you can only <em>call</em> commands on
@ -314,16 +279,18 @@ this object if you are <em>holding</em> the object (that is, its in your inve
first:</p>
<aside class="sidebar">
<p class="sidebar-title">quell/unquell</p>
<p>Quelling allows you as a developer to take on the role of players with less
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Quelling allows you as a developer to take on the role of players with less
priveleges. This is useful for testing and debugging, in particular since a
superuser has a little <cite>too</cite> much power sometimes.
Use <cite>unquell</cite> to get back to your normal self.</p>
superuser has a little `too` much power sometimes.
Use `unquell` to get back to your normal self.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quell
</pre></div>
</div>
<p>If the sword lies on the ground, try</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; hit
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hit
Command &#39;hit&#39; is not available. ..
&gt; get sword
&gt; hit
@ -332,11 +299,11 @@ Command &#39;hit&#39; is not available. ..
</div>
<p>Finally, we get rid of ours sword so we have a clean slate with no more <code class="docutils literal notranslate"><span class="pre">hit</span></code> commands floating around.
We can do that in two ways:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">delete</span> <span class="n">sword</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>delete sword
</pre></div>
</div>
<p>or</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;sword&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>py self.search(&quot;sword&quot;).delete()
</pre></div>
</div>
</section>
@ -355,55 +322,7 @@ All these commands are in just loaded on the default objects that Evennia provid
</ul>
<p>The thing must commonly modified is the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>.</p>
<p>The default cmdset are defined in <code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdsets.py</span></code>. Open that file now:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">(module docstring)</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -453,11 +372,13 @@ All these commands are in just loaded on the default objects that Evennia provid
<span class="c1"># any commands you add below will overload the default ones</span>
<span class="c1">#</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">super()</p>
<p>The <cite>super()</cite> function refers to the parent of the current class and is commonly
used to call same-named methods on the parent.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The `super()` function refers to the parent of the current class and is commonly
used to call same-named methods on the parent.
</pre></div>
</div>
</aside>
<p><code class="docutils literal notranslate"><span class="pre">evennia.default_cmds</span></code> is a container that holds all of Evennias default commands and cmdsets. In this module
we can see that this was imported and then a new child class was made for each cmdset. Each class looks familiar
@ -468,22 +389,7 @@ This is what adds all the default commands to each CmdSet.</p>
add a Command with the same <code class="docutils literal notranslate"><span class="pre">.key</span></code> as a default command, it would completely replace that original. So if you were
to add a command with a key <code class="docutils literal notranslate"><span class="pre">look</span></code>, the original <code class="docutils literal notranslate"><span class="pre">look</span></code> command would be replaced by your own version.</p>
<p>For now, lets add our own <code class="docutils literal notranslate"><span class="pre">hit</span></code> and <code class="docutils literal notranslate"><span class="pre">echo</span></code> commands to the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
@ -499,28 +405,17 @@ to add a command with a key <code class="docutils literal notranslate"><span cla
<span class="c1">#</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">CmdEcho</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">CmdHit</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; reload
</div>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; hit
Who do you want to hit?
</pre></div>
</div>
<p>Your new commands are now available for all player characters in the game. There is another way to add a bunch
of commands at once, and that is to add a <em>CmdSet</em> to the other cmdset. All commands in that cmdset will then be added:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<span class="k">class</span> <span class="nc">CharacterCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</span><span class="p">):</span>
@ -534,7 +429,7 @@ of commands at once, and that is to add a <em>CmdSet</em> to the other cmdset. A
<span class="c1">#</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCmdSet</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Which way you use depends on how much control you want, but if you already have a CmdSet,
this is practical. A Command can be a part of any number of different CmdSets.</p>
<section id="removing-commands">
@ -544,22 +439,7 @@ this is practical. A Command can be a part of any number of different CmdSets.</
<p>We already know that we use <code class="docutils literal notranslate"><span class="pre">cmdset.remove()</span></code> to remove a cmdset. It turns out you can
do the same in <code class="docutils literal notranslate"><span class="pre">at_cmdset_creation</span></code>. For example, lets remove the default <code class="docutils literal notranslate"><span class="pre">get</span></code> Command
from Evennia. We happen to know this can be found as <code class="docutils literal notranslate"><span class="pre">default_cmds.CmdGet</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<span class="k">class</span> <span class="nc">CharacterCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</span><span class="p">):</span>
@ -576,10 +456,10 @@ from Evennia. We happen to know this can be found as <code class="docutils liter
<span class="bp">self</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdGet</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">get</span>
<span class="n">Command</span> <span class="s1">&#39;get&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">available</span> <span class="o">...</span>
</div>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; get
Command &#39;get&#39; is not available ...
</pre></div>
</div>
</section>
@ -591,15 +471,7 @@ command with the same <code class="docutils literal notranslate"><span class="pr
<p>Lets combine this with what we know about classes and
how to <em>override</em> a parent class. Open <code class="docutils literal notranslate"><span class="pre">mygame/commands/mycommands.py</span></code> and lets override
that <code class="docutils literal notranslate"><span class="pre">CmdGet</span></code> command.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># up top, by the other imports</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># up top, by the other imports</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
<span class="c1"># somewhere below</span>
@ -608,8 +480,9 @@ that <code class="docutils literal notranslate"><span class="pre">CmdGet</span><
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="o">.</span><span class="n">contents</span><span class="p">))</span>
</pre></div>
</td></tr></table></div>
</div>
<ul class="simple">
<li><p><strong>Line2</strong>: We import <code class="docutils literal notranslate"><span class="pre">default_cmds</span></code> so we can get the parent class.
We made a new class and we make it <em>inherit</em> <code class="docutils literal notranslate"><span class="pre">default_cmds.CmdGet</span></code>. We dont
@ -627,22 +500,7 @@ has a special function <code class="docutils literal notranslate"><span class="p
</ul>
<p>We now just have to add this so it replaces the default <code class="docutils literal notranslate"><span class="pre">get</span></code> command. Open
<code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdsets.py</span></code> again:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">mycommands</span>
<span class="k">class</span> <span class="nc">CharacterCmdSet</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CharacterCmdSet</span><span class="p">):</span>
@ -659,14 +517,16 @@ has a special function <code class="docutils literal notranslate"><span class="p
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">mycommands</span><span class="o">.</span><span class="n">MyCmdGet</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Another way</p>
<p>Instead of adding <cite>MyCmdGet</cite> explicitly in default_cmdset.py,
you could also add it to <cite>mycommands.MyCmdSet</cite> and let it be
added automatically for you.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Instead of adding `MyCmdGet` explicitly in default_cmdset.py,
you could also add it to `mycommands.MyCmdSet` and let it be
added automatically for you.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; reload
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; get
Get What?
[smaug, fluffy, YourName, ...]
@ -747,7 +607,7 @@ command on ourselves.</p>
<h3>Versions</h3>
<ul>
<li><a href="More-on-Commands.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,13 +49,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="starting-to-code-evennia">
<section class="tex2jax_ignore mathjax_ignore" id="starting-to-code-evennia">
<h1>Starting to code Evennia<a class="headerlink" href="#starting-to-code-evennia" title="Permalink to this headline"></a></h1>
<p>Time to dip our toe into some coding! Evennia is written and extended in <a class="reference external" href="https://python.org">Python</a>,
which is a mature and professional programming language that is very fast to work with.</p>
<p>That said, even though Python is widely considered easy to learn, we can only cover the most immediately
important aspects of Python in this series of starting tutorials. Hopefully we can get you started
but then youll need to continue learning from there. See our <a class="reference internal" href="../../../Links.html"><span class="doc">link section</span></a> for finding
but then youll need to continue learning from there. See our <a class="reference internal" href="../../../Links.html"><span class="doc std std-doc">link section</span></a> for finding
more reference material and dedicated Python tutorials.</p>
<blockquote>
<div><p>While this will be quite basic if you are an experienced developer, you may want to at least
@ -61,23 +63,25 @@ stay around for the first few sections where we cover how to run Python from ins
</div></blockquote>
<p>First, if you were quelling yourself to play the tutorial world, make sure to get your
superuser powers back:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">unquell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> unquell
</pre></div>
</div>
<section id="evennia-hello-world">
<h2>Evennia Hello world<a class="headerlink" href="#evennia-hello-world" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">py</span></code> Command (or <code class="docutils literal notranslate"><span class="pre">!</span></code>, which is an alias) allows you as a superuser to execute raw Python from in-
game. This is useful for quick testing. From the games input line, enter the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;Hello World!&quot;)
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Command input</p>
<p>The line with <cite>&gt;</cite> indicates input to enter in-game, while the lines below are the
expected return from that input.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The line with `&gt;` indicates input to enter in-game, while the lines below are the
expected return from that input.
</pre></div>
</div>
</aside>
<p>You will see</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; print(&quot;Hello world!&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; print(&quot;Hello world!&quot;)
Hello World!
</pre></div>
</div>
@ -95,24 +99,24 @@ button or even graphical element, the normal process is for the user to input co
text and get text back. As we saw above, a piece of text is called a <em>string</em> in Python and is enclosed in
either single- or double-quotes.</p>
<p>Strings can be added together:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;This is a &quot;</span> <span class="o">+</span> <span class="s2">&quot;breaking change.&quot;</span><span class="p">)</span>
<span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">breaking</span> <span class="n">change</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a &quot; + &quot;breaking change.&quot;)
This is a breaking change.
</pre></div>
</div>
<p>A string multiplied with a number will repeat that string as many times:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;|&quot;</span> <span class="o">+</span> <span class="s2">&quot;-&quot;</span> <span class="o">*</span> <span class="mi">40</span> <span class="o">+</span> <span class="s2">&quot;|&quot;</span><span class="p">)</span>
<span class="o">|----------------------------------------|</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|&quot; + &quot;-&quot; * 40 + &quot;|&quot;)
|----------------------------------------|
</pre></div>
</div>
<p>or</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;A&quot; + &quot;a&quot; * 5 + &quot;rgh!&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;A&quot; + &quot;a&quot; * 5 + &quot;rgh!&quot;)
Aaaaaargh!
</pre></div>
</div>
<p>While combining different strings is useful, even more powerful is the ability to modify the contents
of the string in-place. There are several ways to do this in Python and well show two of them here. The first
is to use the <code class="docutils literal notranslate"><span class="pre">.format</span></code> <em>method</em> of the string:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;good&quot;))
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;good&quot;))
This is a good idea!
</pre></div>
</div>
@ -130,12 +134,12 @@ is stand-alone in a python module, like <cite>print()</cite></p>
sits and can thus affect it in various ways. You access it with the period <code class="docutils literal notranslate"><span class="pre">.</span></code>. In this case, the
string has a resource <code class="docutils literal notranslate"><span class="pre">format(...)</span></code> that modifies it. More specifically, it replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> marker
inside the string with the value passed to the format. You can do so many times:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;bad&quot;))
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;bad&quot;))
This is a bad idea!
</pre></div>
</div>
<p>or</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is the {} and {} {} idea!&quot;.format(&quot;first&quot;, &quot;second&quot;, &quot;great&quot;))
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is the {} and {} {} idea!&quot;.format(&quot;first&quot;, &quot;second&quot;, &quot;great&quot;))
This is the first and second great idea!
</pre></div>
</div>
@ -147,23 +151,25 @@ little more about errors in the next section, for now just fix until it prints a
<p>Here we passed three comma-separated strings as <em>arguments</em> to the strings <code class="docutils literal notranslate"><span class="pre">format</span></code> method. These
replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> markers in the same order as they were given.</p>
<p>The input does not have to be strings either:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;STR: </span><span class="si">{}</span><span class="s2">, DEX: </span><span class="si">{}</span><span class="s2">, INT: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
<span class="n">STR</span><span class="p">:</span> <span class="mi">12</span><span class="p">,</span> <span class="n">DEX</span><span class="p">:</span> <span class="mi">14</span><span class="p">,</span> <span class="n">INT</span><span class="p">:</span> <span class="mi">8</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;STR: {}, DEX: {}, INT: {}&quot;.format(12, 14, 8))
STR: 12, DEX: 14, INT: 8
</pre></div>
</div>
<p>To separate two Python instructions on the same line, you use the semi-colon, <code class="docutils literal notranslate"><span class="pre">;</span></code>. Try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(&quot;This is {}!&quot;.format(a))
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(&quot;This is {}!&quot;.format(a))
This is awesome sauce!
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>MUD clients and semi-colon</p>
<p>Some MUD clients use the semi-colon <cite>;</cite> to split client-inputs
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Some MUD clients use the semi-colon `;` to split client-inputs
into separate sends. If so, the above will give an error. Most clients allow you to
run in verbatim mode or to remap to use some other separator than <cite>;</cite>. If you still have
trouble, just use the Evennia web client for now. In real Python code youll pretty much never use
the semi-colon.</p>
run in &#39;verbatim&#39; mode or to remap to use some other separator than `;`. If you still have
trouble, just use the Evennia web client for now. In real Python code you&#39;ll pretty much never use
the semi-colon.
</pre></div>
</div>
</div>
<p>What happened here was that we <em>assigned</em> the string <code class="docutils literal notranslate"><span class="pre">&quot;awesome</span> <span class="pre">sauce&quot;</span></code> to a <em>variable</em> we chose
to name <code class="docutils literal notranslate"><span class="pre">a</span></code>. In the next statement, Python remembered what <code class="docutils literal notranslate"><span class="pre">a</span></code> was and we passed that into <code class="docutils literal notranslate"><span class="pre">format()</span></code>
@ -171,8 +177,8 @@ to get the output. If you replaced the value of <code class="docutils literal no
instead.</p>
<p>Heres the stat-example again, moving the stats to variables (here we just set them, but in a real
game they may be changed over time, or modified by circumstance):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">stren</span><span class="p">,</span> <span class="n">dex</span><span class="p">,</span> <span class="n">intel</span> <span class="o">=</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">8</span> <span class="p">;</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;STR: </span><span class="si">{}</span><span class="s2">, DEX: </span><span class="si">{dex}</span><span class="s2">, INT: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">stren</span><span class="p">,</span> <span class="n">dex</span><span class="p">,</span> <span class="n">intel</span><span class="p">))</span>
<span class="n">STR</span><span class="p">:</span> <span class="mi">13</span><span class="p">,</span> <span class="n">DEX</span><span class="p">:</span> <span class="mi">14</span><span class="p">,</span> <span class="n">INT</span><span class="p">:</span> <span class="mi">8</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py stren, dex, intel = 13, 14, 8 ; print(&quot;STR: {}, DEX: {dex}, INT: {}&quot;.format(stren, dex, intel))
STR: 13, DEX: 14, INT: 8
</pre></div>
</div>
<p>The point is that even if the values of the stats change, the print() statement would not change - it just keeps
@ -180,30 +186,30 @@ pretty-printing whatever is given to it.</p>
<p>Using <code class="docutils literal notranslate"><span class="pre">.format()</span></code> is convenient (and there is a <a class="reference external" href="https://www.w3schools.com/python/ref_string_format.asp">lot more</a>
you can do with it). But the <em>f-string</em> can be even more convenient. An
f-string looks like a normal string … except there is an <code class="docutils literal notranslate"><span class="pre">f</span></code> front of it, like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="sa">f</span><span class="s2">&quot;this is now an f-string.&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>f&quot;this is now an f-string.&quot;
</pre></div>
</div>
<p>An f-string on its own is just like any other string. But lets redo the example we did before, using an f-string:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(f&quot;This is {a}!&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(f&quot;This is {a}!&quot;)
This is awesome sauce!
</pre></div>
</div>
<p>We could just insert that <code class="docutils literal notranslate"><span class="pre">a</span></code> variable directly into the f-string using <code class="docutils literal notranslate"><span class="pre">{a}</span></code>. Fewer parentheses to
remember and arguable easier to read as well.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">stren</span><span class="p">,</span> <span class="n">dex</span><span class="p">,</span> <span class="n">intel</span> <span class="o">=</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">8</span> <span class="p">;</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;STR: </span><span class="si">{</span><span class="n">stren</span><span class="si">}</span><span class="s2">, DEX: </span><span class="si">{</span><span class="n">dex</span><span class="si">}</span><span class="s2">, INT: </span><span class="si">{</span><span class="n">intel</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">STR</span><span class="p">:</span> <span class="mi">13</span><span class="p">,</span> <span class="n">DEX</span><span class="p">:</span> <span class="mi">14</span><span class="p">,</span> <span class="n">INT</span><span class="p">:</span> <span class="mi">8</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py stren, dex, intel = 13, 14, 8 ; print(f&quot;STR: {stren}, DEX: {dex}, INT: {intel}&quot;)
STR: 13, DEX: 14, INT: 8
</pre></div>
</div>
<p>We will be exploring more complex string concepts when we get to creating Commands and need to
parse and understand player input.</p>
<p>Python itself knows nothing about colored text, this is an Evennia thing. Evennia supports the
standard color schemes of traditional MUDs.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;|rThis is red text!|n This is normal color.&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|rThis is red text!|n This is normal color.&quot;)
</pre></div>
</div>
<p>Adding that <code class="docutils literal notranslate"><span class="pre">|r</span></code> at the start will turn our output bright red. <code class="docutils literal notranslate"><span class="pre">|R</span></code> will make it dark red. <code class="docutils literal notranslate"><span class="pre">|n</span></code>
gives the normal text color. You can also use RGB (Red-Green-Blue) values from 0-5 (Xterm256 colors):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;|043This is a blue-green color.|[530|003 This is dark blue text on orange background.&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|043This is a blue-green color.|[530|003 This is dark blue text on orange background.&quot;)
</pre></div>
</div>
<blockquote>
@ -226,19 +232,21 @@ structure should look:</p>
</pre></div>
</div>
<p>For now, only add one line to <code class="docutils literal notranslate"><span class="pre">test.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Python module</p>
<p>This is a text file with the <cite>.py</cite> file ending. A module
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>This is a text file with the `.py` file ending. A module
contains Python source code and from within Python one can
access its contents by importing it via its python-path.</p>
access its contents by importing it via its python-path.
</pre></div>
</div>
</aside>
<p>Dont forget to <em>save</em> the file. We just created our first Python <em>module</em>!
To use this in-game we have to <em>import</em> it. Try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="kn">import</span> <span class="nn">world.test</span>
<span class="n">Hello</span> <span class="n">World</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
Hello World
</pre></div>
</div>
<p>If you make some error (well cover how to handle errors below), fix the error in the module and
@ -252,7 +260,7 @@ path - Evennia handles this for us.</p>
<p>When you import the module, the top “level” of it will execute. In this case, it will immediately
print “Hello World”.</p>
<p>Now try to run this a second time:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="kn">import</span> <span class="nn">world.test</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
</pre></div>
</div>
<p>You will <em>not</em> see any output this second time or any subsequent times! This is not a bug. Rather
@ -260,11 +268,11 @@ it is because of how Python importing works - it stores all imported modules and
avoid importing them more than once. So your <code class="docutils literal notranslate"><span class="pre">print</span></code> will only run the first time, when the module
is first imported.</p>
<p>Try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
</pre></div>
</div>
<p>And then</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
Hello World!
</pre></div>
</div>
@ -275,16 +283,14 @@ not very useful.</p>
<div><p>Well get back to more advanced ways to import code in later tutorial sections - this is an
important topic. But for now, lets press on and resolve this particular problem.</p>
</div></blockquote>
</section>
<section id="our-first-own-function">
<h2>Our first own function<a class="headerlink" href="#our-first-own-function" title="Permalink to this headline"></a></h2>
<h3>Our first own function<a class="headerlink" href="#our-first-own-function" title="Permalink to this headline"></a></h3>
<p>We want to be able to print our hello-world message at any time, not just once after a server
reload. Change your <code class="docutils literal notranslate"><span class="pre">mygame/world/test.py</span></code> file to look like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>As we are moving to multi-line Python code, there are some important things to remember:</p>
<ul class="simple">
<li><p>Capitalization matters in Python. It must be <code class="docutils literal notranslate"><span class="pre">def</span></code> and not <code class="docutils literal notranslate"><span class="pre">DEF</span></code>, <code class="docutils literal notranslate"><span class="pre">who</span></code> is not the same as <code class="docutils literal notranslate"><span class="pre">Who</span></code>.</p></li>
@ -310,14 +316,14 @@ start at least at this indentation level.</p></li>
</ul>
<p>Now lets try this out. First <code class="docutils literal notranslate"><span class="pre">reload</span></code> your game to have it pick up
our updated Python module, then import it.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">reload</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="kn">import</span> <span class="nn">world.test</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py import world.test
</pre></div>
</div>
<p>Nothing happened! That is because the function in our module wont do anything just by importing it (this
is what we wanted). It will only act when we <em>call</em> it. So we need to first import the module and then access the
function within:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
Hello world!
</pre></div>
</div>
@ -328,19 +334,20 @@ own ends.</p>
accessed the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function <em>inside</em> the newly imported module.</p>
<p>By adding <code class="docutils literal notranslate"><span class="pre">()</span></code> to the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function we <em>call</em> it, that is we run the body of the function and
print our text. We can now redo this as many times as we want without having to <code class="docutils literal notranslate"><span class="pre">reload</span></code> in between:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
Hello world!
&gt; py import world.test ; world.test.hello_world()
Hello world!
</pre></div>
</div>
</section>
</section>
<section id="sending-text-to-others">
<h2>Sending text to others<a class="headerlink" href="#sending-text-to-others" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">print</span></code> command is a standard Python structure. We can use that here in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command since
we can se the output. Its great for debugging and quick testing. But if you need to send a text
to an actual player, <code class="docutils literal notranslate"><span class="pre">print</span></code> wont do, because it doesnt know <em>who</em> to send to. Try this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py me.msg(&quot;Hello world!&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.msg(&quot;Hello world!&quot;)
Hello world!
</pre></div>
</div>
@ -361,30 +368,29 @@ debugging and <code class="docutils literal notranslate"><span class="pre">.msg(
<h2>Parsing Python errors<a class="headerlink" href="#parsing-python-errors" title="Permalink to this headline"></a></h2>
<p>Lets try this new text-sending in the function we just created. Go back to
your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> file and Replace the function with this instead:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Save your file and <code class="docutils literal notranslate"><span class="pre">reload</span></code> your server to tell Evennia to re-import new code,
then run it like before:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">&gt;</span> <span class="n">py</span> <span class="kn">import</span> <span class="nn">world.test</span> <span class="p">;</span> <span class="n">world</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">hello_world</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; py import world.test ; world.test.hello_world()
</pre></div>
</div>
<p>No go - this time you get an error!</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">File</span> <span class="s2">&quot;./world/test.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">2</span><span class="p">,</span> <span class="ow">in</span> <span class="n">hello_world</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">File</span> <span class="s2">&quot;./world/test.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">2</span><span class="p">,</span> <span class="ow">in</span> <span class="n">hello_world</span>
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">&#39;me&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Errors in the logs</p>
<p>In regular use, tracebacks will often appear in the log rather than
in the game. Use <cite>evennia log</cite> to view the log in the terminal. Make
sure to scroll back if you expect an error and dont see it. Use
<cite>Ctrl-C</cite> (or <cite>Cmd-C</cite> on Mac) to exit the log-view.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>In regular use, tracebacks will often appear in the log rather than
in the game. Use `evennia --log` to view the log in the terminal. Make
sure to scroll back if you expect an error and don&#39;t see it. Use
`Ctrl-C` (or `Cmd-C` on Mac) to exit the log-view.
</pre></div>
</div>
</aside>
<p>This is called a <em>traceback</em>. Pythons errors are very friendly and will most of the time tell you
exactly what and where things go wrong. Its important that you learn to parse tracebacks so you
@ -411,15 +417,14 @@ Hence the <code class="docutils literal notranslate"><span class="pre">NameError
<p>We know that <code class="docutils literal notranslate"><span class="pre">me</span></code> exists at the point when we run the <code class="docutils literal notranslate"><span class="pre">py</span></code> command, because we can do <code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">me.msg(&quot;Hello</span> <span class="pre">World!&quot;)</span></code>
with no problem. So lets <em>pass</em> that me along to the function so it knows what it should be.
Go back to your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> and change it to this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>We now added an <em>argument</em> to the function. We could have named it anything. Whatever <code class="docutils literal notranslate"><span class="pre">who</span></code> is,
we will call a method <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> on it.</p>
<p>As usual, <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server to make sure the new code is available.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world(me)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world(me)
Hello World!
</pre></div>
</div>
@ -445,27 +450,29 @@ and the concept of <em>Leap before you Look</em>.</p>
object called the <code class="docutils literal notranslate"><span class="pre">TutorialMirror</span></code>. The mirror will echo whatever is being sent to it to
the room it is in.</p>
<p>On the game command-line, lets create a mirror:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">mirror</span><span class="p">:</span><span class="n">contrib</span><span class="o">.</span><span class="n">tutorial_examples</span><span class="o">.</span><span class="n">mirror</span><span class="o">.</span><span class="n">TutorialMirror</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create/drop mirror:contrib.tutorial_examples.mirror.TutorialMirror
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Creating objects</p>
<p>The <cite>create</cite> command was first used to create boxes in the
<a class="reference external" href="Building-Quickstart">Building Stuff</a> tutorial. Note how it
uses a “python-path” to describe where to load the mirrors code from.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>The `create` command was first used to create boxes in the
`Building Stuff &lt;Building-Quickstart&gt;`_ tutorial. Note how it
uses a &quot;python-path&quot; to describe where to load the mirror&#39;s code from.
</pre></div>
</div>
</aside>
<p>A mirror should appear in your location.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">look</span> <span class="n">mirror</span>
<span class="n">mirror</span> <span class="n">shows</span> <span class="n">your</span> <span class="n">reflection</span><span class="p">:</span>
<span class="n">This</span> <span class="ow">is</span> <span class="n">User</span> <span class="c1">#1</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; look mirror
mirror shows your reflection:
This is User #1
</pre></div>
</div>
<p>What you are seeing is actually your own avatar in the game, the same thing that is available as <code class="docutils literal notranslate"><span class="pre">me</span></code> in the <code class="docutils literal notranslate"><span class="pre">py</span></code>
command.</p>
<p>What we are aiming for now is the equivalent of <code class="docutils literal notranslate"><span class="pre">mirror.msg(&quot;Mirror</span> <span class="pre">Mirror</span> <span class="pre">on</span> <span class="pre">the</span> <span class="pre">wall&quot;)</span></code>. But the first thing that
comes to mind will not work:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">mirror</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Mirror, Mirror on the wall ...&quot;</span><span class="p">)</span>
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">&#39;mirror&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py mirror.msg(&quot;Mirror, Mirror on the wall ...&quot;)
NameError: name &#39;mirror&#39; is not defined.
</pre></div>
</div>
<p>This is not surprising: Python knows nothing about “mirrors” or locations or anything. The <code class="docutils literal notranslate"><span class="pre">me</span></code> weve been using
@ -473,29 +480,31 @@ is, as mentioned, just a convenient thing the Evennia devs makes available to th
predict that you wanted to talk to mirrors.</p>
<p>Instead we will need to <em>search</em> for that <code class="docutils literal notranslate"><span class="pre">mirror</span></code> object before we can send to it.
Make sure you are in the same location as the mirror and try:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">me</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;mirror&quot;</span><span class="p">)</span>
<span class="n">mirror</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.search(&quot;mirror&quot;)
mirror
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">me.search(&quot;name&quot;)</span></code> will, by default, search and <em>return</em> an object with the given name found in <em>the same location</em>
as the <code class="docutils literal notranslate"><span class="pre">me</span></code> object is. If it cant find anything youll see an error.</p>
<aside class="sidebar">
<p class="sidebar-title">Function returns</p>
<p>Whereas a function like <cite>print</cite> only prints its arguments, its very common
for functions/methods to <cite>return</cite> a result of some kind. Think of the function
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Whereas a function like `print` only prints its arguments, it&#39;s very common
for functions/methods to `return` a result of some kind. Think of the function
as a machine - you put something in and out comes a result you can use. In the case
of <cite>me.search</cite>, it will perform a database search and spit out the object it finds.</p>
of `me.search`, it will perform a database search and spit out the object it finds.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">me</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;dummy&quot;</span><span class="p">)</span>
<span class="n">Could</span> <span class="ow">not</span> <span class="n">find</span> <span class="s1">&#39;dummy&#39;</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.search(&quot;dummy&quot;)
Could not find &#39;dummy&#39;.
</pre></div>
</div>
<p>Wanting to find things in the same location is very common, but as we continue well
find that Evennia provides ample tools for tagging, searching and finding things from all over your game.</p>
<p>Now that we know how to find the mirror object, we just need to use that instead of <code class="docutils literal notranslate"><span class="pre">me</span></code>!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="n">mirror</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;mirror&quot;</span><span class="p">)</span> <span class="p">;</span> <span class="n">mirror</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Mirror, Mirror on the wall ...&quot;</span><span class="p">)</span>
<span class="n">mirror</span> <span class="n">echoes</span> <span class="n">back</span> <span class="n">to</span> <span class="n">you</span><span class="p">:</span>
<span class="s2">&quot;Mirror, Mirror on the wall ...&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py mirror = self.search(&quot;mirror&quot;) ; mirror.msg(&quot;Mirror, Mirror on the wall ...&quot;)
mirror echoes back to you:
&quot;Mirror, Mirror on the wall ...&quot;
</pre></div>
</div>
<p>The mirror is useful for testing because its <code class="docutils literal notranslate"><span class="pre">.msg</span></code> method just echoes whatever is sent to it back to the room. More common
@ -506,57 +515,57 @@ would be to talk to a player character, in which case the text you sent would ha
<p>So far we have use <code class="docutils literal notranslate"><span class="pre">py</span></code> in single-line mode, using <code class="docutils literal notranslate"><span class="pre">;</span></code> to separate multiple inputs. This is very convenient
when you want to do some quick testing. But you can also start a full multi-line Python interactive interpreter
inside Evennia.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span>
<span class="n">Evennia</span> <span class="n">Interactive</span> <span class="n">Python</span> <span class="n">mode</span>
<span class="n">Python</span> <span class="mf">3.7.1</span> <span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">Oct</span> <span class="mi">22</span> <span class="mi">2018</span><span class="p">,</span> <span class="mi">11</span><span class="p">:</span><span class="mi">21</span><span class="p">:</span><span class="mi">55</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">8.2.0</span><span class="p">]</span> <span class="n">on</span> <span class="n">Linux</span>
<span class="p">[</span><span class="n">py</span> <span class="n">mode</span> <span class="o">-</span> <span class="n">quit</span><span class="p">()</span> <span class="n">to</span> <span class="n">exit</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
Evennia Interactive Python mode
Python 3.7.1 (default, Oct 22 2018, 11:21:55)
[GCC 8.2.0] on Linux
[py mode - quit() to exit]
</pre></div>
</div>
<p>(the details of the output will vary with your Python version and OS). You are now in python interpreter mode. It means
that <em>everything</em> you insert from now on will become a line of Python (you can no longer look around or do other
commands).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; print(&quot;Hello World&quot;)
<span class="o">&gt;&gt;&gt;</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World&quot;</span><span class="p">)</span>
<span class="n">Hello</span> <span class="n">World</span>
<span class="p">[</span><span class="n">py</span> <span class="n">mode</span> <span class="o">-</span> <span class="n">quit</span><span class="p">()</span> <span class="n">to</span> <span class="n">exit</span><span class="p">]</span>
&gt;&gt;&gt; print(&quot;Hello World&quot;)
Hello World
[py mode - quit() to exit]
</pre></div>
</div>
<p>Note that we didnt need to put <code class="docutils literal notranslate"><span class="pre">py</span></code> in front now. The system will also echo your input (thats the bit after
the <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code>). For brevity in this tutorual well turn the echo off. First exit <code class="docutils literal notranslate"><span class="pre">py</span></code> and then start again with the
<code class="docutils literal notranslate"><span class="pre">/noecho</span></code> flag.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quit</span><span class="p">()</span>
<span class="n">Closing</span> <span class="n">the</span> <span class="n">Python</span> <span class="n">console</span><span class="o">.</span>
<span class="o">&gt;</span> <span class="n">py</span><span class="o">/</span><span class="n">noecho</span>
<span class="n">Evennia</span> <span class="n">Interactive</span> <span class="n">Python</span> <span class="n">mode</span> <span class="p">(</span><span class="n">no</span> <span class="n">echoing</span> <span class="n">of</span> <span class="n">prompts</span><span class="p">)</span>
<span class="n">Python</span> <span class="mf">3.7.1</span> <span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">Oct</span> <span class="mi">22</span> <span class="mi">2018</span><span class="p">,</span> <span class="mi">11</span><span class="p">:</span><span class="mi">21</span><span class="p">:</span><span class="mi">55</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">8.2.0</span><span class="p">]</span> <span class="n">on</span> <span class="n">Linux</span>
<span class="p">[</span><span class="n">py</span> <span class="n">mode</span> <span class="o">-</span> <span class="n">quit</span><span class="p">()</span> <span class="n">to</span> <span class="n">exit</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Closing the Python console.
&gt; py/noecho
Evennia Interactive Python mode (no echoing of prompts)
Python 3.7.1 (default, Oct 22 2018, 11:21:55)
[GCC 8.2.0] on Linux
[py mode - quit() to exit]
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">interactive py</p>
<ul class="simple">
<li><p>Start with <cite>py</cite>.</p></li>
<li><p>Use <cite>py/noecho</cite> if you dont want your input to be echoed for every line.</p></li>
<li><p>All your inputs will now be interpreted as Python code.</p></li>
<li><p>Exit with <cite>quit()</cite>.</p></li>
</ul>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- Start with `py`.
- Use `py/noecho` if you don&#39;t want your input to be echoed for every line.
- All your inputs will now be interpreted as Python code.
- Exit with `quit()`.
</pre></div>
</div>
</aside>
<p>We can now enter multi-line Python code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="s2">&quot;Test&quot;</span>
<span class="o">&gt;</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;This is a </span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">}</span>
<span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">Test</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; a = &quot;Test&quot;
&gt; print(f&quot;This is a {a}.&quot;}
This is a Test.
</pre></div>
</div>
<p>Lets try to define a function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">,</span> <span class="n">txt</span><span class="p">):</span>
<span class="o">...</span>
<span class="o">&gt;</span> <span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">txt</span><span class="p">)</span>
<span class="o">...</span>
<span class="o">&gt;</span>
<span class="p">[</span><span class="n">py</span> <span class="n">mode</span> <span class="o">-</span> <span class="n">quit</span><span class="p">()</span> <span class="n">to</span> <span class="n">exit</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; def hello_world(who, txt):
...
&gt; who.msg(txt)
...
&gt;
[py mode - quit() to exit]
</pre></div>
</div>
<p>Some important things above:</p>
@ -570,21 +579,21 @@ for Python to know its part of the function body.</p></li>
the normal prompt on how to exit returns, we know we are done.</p></li>
</ul>
<p>Now we have defined a new function. Lets try it out:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; hello_world(me, &quot;Hello world to me!&quot;)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hello_world(me, &quot;Hello world to me!&quot;)
Hello world to me!
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">me</span></code> is still available to us, so we pass that as the <code class="docutils literal notranslate"><span class="pre">who</span></code> argument, along with a little longer
string. Lets combine this with searching for the mirror.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">mirror</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;mirror&quot;</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">hello_world</span><span class="p">(</span><span class="n">mirror</span><span class="p">,</span> <span class="s2">&quot;Mirror, Mirror on the wall ...&quot;</span><span class="p">)</span>
<span class="n">mirror</span> <span class="n">echoes</span> <span class="n">back</span> <span class="n">to</span> <span class="n">you</span><span class="p">:</span>
<span class="s2">&quot;Mirror, Mirror on the wall ...&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; mirror = me.search(&quot;mirror&quot;)
&gt; hello_world(mirror, &quot;Mirror, Mirror on the wall ...&quot;)
mirror echoes back to you:
&quot;Mirror, Mirror on the wall ...&quot;
</pre></div>
</div>
<p>Exit the <code class="docutils literal notranslate"><span class="pre">py</span></code> mode with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quit</span><span class="p">()</span>
<span class="n">Closing</span> <span class="n">the</span> <span class="n">Python</span> <span class="n">console</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Closing the Python console.
</pre></div>
</div>
</section>
@ -601,8 +610,8 @@ is available).</p>
</ul>
<p>A Python shell opens. This works like <code class="docutils literal notranslate"><span class="pre">py</span></code> did inside the game, with the exception that you dont have
<code class="docutils literal notranslate"><span class="pre">me</span></code> available out of the box. If you want <code class="docutils literal notranslate"><span class="pre">me</span></code>, you need to first find yourself:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="o">&gt;</span> <span class="n">me</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="s2">&quot;YourChar&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; import evennia
&gt; me = evennia.search_object(&quot;YourChar&quot;)[0]
</pre></div>
</div>
<p>Here we make use of one of evennias search functions, available by importing <code class="docutils literal notranslate"><span class="pre">evennia</span></code> directly.
@ -613,29 +622,28 @@ We will cover more advanced searching later, but suffice to say, you put your ow
get at the first of them (counting starts from 0).</p>
</div></blockquote>
<p>Use <code class="docutils literal notranslate"><span class="pre">Ctrl-D</span></code> (<code class="docutils literal notranslate"><span class="pre">Cmd-D</span></code> on Mac) or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit the Python console.</p>
</section>
<section id="ipython">
<h3>ipython<a class="headerlink" href="#ipython" title="Permalink to this headline"></a></h3>
<h2>ipython<a class="headerlink" href="#ipython" title="Permalink to this headline"></a></h2>
<p>The default Python shell is quite limited and ugly. Its <em>highly</em> recommended to install <code class="docutils literal notranslate"><span class="pre">ipython</span></code> instead. This
is a much nicer, third-party Python interpreter with colors and many usability improvements.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">ipython</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>pip install ipython
</pre></div>
</div>
<p>If <code class="docutils literal notranslate"><span class="pre">ipython</span></code> is installed, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code> will use it automatically.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span> <span class="n">shell</span>
<span class="o">...</span>
<span class="n">IPython</span> <span class="mf">7.4.0</span> <span class="o">--</span> <span class="n">An</span> <span class="n">enhanced</span> <span class="n">Interactive</span> <span class="n">Python</span><span class="o">.</span> <span class="n">Type</span> <span class="s1">&#39;?&#39;</span> <span class="k">for</span> <span class="n">help</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
</pre></div>
</div>
<p>You now have Tab-completion:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="o">&gt;</span> <span class="n">evennia</span><span class="o">.&lt;</span><span class="n">TAB</span><span class="o">&gt;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia shell
...
IPython 7.4.0 -- An enhanced Interactive Python. Type &#39;?&#39; for help
In [1]: You now have Tab-completion:
&gt; import evennia
&gt; evennia.&lt;TAB&gt;
</pre></div>
</div>
<p>That is, enter <code class="docutils literal notranslate"><span class="pre">evennia.</span></code> and then press the TAB key - you will be given a list of all the resources
available on the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> object. This is great for exploring what Evennia has to offer. For example,
use your arrow keys to scroll to <code class="docutils literal notranslate"><span class="pre">search_object()</span></code> to fill it in.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; evennia.search_object?
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; evennia.search_object?
</pre></div>
</div>
<p>Adding a <code class="docutils literal notranslate"><span class="pre">?</span></code> and pressing return will give you the full documentation for <code class="docutils literal notranslate"><span class="pre">.search_object</span></code>. Use <code class="docutils literal notranslate"><span class="pre">??</span></code> if you
@ -644,21 +652,22 @@ want to see the entire source code.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>Persistent code</p>
<p>Common for both <cite>py</cite> and <cite>python</cite>/<cite>ipython</cite> is that the code you write is not persistent - it will
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Common for both `py` and `python`/`ipython` is that the code you write is not persistent - it will
be gone after you shut down the interpreter (but ipython will remember your input history). For making long-lasting
Python code, we need to save it in a Python module, like we did for <cite>world/test.py</cite>.</p>
Python code, we need to save it in a Python module, like we did for `world/test.py`.
</pre></div>
</div>
</div>
</section>
</section>
<section id="conclusions">
<h2>Conclusions<a class="headerlink" href="#conclusions" title="Permalink to this headline"></a></h2>
<section class="tex2jax_ignore mathjax_ignore" id="conclusions">
<h1>Conclusions<a class="headerlink" href="#conclusions" title="Permalink to this headline"></a></h1>
<p>This covers quite a lot of basic Python usage. We printed and formatted strings, defined our own
first function, fixed an error and even searched and talked to a mirror! Being able to access
python inside and outside of the game is an important skill for testing and debugging, but in
practice you will be writing most your code in Python modules.</p>
<p>To that end we also created a first new Python module in the <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> game dir, then imported and used it.
Now lets look at the rest of the stuff youve got going on inside that <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> folder …</p>
</section>
</section>
@ -686,20 +695,20 @@ Now lets look at the rest of the stuff youve got going on inside that <cod
<li><a class="reference internal" href="#">Starting to code Evennia</a><ul>
<li><a class="reference internal" href="#evennia-hello-world">Evennia Hello world</a></li>
<li><a class="reference internal" href="#making-some-text-graphics">Making some text graphics</a></li>
<li><a class="reference internal" href="#importing-code-from-other-modules">Importing code from other modules</a></li>
<li><a class="reference internal" href="#importing-code-from-other-modules">Importing code from other modules</a><ul>
<li><a class="reference internal" href="#our-first-own-function">Our first own function</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sending-text-to-others">Sending text to others</a></li>
<li><a class="reference internal" href="#parsing-python-errors">Parsing Python errors</a></li>
<li><a class="reference internal" href="#passing-arguments-to-functions">Passing arguments to functions</a></li>
<li><a class="reference internal" href="#finding-others-to-send-to">Finding others to send to</a></li>
<li><a class="reference internal" href="#multi-line-py">Multi-line py</a></li>
<li><a class="reference internal" href="#other-ways-to-test-python-code">Other ways to test Python code</a><ul>
<li><a class="reference internal" href="#other-ways-to-test-python-code">Other ways to test Python code</a></li>
<li><a class="reference internal" href="#ipython">ipython</a></li>
</ul>
</li>
<li><a class="reference internal" href="#conclusions">Conclusions</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
@ -728,7 +737,7 @@ Now lets look at the rest of the stuff youve got going on inside that <cod
<h3>Versions</h3>
<ul>
<li><a href="Python-basic-introduction.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,7 +49,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="python-classes-and-objects">
<section class="tex2jax_ignore mathjax_ignore" id="python-classes-and-objects">
<h1>Python Classes and objects<a class="headerlink" href="#python-classes-and-objects" title="Permalink to this headline"></a></h1>
<p>We have now learned how to run some simple Python code from inside (and outside) your game server.
We have also taken a look at what our game dir looks and what is where. Now well start to use it.</p>
@ -63,23 +65,23 @@ it much easier to find errors and to know what code is good and which has issues
and it will import and use it (often instead of its defaults).</p>
</div></blockquote>
<p>We have already successfully imported things, for example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world(me)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world(me)
Hello World!
</pre></div>
</div>
<p>In this example, on your hard drive, the files looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mygame</span><span class="o">/</span>
<span class="n">world</span><span class="o">/</span>
<span class="n">world</span><span class="o">/</span>
<span class="n">test</span><span class="o">.</span><span class="n">py</span> <span class="o">&lt;-</span> <span class="n">inside</span> <span class="n">this</span> <span class="n">file</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">function</span> <span class="n">hello_world</span>
</pre></div>
</div>
<p>If you followed earlier tutorial lessons, the <code class="docutils literal notranslate"><span class="pre">mygame/world/test.py</span></code> file should look like this (if
not, make it so):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Remember:</p>
<ul class="simple">
@ -94,43 +96,43 @@ not, make it so):</p>
Python <em>modules</em> (that is, files ending with .py). A python-path separates each part of the
path <code class="docutils literal notranslate"><span class="pre">.</span></code> and always skips the <code class="docutils literal notranslate"><span class="pre">.py</span></code> file endings. Also, Evennia already knows to start looking
for python resources inside <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> so this should never be specified. Hence</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">world.test</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>import world.test
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">import</span></code> Python instruction loads <code class="docutils literal notranslate"><span class="pre">world.test</span></code> so you have it available. You can now go “into”
this module to get to the function you want:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">world</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">hello_world</span><span class="p">(</span><span class="n">me</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>world.test.hello_world(me)
</pre></div>
</div>
<p>Using <code class="docutils literal notranslate"><span class="pre">import</span></code> like this means that you have to specify the full <code class="docutils literal notranslate"><span class="pre">world.test</span></code> every time you want
to get to your function. Heres a more powerful form of import:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">world.test</span> <span class="kn">import</span> <span class="n">hello_world</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from world.test import hello_world
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span> <span class="pre">...</span></code> is very, very common as long as you want to get something with a longer
python path. It imports <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> directly, so you can use it right away!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> &gt; py from world.test import hello_world ; hello_world(me)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; py from world.test import hello_world ; hello_world(me)
Hello World!
</pre></div>
</div>
<p>Lets say your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> module had a bunch of interesting functions. You could then import them
all one by one:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">world.test</span> <span class="kn">import</span> <span class="n">hello_world</span><span class="p">,</span> <span class="n">my_func</span><span class="p">,</span> <span class="n">awesome_func</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from world.test import hello_world, my_func, awesome_func
</pre></div>
</div>
<p>If there were <em>a lot</em> of functions, you could instead just import <code class="docutils literal notranslate"><span class="pre">test</span></code> and get the function
from there when you need (without having to give the full <code class="docutils literal notranslate"><span class="pre">world.test</span></code> every time):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; from world import test ; test.hello_world(me
Hello World!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; from world import test ; test.hello_world(me
Hello World!
</pre></div>
</div>
<p>You can also <em>rename</em> stuff you import. Say for example that the module you import to already
has a function <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> but we also want to use the one from <code class="docutils literal notranslate"><span class="pre">world/test.py</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">world.test</span> <span class="kn">import</span> <span class="n">hello_world</span> <span class="k">as</span> <span class="n">test_hello_world</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>from world.test import hello_world as test_hello_world
</pre></div>
</div>
<p>The form <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span> <span class="pre">...</span> <span class="pre">as</span> <span class="pre">...</span></code> renames the import.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; from world.test import hello_world as hw ; hw(me)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; from world.test import hello_world as hw ; hw(me)
Hello World!
</pre></div>
</div>
@ -138,17 +140,17 @@ Hello World!
<div><p>Avoid renaming unless its to avoid a name-collistion like above - you want to make things as
easy to read as possible, and renaming adds another layer of potential confusion.</p>
</div></blockquote>
<p>In <a class="reference internal" href="Python-basic-introduction.html"><span class="doc">the basic intro to Python</span></a> we learned how to open the in-game
<p>In <a class="reference internal" href="Python-basic-introduction.html"><span class="doc std std-doc">the basic intro to Python</span></a> we learned how to open the in-game
multi-line interpreter.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span>
<span class="n">Evennia</span> <span class="n">Interactive</span> <span class="n">Python</span> <span class="n">mode</span>
<span class="n">Python</span> <span class="mf">3.7.1</span> <span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">Oct</span> <span class="mi">22</span> <span class="mi">2018</span><span class="p">,</span> <span class="mi">11</span><span class="p">:</span><span class="mi">21</span><span class="p">:</span><span class="mi">55</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">8.2.0</span><span class="p">]</span> <span class="n">on</span> <span class="n">Linux</span>
<span class="p">[</span><span class="n">py</span> <span class="n">mode</span> <span class="o">-</span> <span class="n">quit</span><span class="p">()</span> <span class="n">to</span> <span class="n">exit</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
Evennia Interactive Python mode
Python 3.7.1 (default, Oct 22 2018, 11:21:55)
[GCC 8.2.0] on Linux
[py mode - quit() to exit]
</pre></div>
</div>
<p>You now only need to import once to use the imported function over and over.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; from world.test import hello_world
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; from world.test import hello_world
&gt; hello_world()
Hello World!
&gt; hello_world()
@ -166,16 +168,7 @@ imports at the top, resources that are then used by all code in that module.</p>
<h2>On classes and objects<a class="headerlink" href="#on-classes-and-objects" title="Permalink to this headline"></a></h2>
<p>Now that we know about imports, let look at a real Evennia module and try to understand it.</p>
<p>Open <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/objects.py</span></code> in your text editor of choice.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">module docstring</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultObject</span>
@ -186,12 +179,14 @@ imports at the top, resources that are then used by all code in that module.</p>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
</pre></div>
</td></tr></table></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Docstrings vs Comments</p>
<p>A docstring is not the same as a comment (created by <cite>#</cite>). A
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>A docstring is not the same as a comment (created by `#`). A
docstring is not ignored by Python but is an integral part of the thing
it is documenting (the module and the class in this case).</p>
it is documenting (the module and the class in this case).
</pre></div>
</div>
</aside>
<p>The real file is much longer but we can ignore the multi-line strings (<code class="docutils literal notranslate"><span class="pre">&quot;&quot;&quot;</span> <span class="pre">...</span> <span class="pre">&quot;&quot;&quot;</span></code>). These serve
as documentation-strings, or <em>docstrings</em> for the module (at the top) and the <code class="docutils literal notranslate"><span class="pre">class</span></code> below.</p>
@ -201,13 +196,15 @@ as a black box.</p>
<p>Next we have a <code class="docutils literal notranslate"><span class="pre">class</span></code> named <code class="docutils literal notranslate"><span class="pre">Object</span></code>, which <em>inherits</em> from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>. This class doesnt
actually do anything on its own, its only code (except the docstring) is <code class="docutils literal notranslate"><span class="pre">pass</span></code> which means,
well, to pass and dont do anything.</p>
<p>We will get back to this module in the <a class="reference internal" href="Learning-Typeclasses.html"><span class="doc">next lesson</span></a>. First we need to do a
<p>We will get back to this module in the <a class="reference internal" href="Learning-Typeclasses.html"><span class="doc std std-doc">next lesson</span></a>. First we need to do a
little detour to understand what a class, an object or instance is. These are fundamental
things to understand before you can use Evennia efficiently.</p>
<aside class="sidebar">
<p class="sidebar-title">OOP</p>
<p>Classes, objects, instances and inheritance are fundamental to Python. This and some
other concepts are often clumped together under the term Object-Oriented-Programming (OOP).</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Classes, objects, instances and inheritance are fundamental to Python. This and some
other concepts are often clumped together under the term Object-Oriented-Programming (OOP).
</pre></div>
</div>
</aside>
<section id="classes-and-instances">
<h3>Classes and instances<a class="headerlink" href="#classes-and-instances" title="Permalink to this headline"></a></h3>
@ -215,21 +212,16 @@ other concepts are often clumped together under the term Object-Oriented-Program
of everyone of that class. For example, we could have a class <code class="docutils literal notranslate"><span class="pre">Monster</span></code> which has resources for moving itself
from room to room.</p>
<p>Open a new file <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/monsters.py</span></code>. Add the following simple class:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Monster</span><span class="p">:</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Monster&quot;</span>
<span class="k">def</span> <span class="nf">move_around</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> is moving!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Above we have defined a <code class="docutils literal notranslate"><span class="pre">Monster</span></code> class with one variable <code class="docutils literal notranslate"><span class="pre">key</span></code> (that is, the name) and one
<em>method</em> on it. A method is like a function except it sits “on” the class. It also always has
at least one argument (almost always written as <code class="docutils literal notranslate"><span class="pre">self</span></code> although you could in principle use
@ -245,11 +237,11 @@ back to the <code class="docutils literal notranslate"><span class="pre">key</sp
<p>A class is just a template. Before it can be used, we must create an <em>instance</em> of the class. If
<code class="docutils literal notranslate"><span class="pre">Monster</span></code> is a class, then an instance is Fluffy, the individual red dragon. You instantiate
by <em>calling</em> the class, much like you would a function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">fluffy</span> <span class="o">=</span> <span class="n">Monster</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>fluffy = Monster()
</pre></div>
</div>
<p>Lets try it in-game (we use multi-line mode, its easier)</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Monster
&gt; fluffy = Monster()
&gt; fluffy.move_around()
@ -264,78 +256,73 @@ there when defining the method, we <em>never</em> add it explicitly when we call
will add the correct <code class="docutils literal notranslate"><span class="pre">self</span></code> for us automatically behind the scenes).</p>
</div></blockquote>
<p>Lets create the sibling of Fluffy, Cuddly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; cuddly = Monster()
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; cuddly = Monster()
&gt; cuddly.move_around()
Monster is moving!
Monster is moving!
</pre></div>
</div>
<p>We now have two dragons and theyll hang around until with call <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit this Python
instance. We can have them move as many times as we want. But no matter how many dragons we
create, they will all show the same printout since <code class="docutils literal notranslate"><span class="pre">key</span></code> is always fixed as “Monster”.</p>
<p>Lets make the class a little more flexible:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Monster</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="k">def</span> <span class="nf">move_around</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> is moving!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">__init__</span></code> is a special method that Python recognizes. If given, this handles extra arguments
when you instantiate a new Monster. We have it add an argument <code class="docutils literal notranslate"><span class="pre">key</span></code> that we store on <code class="docutils literal notranslate"><span class="pre">self</span></code>.</p>
<p>Now, for Evennia to see this code change, we need to reload the server. You can either do it this
way:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">quit</span><span class="p">()</span>
<span class="n">Python</span> <span class="n">Console</span> <span class="ow">is</span> <span class="n">closing</span><span class="o">.</span>
<span class="o">&gt;</span> <span class="n">reload</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Python Console is closing.
&gt; reload
</pre></div>
</div>
<p>Or you can use a separate terminal and restart from outside the game:</p>
<aside class="sidebar">
<p class="sidebar-title">On reloading</p>
<p>Reloading with the python mode gets a little annoying since you need to redo everything
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Reloading with the python mode gets a little annoying since you need to redo everything
after every reload. Just keep in mind that during regular development you will not be
working this way. The in-game python mode is practical for quick fixes and experiments like
this, but actual code is normally written externally, in python modules.</p>
this, but actual code is normally written externally, in python modules.
</pre></div>
</div>
</aside>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ evennia reload (or restart)
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ evennia reload (or restart)
</pre></div>
</div>
<p>Either way youll need to go into <code class="docutils literal notranslate"><span class="pre">py</span></code> again:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Monster
fluffy = Monster(&quot;Fluffy&quot;)
fluffy.move_around()
Fluffy is moving!
Fluffy is moving!
</pre></div>
</div>
<p>Now we passed <code class="docutils literal notranslate"><span class="pre">&quot;Fluffy&quot;</span></code> as an argument to the class. This went into <code class="docutils literal notranslate"><span class="pre">__init__</span></code> and set <code class="docutils literal notranslate"><span class="pre">self.key</span></code>, which we
later used to print with the right name! Again, note that we didnt include <code class="docutils literal notranslate"><span class="pre">self</span></code> when calling.</p>
</section>
<section id="what-s-so-good-about-objects">
<h3>Whats so good about objects?<a class="headerlink" href="#what-s-so-good-about-objects" title="Permalink to this headline"></a></h3>
<section id="whats-so-good-about-objects">
<h3>Whats so good about objects?<a class="headerlink" href="#whats-so-good-about-objects" title="Permalink to this headline"></a></h3>
<p>So far all weve seen a class do is to behave our first <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function but more complex. We
could just have made a function:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">monster_move_around</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">key</span><span class="si">}</span><span class="s2"> is moving!&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">def</span> <span class="nf">monster_move_around</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">key</span><span class="si">}</span><span class="s2"> is moving!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The difference between the function and an instance of a class (the object), is that the
object retains <em>state</em>. Once you called the function it forgets everything about what you called
it with last time. The object, on the other hand, remembers changes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; fluffy.key = &quot;Cuddly&quot;
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; fluffy.key = &quot;Cuddly&quot;
&gt; fluffy.move_around()
Cuddly is moving!
Cuddly is moving!
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">fluffy</span></code> objects <code class="docutils literal notranslate"><span class="pre">key</span></code> was changed to “Cuddly” for as long as its around. This makes objects
@ -357,39 +344,14 @@ objects in turn:</p>
<p>Classes can <em>inherit</em> from each other. A “child” class will inherit everything from its “parent” class. But if
the child adds something with the same name as its parent, it will <em>override</em> whatever it got from its parent.</p>
<p>Lets expand <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/monsters.py</span></code> with another class:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
<span class="k">class</span> <span class="nc">Monster</span><span class="p">:</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This is a base class for Monster.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="k">def</span> <span class="nf">move_around</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> is moving!&quot;</span><span class="p">)</span>
@ -404,30 +366,33 @@ the child adds something with the same name as its parent, it will <em>override<
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> flies through the air high above!&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">firebreath</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot; </span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Let our dragon breathe fire.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> breathes fire!&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>We added some docstrings for clarity. Its always a good idea to add doc strings; you can do so also for methods,
as exemplified for the new <code class="docutils literal notranslate"><span class="pre">firebreath</span></code> method.</p>
<p>We created the new class <code class="docutils literal notranslate"><span class="pre">Dragon</span></code> but we also specified that <code class="docutils literal notranslate"><span class="pre">Monster</span></code> is the <em>parent</em> of <code class="docutils literal notranslate"><span class="pre">Dragon</span></code> but adding
the parent in parenthesis. <code class="docutils literal notranslate"><span class="pre">class</span> <span class="pre">Classname(Parent)</span></code> is the way to do this.</p>
<aside class="sidebar">
<p class="sidebar-title">Multi-inheritance</p>
<p>Its possible to add more comma-separated parents to a class. You should usually avoid
this until you <cite>really</cite> know what you are doing. A single parent will be enough for almost
every case youll need.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>It&#39;s possible to add more comma-separated parents to a class. You should usually avoid
this until you `really` know what you are doing. A single parent will be enough for almost
every case you&#39;ll need.
</pre></div>
</div>
</aside>
<p>Lets try out our new class. First <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server and the do</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Dragon
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Dragon
&gt; smaug = Dragon(&quot;Smaug&quot;)
&gt; smaug.move_around()
Smaug flies through the air high above!
&gt; smaug.firebreath()
Smaug breathes fire!
Smaug breathes fire!
</pre></div>
</div>
<p>Because we didnt implement <code class="docutils literal notranslate"><span class="pre">__init__</span></code> in <code class="docutils literal notranslate"><span class="pre">Dragon</span></code>, we got the one from <code class="docutils literal notranslate"><span class="pre">Monster</span></code> instead. But since we
@ -436,33 +401,25 @@ available for <code class="docutils literal notranslate"><span class="pre">Drago
can breathe fire.</p>
<p>One can also force a class to use resources from the parent even if you are overriding some of it. This is done
with the <code class="docutils literal notranslate"><span class="pre">super()</span></code> method. Modify your <code class="docutils literal notranslate"><span class="pre">Dragon</span></code> class as follows:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># ... </span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># ...</span>
<span class="k">class</span> <span class="nc">Dragon</span><span class="p">(</span><span class="n">Monster</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">move_around</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">move_around</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;The world trembles.&quot;</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</td></tr></table></div>
</div>
<blockquote>
<div><p>Keep <code class="docutils literal notranslate"><span class="pre">Monster</span></code> and the <code class="docutils literal notranslate"><span class="pre">firebreath</span></code> method, <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">...</span></code> indicates the rest of the code is untouched.</p>
</div></blockquote>
<p>The <code class="docutils literal notranslate"><span class="pre">super().move_around()</span></code> line means that we are calling <code class="docutils literal notranslate"><span class="pre">move_around()</span></code> on the parent of the class. So in this
case, we will call <code class="docutils literal notranslate"><span class="pre">Monster.move_around</span></code> first, before doing our own thing.</p>
<p>Now <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server and then:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Dragon
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
&gt; from typeclasses.monsters import Dragon
&gt; smaug = Dragon(&quot;Smaug&quot;)
&gt; smaug.move_around()
Smaug is moving!
@ -511,7 +468,7 @@ provides. But first we need to learn just where to find everything.</p>
<li><a class="reference internal" href="#importing-things">Importing things</a></li>
<li><a class="reference internal" href="#on-classes-and-objects">On classes and objects</a><ul>
<li><a class="reference internal" href="#classes-and-instances">Classes and instances</a></li>
<li><a class="reference internal" href="#what-s-so-good-about-objects">Whats so good about objects?</a></li>
<li><a class="reference internal" href="#whats-so-good-about-objects">Whats so good about objects?</a></li>
<li><a class="reference internal" href="#classes-can-have-children">Classes can have children</a></li>
</ul>
</li>
@ -546,7 +503,7 @@ provides. But first we need to learn just where to find everything.</p>
<h3>Versions</h3>
<ul>
<li><a href="Python-classes-and-objects.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,49 +49,51 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="searching-for-things">
<section class="tex2jax_ignore mathjax_ignore" id="searching-for-things">
<h1>Searching for things<a class="headerlink" href="#searching-for-things" title="Permalink to this headline"></a></h1>
<p>We have gone through how to create the various entities in Evennia. But creating something is of little use
if we cannot find and use it afterwards.</p>
<section id="main-search-functions">
<h2>Main search functions<a class="headerlink" href="#main-search-functions" title="Permalink to this headline"></a></h2>
<p>The base tools are the <code class="docutils literal notranslate"><span class="pre">evennia.search_*</span></code> functions, such as <code class="docutils literal notranslate"><span class="pre">evennia.search_object</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">rose</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
<span class="n">acct</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_account</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;MyAccountName&quot;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s2">&quot;foo@bar.com&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> rose = evennia.search_object(key=&quot;rose&quot;)
acct = evennia.search_account(key=&quot;MyAccountName&quot;, email=&quot;foo@bar.com&quot;)
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Querysets</p>
<p>What is returned from the main search functions is actually a <cite>queryset</cite>. They can be
treated like lists except that they cant modified in-place. Well discuss querysets in
the <cite>next lesson</cite> &lt;Django-queries&gt;`_.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>What is returned from the main search functions is actually a `queryset`. They can be
treated like lists except that they can&#39;t modified in-place. We&#39;ll discuss querysets in
the `next lesson` &lt;Django-queries&gt;`_.
</pre></div>
</div>
</aside>
<p>Strings are always case-insensitive, so searching for <code class="docutils literal notranslate"><span class="pre">&quot;rose&quot;</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;Rose&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">&quot;rOsE&quot;</span></code> give the same results.
Its important to remember that what is returned from these search methods is a <em>listing</em> of 0, one or more
elements - all the matches to your search. To get the first match:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rose</span> <span class="o">=</span> <span class="n">rose</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>rose = rose[0]
</pre></div>
</div>
<p>Often you really want all matches to the search parameters you specify. In other situations, having zero or
more than one match is a sign of a problem and you need to handle this case yourself.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">the_one_ring</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="s2">&quot;The one Ring&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">the_one_ring</span><span class="p">:</span>
<span class="c1"># handle not finding the ring at all</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">the_one_ring</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1"># handle finding more than one ring</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># ok - exactly one ring found</span>
<span class="n">the_one_ring</span> <span class="o">=</span> <span class="n">the_one_ring</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>the_one_ring = evennia.search_object(key=&quot;The one Ring&quot;)
if not the_one_ring:
# handle not finding the ring at all
elif len(the_one_ring) &gt; 1:
# handle finding more than one ring
else:
# ok - exactly one ring found
the_one_ring = the_one_ring[0]
</pre></div>
</div>
<p>There are equivalent search functions for all the main resources. You can find a listing of them
<a class="reference internal" href="../../../Evennia-API.html"><span class="doc">in the Search functions section</span></a> of the API frontpage.</p>
<a class="reference internal" href="../../../Evennia-API.html"><span class="doc std std-doc">in the Search functions section</span></a> of the API frontpage.</p>
</section>
<section id="searching-using-object-search">
<h2>Searching using Object.search<a class="headerlink" href="#searching-using-object-search" title="Permalink to this headline"></a></h2>
<p>On the <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> is a <code class="docutils literal notranslate"><span class="pre">.search</span></code> method which we have already tried out when we made Commands. For
this to be used you must already have an object available:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rose</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>rose = obj.search(&quot;rose&quot;)
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">.search</span></code> method wraps <code class="docutils literal notranslate"><span class="pre">evennia.search_object</span></code> and handles its output in various ways.</p>
@ -100,17 +104,7 @@ things in objs inventory or in the same room).</p></li>
<li><p>On a no-match or multimatch, <code class="docutils literal notranslate"><span class="pre">.search</span></code> will automatically send an error message to <code class="docutils literal notranslate"><span class="pre">obj</span></code>.</p></li>
</ul>
<p>So this method handles error messaging for you. A very common way to use it is in commands:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
<span class="k">class</span> <span class="nc">MyCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
@ -122,26 +116,26 @@ things in objs inventory or in the same room).</p></li>
<span class="k">if</span> <span class="ow">not</span> <span class="n">foo</span><span class="p">:</span>
<span class="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Remember, <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> is the one calling the command. This is usually a Character, which
inherits from <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>! This (rather stupid) Command searches for an object named “foo” in
the same location. If it cant find it, <code class="docutils literal notranslate"><span class="pre">foo</span></code> will be <code class="docutils literal notranslate"><span class="pre">None</span></code>. The error has already been reported
to <code class="docutils literal notranslate"><span class="pre">self.caller</span></code> so we just abort with <code class="docutils literal notranslate"><span class="pre">return</span></code>.</p>
<p>You can use <code class="docutils literal notranslate"><span class="pre">.search</span></code> to find anything, not just stuff in the same room:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">volcano</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;Volcano&quot;</span><span class="p">,</span> <span class="k">global</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>volcano = self.caller.search(&quot;Volcano&quot;, global=True)
</pre></div>
</div>
<p>If you only want to search for a specific list of things, you can do so too:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">stone</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;MyStone&quot;</span><span class="p">,</span> <span class="n">candidates</span><span class="o">=</span><span class="p">[</span><span class="n">obj1</span><span class="p">,</span> <span class="n">obj2</span><span class="p">,</span> <span class="n">obj3</span><span class="p">,</span> <span class="n">obj4</span><span class="p">])</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>stone = self.caller.search(&quot;MyStone&quot;, candidates=[obj1, obj2, obj3, obj4])
</pre></div>
</div>
<p>This will only return a match if MyStone is one of the four provided candidate objects. This is quite powerful,
heres how youd find something only in your inventory:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">potion</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;Healing potion&quot;</span><span class="p">,</span> <span class="n">candidates</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>potion = self.caller.search(&quot;Healing potion&quot;, candidates=self.caller.contents)
</pre></div>
</div>
<p>You can also turn off the automatic error handling:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">swords</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;Sword&quot;</span><span class="p">,</span> <span class="n">quiet</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>swords = self.caller.search(&quot;Sword&quot;, quiet=True)
</pre></div>
</div>
<p>With <code class="docutils literal notranslate"><span class="pre">quiet=True</span></code> the user will not be notified on zero or multi-match errors. Instead you are expected to handle this
@ -151,12 +145,12 @@ yourself and what you get back is now a list of zero, one or more matches!</p>
<h2>What can be searched for<a class="headerlink" href="#what-can-be-searched-for" title="Permalink to this headline"></a></h2>
<p>These are the main database entities one can search for:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../../../Components/Objects.html"><span class="doc">Objects</span></a></p></li>
<li><p><a class="reference internal" href="../../../Components/Accounts.html"><span class="doc">Accounts</span></a></p></li>
<li><p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Scripts</span></a>,</p></li>
<li><p><a class="reference external" href="Components/Communications.html#channels">Channels</a>,</p></li>
<li><p><a class="reference external" href="Howto/Starting/Part1/Communication#Msg">Messages</a></p></li>
<li><p><a class="reference internal" href="../../../Components/Help-System.html"><span class="doc">Help Entries</span></a>.</p></li>
<li><p><a class="reference internal" href="../../../Components/Objects.html"><span class="doc std std-doc">Objects</span></a></p></li>
<li><p><a class="reference internal" href="../../../Components/Accounts.html"><span class="doc std std-doc">Accounts</span></a></p></li>
<li><p><a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a>,</p></li>
<li><p><a class="reference internal" href="../../../Components/Channels.html"><span class="doc std std-doc">Channels</span></a>,</p></li>
<li><p><a class="reference internal" href="../../../Components/Msg.html"><span class="doc std std-doc">Messages</span></a></p></li>
<li><p><a class="reference internal" href="../../../Components/Help-System.html"><span class="doc std std-doc">Help Entries</span></a>.</p></li>
</ul>
<p>Most of the time youll likely spend your time searching for Objects and the occasional Accounts.</p>
<p>So to find an entity, what can be searched for?</p>
@ -168,7 +162,7 @@ yourself and what you get back is now a list of zero, one or more matches!</p>
<h3>Search by aliases<a class="headerlink" href="#search-by-aliases" title="Permalink to this headline"></a></h3>
<p>Objects and Accounts can have any number of aliases. When searching for <code class="docutils literal notranslate"><span class="pre">key</span></code> these will searched too,
you cant easily search only for aliases.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rose</span><span class="o">.</span><span class="n">aliases</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;flower&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>rose.aliases.add(&quot;flower&quot;)
</pre></div>
</div>
<p>If the above <code class="docutils literal notranslate"><span class="pre">rose</span></code> has a <code class="docutils literal notranslate"><span class="pre">key</span></code> <code class="docutils literal notranslate"><span class="pre">&quot;Rose&quot;</span></code>, it can now also be found by searching for <code class="docutils literal notranslate"><span class="pre">flower</span></code>. In-game
@ -179,55 +173,55 @@ you can assign new aliases to things with the <code class="docutils literal notr
<p>Only Objects (things inheriting from <code class="docutils literal notranslate"><span class="pre">evennia.DefaultObject</span></code>) has a location. This is usually a room.
The <code class="docutils literal notranslate"><span class="pre">Object.search</span></code> method will automatically limit it search by location, but it also works for the
general search function. If we assume <code class="docutils literal notranslate"><span class="pre">room</span></code> is a particular Room instance,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">chest</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="s2">&quot;Treasure chest&quot;</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="n">room</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>chest = evennia.search_object(&quot;Treasure chest&quot;, location=room)
</pre></div>
</div>
</section>
<section id="search-by-tags">
<h3>Search by Tags<a class="headerlink" href="#search-by-tags" title="Permalink to this headline"></a></h3>
<p>Think of a <a class="reference internal" href="../../../Components/Tags.html"><span class="doc">Tag</span></a> as the label the airport puts on your luggage when flying.
<p>Think of a <a class="reference internal" href="../../../Components/Tags.html"><span class="doc std std-doc">Tag</span></a> as the label the airport puts on your luggage when flying.
Everyone going on the same plane gets a tag grouping them together so the airport can know what should
go to which plane. Entities in Evennia can be grouped in the same way. Any number of tags can be attached
to each object.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rose</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;flowers&quot;</span><span class="p">)</span>
<span class="n">daffodil</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;flowers&quot;</span><span class="p">)</span>
<span class="n">tulip</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;flowers&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>rose.tags.add(&quot;flowers&quot;)
daffodil.tags.add(&quot;flowers&quot;)
tulip.tags.add(&quot;flowers&quot;)
</pre></div>
</div>
<p>You can now find all flowers using the <code class="docutils literal notranslate"><span class="pre">search_tag</span></code> function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_flowers</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="s2">&quot;flowers&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_flowers = evennia.search_tag(&quot;flowers&quot;)
</pre></div>
</div>
<p>Tags can also have categories. By default this category is <code class="docutils literal notranslate"><span class="pre">None</span></code> which is also considered a category.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">silmarillion</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;fantasy&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;books&quot;</span><span class="p">)</span>
<span class="n">ice_and_fire</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;fantasy&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;books&quot;</span><span class="p">)</span>
<span class="n">mona_lisa_overdrive</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;cyberpunk&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;books&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>silmarillion.tags.add(&quot;fantasy&quot;, category=&quot;books&quot;)
ice_and_fire.tags.add(&quot;fantasy&quot;, category=&quot;books&quot;)
mona_lisa_overdrive.tags.add(&quot;cyberpunk&quot;, category=&quot;books&quot;)
</pre></div>
</div>
<p>Note that if you specify the tag you <em>must</em> also include its category, otherwise that category
will be <code class="docutils literal notranslate"><span class="pre">None</span></code> and find no matches.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_fantasy_books</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="s2">&quot;fantasy&quot;</span><span class="p">)</span> <span class="c1"># no matches! </span>
<span class="n">all_fantasy_books</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="s2">&quot;fantasy&quot;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">&quot;books&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_fantasy_books = evennia.search_tag(&quot;fantasy&quot;) # no matches!
all_fantasy_books = evennia.search_tag(&quot;fantasy&quot;, category=&quot;books&quot;)
</pre></div>
</div>
<p>Only the second line above returns the two fantasy books. If we specify a category however,
we can get all tagged entities within that category:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_books</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_tag</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">&quot;books&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_books = evennia.search_tag(category=&quot;books&quot;)
</pre></div>
</div>
<p>This gets all three books.</p>
</section>
<section id="search-by-attribute">
<h3>Search by Attribute<a class="headerlink" href="#search-by-attribute" title="Permalink to this headline"></a></h3>
<p>We can also search by the <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attributes</span></a> associated with entities.</p>
<p>We can also search by the <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attributes</span></a> associated with entities.</p>
<p>For example, lets give our rose thorns:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rose</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">wines</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">daffodil</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">has_thorns</span> <span class="o">=</span> <span class="kc">False</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>rose.db.has_thorns = True
wines.db.has_thorns = True
daffodil.db.has_thorns = False
</pre></div>
</div>
<p>Now we can find things attribute and the value we want it to have:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">is_ouch</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object_attribute</span><span class="p">(</span><span class="s2">&quot;has_thorns&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>is_ouch = evennia.search_object_attribute(&quot;has_thorns&quot;, True)
</pre></div>
</div>
<p>This returns the rose and the wines.</p>
@ -239,36 +233,38 @@ by-tag is generally faster.</p>
<section id="search-by-typeclass">
<h3>Search by Typeclass<a class="headerlink" href="#search-by-typeclass" title="Permalink to this headline"></a></h3>
<p>Sometimes its useful to find all objects of a specific Typeclass. All of Evennias search tools support this.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_roses</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="n">typeclass</span><span class="o">=</span><span class="s2">&quot;typeclasses.flowers.Rose&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_roses = evennia.search_object(typeclass=&quot;typeclasses.flowers.Rose&quot;)
</pre></div>
</div>
<p>If you have the <code class="docutils literal notranslate"><span class="pre">Rose</span></code> class already imported you can also pass it directly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_roses</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="n">typeclass</span><span class="o">=</span><span class="n">Rose</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_roses = evennia.search_object(typeclass=Rose)
</pre></div>
</div>
<p>You can also search using the typeclass itself:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_roses</span> <span class="o">=</span> <span class="n">Rose</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>all_roses = Rose.objects.all()
</pre></div>
</div>
<p>This last way of searching is a simple form of a Django <em>query</em>. This is a way to express SQL queries using
Python. Well cover this some more as an <a class="reference external" href="#Extra-Credits">Extra-credits</a> section at the end of this lesson.</p>
Python.</p>
</section>
<section id="search-by-dbref">
<h3>Search by dbref<a class="headerlink" href="#search-by-dbref" title="Permalink to this headline"></a></h3>
<p>The database id or <code class="docutils literal notranslate"><span class="pre">#dbref</span></code> is unique and never-reused within each database table. In search methods you can
replace the search for <code class="docutils literal notranslate"><span class="pre">key</span></code> with the dbref to search for. This must be written as a string <code class="docutils literal notranslate"><span class="pre">#dbref</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">the_answer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;#42&quot;</span><span class="p">)</span>
<span class="n">eightball</span> <span class="o">=</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_object</span><span class="p">(</span><span class="s2">&quot;#8&quot;</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>the_answer = self.caller.search(&quot;#42&quot;)
eightball = evennia.search_object(&quot;#8&quot;)
</pre></div>
</div>
<p>Since <code class="docutils literal notranslate"><span class="pre">#dbref</span></code> is always unique, this search is always global.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Relying on #dbrefs</p>
<p>You may be used to using #dbrefs a lot from other codebases. It is however considered
<cite>bad practice</cite> in Evennia to rely on hard-coded #dbrefs. It makes your code hard to maintain
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>You may be used to using #dbrefs a lot from other codebases. It is however considered
`bad practice` in Evennia to rely on hard-coded #dbrefs. It makes your code hard to maintain
and tied to the exact layout of the database. In 99% of cases you should pass the actual objects
around and search by key/tags/attribute instead.</p>
around and search by key/tags/attribute instead.
</pre></div>
</div>
</div>
</section>
</section>
@ -381,7 +377,7 @@ Django queries and querysets in earnest.</p>
<h3>Versions</h3>
<ul>
<li><a href="Searching-Things.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -46,7 +48,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="starting-tutorial-part-1">
<section class="tex2jax_ignore mathjax_ignore" id="starting-tutorial-part-1">
<h1>Starting Tutorial (Part 1)<a class="headerlink" href="#starting-tutorial-part-1" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">Tutorial Parts</p>
@ -71,18 +73,18 @@ and share with others!</p>
<h2>Lessons of Part 1 - “What we have”<a class="headerlink" href="#lessons-of-part-1-what-we-have" title="Permalink to this headline"></a></h2>
<ol class="simple">
<li><p>Introduction (you are here)</p></li>
<li><p><a class="reference internal" href="Building-Quickstart.html"><span class="doc">Building stuff</span></a></p></li>
<li><p><a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc">The Tutorial World</span></a></p></li>
<li><p><a class="reference internal" href="Python-basic-introduction.html"><span class="doc">Python basics</span></a></p></li>
<li><p><a class="reference internal" href="Gamedir-Overview.html"><span class="doc">Game dir overview</span></a></p></li>
<li><p><a class="reference internal" href="Python-classes-and-objects.html"><span class="doc">Python classes and objects</span></a></p></li>
<li><p><a class="reference internal" href="Evennia-Library-Overview.html"><span class="doc">Accessing the Evennia library</span></a></p></li>
<li><p><a class="reference internal" href="Learning-Typeclasses.html"><span class="doc">Typeclasses and Persistent objects</span></a></p></li>
<li><p><a class="reference internal" href="Adding-Commands.html"><span class="doc">Making first own Commands</span></a></p></li>
<li><p><a class="reference internal" href="More-on-Commands.html"><span class="doc">Parsing and replacing default Commands</span></a></p></li>
<li><p><a class="reference internal" href="Creating-Things.html"><span class="doc">Creating things</span></a></p></li>
<li><p><a class="reference internal" href="Searching-Things.html"><span class="doc">Searching for things</span></a></p></li>
<li><p><a class="reference internal" href="Django-queries.html"><span class="doc">Advanced searching with Django queries</span></a></p></li>
<li><p><a class="reference internal" href="Building-Quickstart.html"><span class="doc std std-doc">Building stuff</span></a></p></li>
<li><p><a class="reference internal" href="Tutorial-World-Introduction.html"><span class="doc std std-doc">The Tutorial World</span></a></p></li>
<li><p><a class="reference internal" href="Python-basic-introduction.html"><span class="doc std std-doc">Python basics</span></a></p></li>
<li><p><a class="reference internal" href="Gamedir-Overview.html"><span class="doc std std-doc">Game dir overview</span></a></p></li>
<li><p><a class="reference internal" href="Python-classes-and-objects.html"><span class="doc std std-doc">Python classes and objects</span></a></p></li>
<li><p><a class="reference internal" href="Evennia-Library-Overview.html"><span class="doc std std-doc">Accessing the Evennia library</span></a></p></li>
<li><p><a class="reference internal" href="Learning-Typeclasses.html"><span class="doc std std-doc">Typeclasses and Persistent objects</span></a></p></li>
<li><p><a class="reference internal" href="Adding-Commands.html"><span class="doc std std-doc">Making first own Commands</span></a></p></li>
<li><p><a class="reference internal" href="More-on-Commands.html"><span class="doc std std-doc">Parsing and replacing default Commands</span></a></p></li>
<li><p><a class="reference internal" href="Creating-Things.html"><span class="doc std std-doc">Creating things</span></a></p></li>
<li><p><a class="reference internal" href="Searching-Things.html"><span class="doc std std-doc">Searching for things</span></a></p></li>
<li><p><a class="reference internal" href="Django-queries.html"><span class="doc std std-doc">Advanced searching with Django queries</span></a></p></li>
</ol>
<p>In this first part well focus on what we get out of the box in Evennia - well get used to the tools,
and how to find things we are looking for. We will also dive into some of things youll
@ -106,7 +108,7 @@ to convert this to back-slashes <code class="docutils literal notranslate"><span
</section>
<section id="a-mud-client">
<h3>A MUD client<a class="headerlink" href="#a-mud-client" title="Permalink to this headline"></a></h3>
<p>You might already have a MUD-client you prefer. Check out the <a class="reference internal" href="../../../Setup/Client-Support-Grid.html"><span class="doc">grid of supported clients</span></a> for aid.
<p>You might already have a MUD-client you prefer. Check out the <a class="reference internal" href="../../../Setup/Client-Support-Grid.html"><span class="doc std std-doc">grid of supported clients</span></a> for aid.
If telnets not your thing, you can also just use Evennias web client in your browser.</p>
<blockquote>
<div><p>In this documentation we often use MUD and MU or MU* interchangeably
@ -131,13 +133,13 @@ Python is whitespace-aware, this will make your life a lot easier.</p>
</section>
<section id="set-up-a-game-dir-for-the-tutorial">
<h3>Set up a game dir for the tutorial<a class="headerlink" href="#set-up-a-game-dir-for-the-tutorial" title="Permalink to this headline"></a></h3>
<p>Next you should make sure you have <a class="reference internal" href="../../../Setup/Setup-Quickstart.html"><span class="doc">installed Evennia</span></a>. If you followed the instructions
<p>Next you should make sure you have <a class="reference internal" href="../../../Setup/Setup-Quickstart.html"><span class="doc std std-doc">installed Evennia</span></a>. If you followed the instructions
you will already have created a game-dir. You could use that for this tutorial or you may want to do the
tutorial in its own, isolated game dir; its up to you.</p>
<ul>
<li><p>If you want a new gamedir for the tutorial game and already have Evennia running with another gamedir,
first enter that gamedir and run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span> <span class="n">stop</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia stop
</pre></div>
</div>
</li>
@ -149,10 +151,10 @@ different ports from the defaults, or thered be a clash. We will go into chan
<ul>
<li><p>Now go to where you want to create your tutorial-game. We will always refer to it as <code class="docutils literal notranslate"><span class="pre">mygame</span></code> so
it may be convenient if you do too:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span> <span class="o">--</span><span class="n">init</span> <span class="n">mygame</span>
<span class="n">cd</span> <span class="n">mygame</span>
<span class="n">evennia</span> <span class="n">migrate</span>
<span class="n">evennia</span> <span class="n">start</span> <span class="o">--</span><span class="n">log</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia --init mygame
cd mygame
evennia migrate
evennia start --log
</pre></div>
</div>
<p>Add your superuser name and password at the prompt (email is optional). Make sure you can
@ -161,7 +163,7 @@ in your web browser (Mac users: Try <code class="docutils literal notranslate"><
<p>The above <code class="docutils literal notranslate"><span class="pre">--log</span></code> flag will have Evennia output all its logs to the terminal. This will block
the terminal from other input. To leave the log-view, press <code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> (<code class="docutils literal notranslate"><span class="pre">Cmd-C</span></code> on Mac). To see
the log again just run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span> <span class="o">--</span><span class="n">log</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia --log
</pre></div>
</div>
</li>
@ -234,7 +236,7 @@ the log again just run</p>
<h3>Versions</h3>
<ul>
<li><a href="Starting-Part1.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,12 +49,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="the-tutorial-world">
<section class="tex2jax_ignore mathjax_ignore" id="the-tutorial-world">
<h1>The Tutorial World<a class="headerlink" href="#the-tutorial-world" title="Permalink to this headline"></a></h1>
<p>The <em>Tutorial World</em> is a small and functioning MUD-style game world shipped with Evennia.<br />Its a small showcase of what is possible. It can also be useful for those who have an easier
<p>The <em>Tutorial World</em> is a small and functioning MUD-style game world shipped with Evennia.
Its a small showcase of what is possible. It can also be useful for those who have an easier
time learning by deconstructing existing code.</p>
<p>Stand in the Limbo room and install it with</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">batchcommand</span> <span class="n">tutorial_world</span><span class="o">.</span><span class="n">build</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>batchcommand tutorial_world.build
</pre></div>
</div>
<p>What this does is to run the build script
@ -61,7 +64,7 @@ This is pretty much just a list of build-commands executed in sequence by the <c
Wait for the building to complete and dont run it twice. A new exit should have appeared named <em>Tutorial</em>.</p>
<p>The game consists of a single-player quest and has some 20 rooms that you can explore as you seek
to discover the whereabouts of a mythical weapon. Make sure you dont play as superuser:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">quell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>quell
</pre></div>
</div>
<p>Enter the new exit by writing <code class="docutils literal notranslate"><span class="pre">tutorial</span></code>. Enjoy! If you succeed you will eventually
@ -121,15 +124,19 @@ Either way you should now be back in Limbo, able to reflect on the experience.</
</ul>
<aside class="sidebar">
<p class="sidebar-title">Extra Credit</p>
<p>If you have previous programming experience (or after you have gone
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>If you have previous programming experience (or after you have gone
through this Starter tutorial) it may be instructive to dig a little deeper into the Tutorial-world
code to learn how it achieves what it does. The code is heavily documented.
You can find all the code in <a class="reference external" href="../../api/evennia.contrib.tutorial_world.html">evennia/contrib/tutorial_world</a>,
the build-script is <a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/contrib/tutorial_world/build.ev">here</a>.</p>
<p>When reading and learning from the code, however, keep in mind that <em>Tutorial World</em> was created with a very
You can find all the code in `evennia/contrib/tutorial_world &lt;../../api/evennia.contrib.tutorial_world.html&gt;`_,
the build-script is `here &lt;https://github.com/evennia/evennia/blob/master/evennia/contrib/tutorial_world/build.ev&gt;`_.
When reading and learning from the code, however, keep in mind that *Tutorial World* was created with a very
specific goal in mind: to install easily and to not permanently modify the rest of the server. It therefore
goes to some length to use only temporary solutions and to clean up after itself. This is not something
you will usually need to worry about when making your own game.</p>
you will usually need to worry about when making your own game.
</pre></div>
</div>
</aside>
<p>Quite a lot of stuff crammed in such a small area!</p>
</section>
@ -138,14 +145,14 @@ you will usually need to worry about when making your own game.</p>
<p>Once are done playing with the tutorial world, lets uninstall it.
Uninstalling the tutorial world basically means deleting all the rooms and objects it consists of.
Make sure you are back in Limbo, then</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">find</span> <span class="n">tut</span><span class="c1">#01</span>
<span class="n">find</span> <span class="n">tut</span><span class="c1">#16</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> find tut#01
find tut#16
</pre></div>
</div>
<p>This should locate the first and last rooms created by <code class="docutils literal notranslate"><span class="pre">build.ev</span></code> - <em>Intro</em> and <em>Outro</em>. If you
installed normally, everything created between these two numbers should be part of the tutorial.
Note their #dbref numbers, for example 5 and 80. Next we just delete all objects in that range:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">del</span> <span class="mi">5</span><span class="o">-</span><span class="mi">80</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> del 5-80
</pre></div>
</div>
<p>You will see some errors since some objects are auto-deleted and so cannot be found when the delete
@ -216,7 +223,7 @@ move on with how to access this power through code.</p>
<h3>Versions</h3>
<ul>
<li><a href="Tutorial-World-Introduction.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -48,7 +50,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="on-planning-a-game">
<section class="tex2jax_ignore mathjax_ignore" id="on-planning-a-game">
<h1>On Planning a Game<a class="headerlink" href="#on-planning-a-game" title="Permalink to this headline"></a></h1>
<p>Last lesson we asked ourselves some questions about our motivation. In this one well present
some more technical questions to consider. In the next lesson well answer them for the sake of
@ -172,10 +174,12 @@ release. Make a list. Keep future expansions in mind but limit yourself.</p>
build a little “tech demo” along the way.</p>
<aside class="sidebar">
<p class="sidebar-title">Tech demo</p>
<p>With “tech demo” we mean a small example of your code in-action: A room with a mob,
a way to jump into and test character-creation etc. The tech demo need not be pretty, its
there to test functionality. Its not the beginning of your game world (unless you find that
to be more fun).</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>With &quot;tech demo&quot; we mean a small example of your code in-action: A room with a mob,
a way to jump into and test character-creation etc. The tech demo need not be pretty, it&#39;s
there to test functionality. It&#39;s not the beginning of your game world (unless you find that
to be more fun).
</pre></div>
</div>
</aside>
<p>Try to avoid going wild with building a huge game world before you have a tech-demo showing off all parts
you expect to have in the first version of your game. Otherwise you run the risk of having to redo it all
@ -191,10 +195,10 @@ what tools you have available.</p>
<p>During Coding you look back at the things you wanted during the <strong>Planning</strong> phase and try to
implement them. Dont be shy to update your plans if you find things easier/harder than you thought.
The earlier you revise problems, the easier they will be to fix.</p>
<p>A good idea is to host your code online using <em>version control</em>. Github.com offers free Private repos
<p>A good idea is to host your code online using <em>version control</em>. <a class="reference external" href="http://Github.com">Github.com</a> offers free Private repos
these days if you dont want the world to learn your secrets. Not only version control
make it easy for your team to collaborate, it also means
your work is backed up at all times. The page on <a class="reference internal" href="../../../Coding/Version-Control.html"><span class="doc">Version Control</span></a>
your work is backed up at all times. The page on <a class="reference internal" href="../../../Coding/Version-Control.html"><span class="doc std std-doc">Version Control</span></a>
will help you to setting up a sane developer environment with proper version control.</p>
</section>
<section id="world-building">
@ -226,7 +230,7 @@ flag and let people try it!</p>
you never could have imagined. In Alpha you might be best off to
focus on inviting friends and maybe other MUD developers, people who you can pester to give proper
feedback and bug reports (there <em>will</em> be bugs, there is no way around it).</p>
<p>Follow the quick instructions for <a class="reference internal" href="../../../Setup/Online-Setup.html"><span class="doc">Online Setup</span></a> to make your
<p>Follow the quick instructions for <a class="reference internal" href="../../../Setup/Online-Setup.html"><span class="doc std std-doc">Online Setup</span></a> to make your
game visible online.</p>
<p>If you hadnt already, make sure to put up your game on the
<a class="reference external" href="http://games.evennia.com/">Evennia game index</a> so people know its in the works (actually, even
@ -320,7 +324,7 @@ have made their dream game a reality!</p>
<h3>Versions</h3>
<ul>
<li><a href="Game-Planning.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -48,7 +50,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="planning-the-use-of-some-useful-contribs">
<section class="tex2jax_ignore mathjax_ignore" id="planning-the-use-of-some-useful-contribs">
<h1>Planning the use of some useful contribs<a class="headerlink" href="#planning-the-use-of-some-useful-contribs" title="Permalink to this headline"></a></h1>
<p>Evennia is deliberately bare-bones out of the box. The idea is that you should be as unrestricted as possible
in designing your game. This is why you can easily replace the few defaults we have and why we dont try to
@ -56,7 +58,7 @@ prescribe any major game systems on you.</p>
<p>That said, Evennia <em>does</em> offer some more game-opinionated <em>optional</em> stuff. These are referred to as <em>Contribs</em>
and is an ever-growing treasure trove of code snippets, concepts and even full systems you can pick and choose
from to use, tweak or take inspiration from when you make your game.</p>
<p>The <a class="reference internal" href="../../../Contribs/Contrib-Overview.html"><span class="doc">Contrib overview</span></a> page gives the full list of the current roster of contributions. On
<p>The <a class="reference internal" href="../../../Contribs/Contrib-Overview.html"><span class="doc std std-doc">Contrib overview</span></a> page gives the full list of the current roster of contributions. On
this page we will review a few contribs we will make use of for our game. We will do the actual installation
of them when we start coding in the next part of this tutorial series. While we will introduce them here, you
are wise to read their doc-strings yourself for the details.</p>
@ -73,13 +75,13 @@ are wise to read their doc-strings yourself for the details.</p>
</ul>
<section id="barter-contrib">
<h2>Barter contrib<a class="headerlink" href="#barter-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.barter.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.barter.html"><span class="doc std std-doc">source</span></a></p>
<p>Reviewing this contrib suggests that it allows for safe trading between two parties. The basic principle
is that the parties puts up the stuff they want to sell and the system will guarantee that these systems are
exactly what is being offered. Both sides can modify their offers (bartering) until both mark themselves happy
with the deal. Only then the deal is sealed and the objects are exchanged automatically. Interestingly, this
works just fine for money too - just put coin objects on one side of the transaction.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Sue &gt; trade Tom: Hi, I have a necklace to sell; wanna trade for a healing potion?
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Sue &gt; trade Tom: Hi, I have a necklace to sell; wanna trade for a healing potion?
Tom &gt; trade Sue: Hm, I could use a necklace ...
&lt;both accepted trade. Start trade&gt;
Sue &gt; offer necklace: This necklace is really worth it.
@ -102,20 +104,20 @@ things than boring gold coin.</p>
</section>
<section id="character-generation-contrib">
<h2>Character generation contrib<a class="headerlink" href="#character-generation-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.chargen.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.chargen.html"><span class="doc std std-doc">source</span></a></p>
<p>This contrib is an example module for creating characters. Since we will be using <code class="docutils literal notranslate"><span class="pre">MULTISESSION_MODE=3</span></code> we will
get a selection screen like this automatically. We also plan to use a proper menu to build our character, so
we will <em>not</em> be using this contrib.</p>
</section>
<section id="clothing-contrib">
<h2>Clothing contrib<a class="headerlink" href="#clothing-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.clothing.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.clothing.html"><span class="doc std std-doc">source</span></a></p>
<p>This contrib provides a full system primarily aimed at wearing clothes, but it could also work for armor. You wear
an object in a particular location and this will then be reflected in your characters description. You can
also add roleplaying flavor:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">wear</span> <span class="n">helmet</span> <span class="n">slightly</span> <span class="n">askew</span> <span class="n">on</span> <span class="n">her</span> <span class="n">head</span>
<span class="n">look</span> <span class="bp">self</span>
<span class="n">Username</span> <span class="ow">is</span> <span class="n">wearing</span> <span class="n">a</span> <span class="n">helmet</span> <span class="n">slightly</span> <span class="n">askew</span> <span class="n">on</span> <span class="n">her</span> <span class="n">head</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; wear helmet slightly askew on her head
look self
Username is wearing a helmet slightly askew on her head.
</pre></div>
</div>
<p>By default there are no body locations in this contrib, we will need to expand on it a little to make it useful
@ -123,16 +125,16 @@ for things like armor. Its a good contrib to build from though, so thats w
</section>
<section id="dice-contrib">
<h2>Dice contrib<a class="headerlink" href="#dice-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.dice.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.dice.html"><span class="doc std std-doc">source</span></a></p>
<p>The dice contrib presents a general dice roller to use in game.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">roll</span> <span class="mi">2</span><span class="n">d6</span>
<span class="n">Roll</span><span class="p">(</span><span class="n">s</span><span class="p">):</span> <span class="mi">2</span> <span class="ow">and</span> <span class="mf">5.</span> <span class="n">Total</span> <span class="n">result</span> <span class="ow">is</span> <span class="mf">7.</span>
<span class="o">&gt;</span> <span class="n">roll</span> <span class="mi">1</span><span class="n">d100</span> <span class="o">+</span> <span class="mi">2</span>
<span class="n">Roll</span><span class="p">(</span><span class="n">s</span><span class="p">):</span> <span class="mf">43.</span> <span class="n">Total</span> <span class="n">result</span> <span class="ow">is</span> <span class="mi">47</span>
<span class="o">&gt;</span> <span class="n">roll</span> <span class="mi">1</span><span class="n">d20</span> <span class="o">&gt;</span> <span class="mi">12</span>
<span class="n">Roll</span><span class="p">(</span><span class="n">s</span><span class="p">):</span> <span class="mf">7.</span> <span class="n">Total</span> <span class="n">result</span> <span class="ow">is</span> <span class="mf">7.</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">failure</span> <span class="p">(</span><span class="n">by</span> <span class="mi">5</span><span class="p">)</span>
<span class="o">&gt;</span> <span class="n">roll</span><span class="o">/</span><span class="n">hidden</span> <span class="mi">1</span><span class="n">d20</span> <span class="o">&gt;</span> <span class="mi">12</span>
<span class="n">Roll</span><span class="p">(</span><span class="n">s</span><span class="p">):</span> <span class="mf">18.</span> <span class="n">Total</span> <span class="n">result</span> <span class="ow">is</span> <span class="mf">17.</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">success</span> <span class="p">(</span><span class="n">by</span> <span class="mi">6</span><span class="p">)</span><span class="o">.</span> <span class="p">(</span><span class="ow">not</span> <span class="n">echoed</span><span class="p">)</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; roll 2d6
Roll(s): 2 and 5. Total result is 7.
&gt; roll 1d100 + 2
Roll(s): 43. Total result is 47
&gt; roll 1d20 &gt; 12
Roll(s): 7. Total result is 7. This is a failure (by 5)
&gt; roll/hidden 1d20 &gt; 12
Roll(s): 18. Total result is 17. This is a success (by 6). (not echoed)
</pre></div>
</div>
<p>The contrib also has a python function for producing these results in-code. However, while
@ -143,7 +145,7 @@ or play a game, we will not need it for the core of our game.</p>
</section>
<section id="extended-room-contrib">
<h2>Extended room contrib<a class="headerlink" href="#extended-room-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.extended_room.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.extended_room.html"><span class="doc std std-doc">source</span></a></p>
<p>This is a custom Room typeclass that changes its description based on time of day and season.</p>
<p>For example, at night, in wintertime you could show the room as being dark and frost-covered while in daylight
at summer it could describe a flowering meadow. The description can also contain special markers, so
@ -158,25 +160,25 @@ game, why not!</p>
</section>
<section id="rp-system-contrib">
<h2>RP-System contrib<a class="headerlink" href="#rp-system-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.rpsystem.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.rpsystem.html"><span class="doc std std-doc">source</span></a></p>
<p>This contrib adds a full roleplaying subsystem to your game. It gives every character a “short-description”
(sdesc) that is what people will see when first meeting them. Lets say Tom has an sdesc “A tall man” and
Sue has the sdesc “A muscular, blonde woman”</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">look</span>
<span class="n">Tom</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">room</span> <span class="n">desc</span><span class="o">&gt;</span> <span class="o">...</span> <span class="n">You</span> <span class="n">see</span><span class="p">:</span> <span class="n">A</span> <span class="n">muscular</span><span class="p">,</span> <span class="n">blonde</span> <span class="n">woman</span>
<span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">emote</span> <span class="o">/</span><span class="n">me</span> <span class="n">smiles</span> <span class="n">to</span> <span class="o">/</span><span class="n">muscular</span><span class="o">.</span>
<span class="n">Tom</span><span class="p">:</span> <span class="n">Tom</span> <span class="n">smiles</span> <span class="n">to</span> <span class="n">A</span> <span class="n">muscular</span><span class="p">,</span> <span class="n">blonde</span> <span class="n">woman</span><span class="o">.</span>
<span class="n">Sue</span><span class="p">:</span> <span class="n">A</span> <span class="n">tall</span> <span class="n">man</span> <span class="n">smiles</span> <span class="n">to</span> <span class="n">Sue</span><span class="o">.</span>
<span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">emote</span> <span class="n">Leaning</span> <span class="n">forward</span><span class="p">,</span> <span class="o">/</span><span class="n">me</span> <span class="n">says</span><span class="p">,</span> <span class="s2">&quot;Well hello, what&#39;s yer name?&quot;</span>
<span class="n">Tom</span><span class="p">:</span> <span class="n">Leaning</span> <span class="n">forward</span><span class="p">,</span> <span class="n">Tom</span> <span class="n">says</span><span class="p">,</span> <span class="s2">&quot;Well hello...&quot;</span>
<span class="n">Sue</span><span class="p">:</span> <span class="n">Leaning</span> <span class="n">forward</span><span class="p">,</span> <span class="n">A</span> <span class="n">tall</span> <span class="n">man</span> <span class="n">says</span><span class="p">,</span> <span class="s2">&quot;Well hello, what&#39;s yer name?&quot;</span>
<span class="n">Sue</span> <span class="o">&gt;</span> <span class="n">emote</span> <span class="o">/</span><span class="n">me</span> <span class="n">grins</span><span class="o">.</span> <span class="s2">&quot;I&#39;m Angelica&quot;</span><span class="p">,</span> <span class="n">she</span> <span class="n">says</span><span class="o">.</span>
<span class="n">Sue</span><span class="p">:</span> <span class="n">Sue</span> <span class="n">grins</span><span class="o">.</span> <span class="s2">&quot;I&#39;m Angelica&quot;</span><span class="p">,</span> <span class="n">she</span> <span class="n">says</span><span class="o">.</span>
<span class="n">Tom</span><span class="p">:</span> <span class="n">A</span> <span class="n">muscular</span><span class="p">,</span> <span class="n">blonde</span> <span class="n">woman</span> <span class="n">grins</span><span class="o">.</span> <span class="s2">&quot;I&#39;m Angelica&quot;</span><span class="p">,</span> <span class="n">she</span> <span class="n">says</span><span class="o">.</span>
<span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">recog</span> <span class="n">muscular</span> <span class="n">Angelica</span>
<span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">emote</span> <span class="o">/</span><span class="n">me</span> <span class="n">nods</span> <span class="n">to</span> <span class="o">/</span><span class="n">angelica</span><span class="p">:</span> <span class="s2">&quot;I have a message for you ...&quot;</span>
<span class="n">Tom</span><span class="p">:</span> <span class="n">Tom</span> <span class="n">nods</span> <span class="n">to</span> <span class="n">Angelica</span><span class="p">:</span> <span class="s2">&quot;I have a message for you ...&quot;</span>
<span class="n">Sue</span><span class="p">:</span> <span class="n">A</span> <span class="n">tall</span> <span class="n">man</span> <span class="n">nods</span> <span class="n">to</span> <span class="n">Sue</span><span class="p">:</span> <span class="s2">&quot;I have a message for you ...&quot;</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Tom &gt; look
Tom: &lt;room desc&gt; ... You see: A muscular, blonde woman
Tom &gt; emote /me smiles to /muscular.
Tom: Tom smiles to A muscular, blonde woman.
Sue: A tall man smiles to Sue.
Tom &gt; emote Leaning forward, /me says, &quot;Well hello, what&#39;s yer name?&quot;
Tom: Leaning forward, Tom says, &quot;Well hello...&quot;
Sue: Leaning forward, A tall man says, &quot;Well hello, what&#39;s yer name?&quot;
Sue &gt; emote /me grins. &quot;I&#39;m Angelica&quot;, she says.
Sue: Sue grins. &quot;I&#39;m Angelica&quot;, she says.
Tom: A muscular, blonde woman grins. &quot;I&#39;m Angelica&quot;, she says.
Tom &gt; recog muscular Angelica
Tom &gt; emote /me nods to /angelica: &quot;I have a message for you ...&quot;
Tom: Tom nods to Angelica: &quot;I have a message for you ...&quot;
Sue: A tall man nods to Sue: &quot;I have a message for you ...&quot;
</pre></div>
</div>
<p>Above, Sue introduces herself as “Angelica” and Tom uses this info to <code class="docutils literal notranslate"><span class="pre">recoc</span></code> her as “Angelica” hereafter. He
@ -184,40 +186,40 @@ could have <code class="docutils literal notranslate"><span class="pre">recoc</s
<code class="docutils literal notranslate"><span class="pre">say</span></code>, the spoken words are embedded in the emotes in quotes <code class="docutils literal notranslate"><span class="pre">&quot;...&quot;</span></code>.</p>
<p>The RPSystem module also includes options for <code class="docutils literal notranslate"><span class="pre">poses</span></code>, which help to establish your position in the room
when others look at you.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Tom</span> <span class="o">&gt;</span> <span class="n">pose</span> <span class="n">stands</span> <span class="n">by</span> <span class="n">the</span> <span class="n">bar</span><span class="p">,</span> <span class="n">looking</span> <span class="n">bored</span><span class="o">.</span>
<span class="n">Sue</span> <span class="o">&gt;</span> <span class="n">look</span>
<span class="n">Sue</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">room</span> <span class="n">desc</span><span class="o">&gt;</span> <span class="o">...</span> <span class="n">A</span> <span class="n">tall</span> <span class="n">man</span> <span class="n">stands</span> <span class="n">by</span> <span class="n">the</span> <span class="n">bar</span><span class="p">,</span> <span class="n">looking</span> <span class="n">bored</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Tom &gt; pose stands by the bar, looking bored.
Sue &gt; look
Sue: &lt;room desc&gt; ... A tall man stands by the bar, looking bored.
</pre></div>
</div>
<p>You can also wear a mask to hide your identity; your sdesc will then be changed to the sdesc of the mask,
like <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">person</span> <span class="pre">with</span> <span class="pre">a</span> <span class="pre">mask</span></code>.</p>
<p>The RPSystem gives a lot of roleplaying power out of the box, so we will add it. There is also a separate
<a class="reference external" href="../../../api/evennia.contrib.rplanguage.html">rplanguage</a> module that integrates with the spoken words in your emotes and garbles them if you dont understand
<a class="reference internal" href="../../../api/evennia.contrib.rplanguage.html"><span class="doc std std-doc">rplanguage</span></a> module that integrates with the spoken words in your emotes and garbles them if you dont understand
the language spoken. In order to restrict the scope we will not include languages for the tutorial game.</p>
</section>
<section id="talking-npc-contrib">
<h2>Talking NPC contrib<a class="headerlink" href="#talking-npc-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.talking_npc.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.talking_npc.html"><span class="doc std std-doc">source</span></a></p>
<p>This exemplifies an NPC with a menu-driven dialogue tree. We will not use this contrib explicitly, but its
good as inspiration for how well do quest-givers later.</p>
</section>
<section id="traits-contrib">
<h2>Traits contrib<a class="headerlink" href="#traits-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.traits.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.traits.html"><span class="doc std std-doc">source</span></a></p>
<p>An issue with dealing with roleplaying attributes like strength, dexterity, or skills like hunting, sword etc
is how to keep track of the values in the moment. Your strength may temporarily be buffed by a strength-potion.
Your swordmanship may be worse because you are encumbered. And when you drink your health potion you must make
sure that those +20 health does not bring your health higher than its maximum. All this adds complexity.</p>
<p>The <em>Traits</em> contrib consists of several types of objects to help track and manage values like this. When
installed, the traits are accessed on a new handler <code class="docutils literal notranslate"><span class="pre">.traits</span></code>, for example</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">traits</span><span class="o">.</span><span class="n">hp</span><span class="o">.</span><span class="n">value</span>
<span class="mi">100</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">traits</span><span class="o">.</span><span class="n">hp</span> <span class="o">-=</span> <span class="mi">20</span> <span class="c1"># getting hurt</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">traits</span><span class="o">.</span><span class="n">hp</span><span class="o">.</span><span class="n">value</span>
<span class="mi">80</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">traits</span><span class="o">.</span><span class="n">hp</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span> <span class="c1"># drink a potion</span>
<span class="o">&gt;</span> <span class="n">py</span> <span class="bp">self</span><span class="o">.</span><span class="n">traits</span><span class="o">.</span><span class="n">hp</span><span class="o">.</span><span class="n">value</span>
<span class="mi">100</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py self.traits.hp.value
100
&gt; py self.traits.hp -= 20 # getting hurt
&gt; py self.traits.hp.value
80
&gt; py self.traits.hp.reset() # drink a potion
&gt; py self.traits.hp.value
100
</pre></div>
</div>
<p>A Trait is persistent (it uses an Attribute under the hood) and tracks changes, min/max and other things
@ -253,7 +255,7 @@ effects of slow poisons and healing both.</p></li>
</section>
<section id="turnbattle-contrib">
<h2>Turnbattle contrib<a class="headerlink" href="#turnbattle-contrib" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="../../../api/evennia.contrib.turnbattle.html">source</a></p>
<p><a class="reference internal" href="../../../api/evennia.contrib.turnbattle.html"><span class="doc std std-doc">source</span></a></p>
<p>This contrib consists of several implementations of a turn-based combat system, divivided into complexity:</p>
<ul class="simple">
<li><p>basic - initiative and turn order, attacks against defense values, damage.</p></li>
@ -339,7 +341,7 @@ back to your planning and adjust it as you learn what works and what does not.</
<h3>Versions</h3>
<ul>
<li><a href="Planning-Some-Useful-Contribs.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="planning-our-tutorial-game">
<section class="tex2jax_ignore mathjax_ignore" id="planning-our-tutorial-game">
<h1>Planning our tutorial game<a class="headerlink" href="#planning-our-tutorial-game" title="Permalink to this headline"></a></h1>
<p>Using the general plan from last lesson well now establish what kind of game we want to create for this tutorial.
Remembering that we need to keep the scope down, lets establish some parameters.
@ -101,8 +103,8 @@ goes outside the regular hierarchy and should usually only.</p>
other. By default, the <code class="docutils literal notranslate"><span class="pre">public</span></code> channel is created for general discourse.
Channels are logged to a file and when you are coming back to the game you can view the history of a channel
in case you missed something.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; public Hello world!
[Public] MyName: Hello world!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; public Hello world!
[Public] MyName: Hello world!
</pre></div>
</div>
<p>But Channels can also be set up to work between Characters instead of Accounts. This would mean the channels
@ -149,7 +151,7 @@ build the brunt of things using Evennias Batchcode system.</p>
the ability to create objects with in-built commands is easy and safe, actual code-creation (aka <em>softcode</em> ) is
not something Evennia supports natively. Regular, untrusted users should never be allowed to execute raw Python
code (such as what you can do with the <code class="docutils literal notranslate"><span class="pre">py</span></code> command). You can
<a class="reference internal" href="../../../Concepts/Soft-Code.html"><span class="doc">read more about Evennias stance on softcode here</span></a>. If you want users to do limited scripting,
<a class="reference internal" href="../../../Concepts/Soft-Code.html"><span class="doc std std-doc">read more about Evennias stance on softcode here</span></a>. If you want users to do limited scripting,
its suggested that this is accomplished by adding more powerful build-commands for them to use.</p>
<p>For our tutorial-game, we will only allow privileged builders to modify the world. The exception is crafting,
which we will limit to repairing broken items by combining them with other repair-related items.</p>
@ -556,7 +558,7 @@ to code themselves. So in the next lesson we will check out what help we have fr
<h3>Versions</h3>
<ul>
<li><a href="Planning-The-Tutorial-Game.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -48,7 +50,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="where-do-i-begin">
<section class="tex2jax_ignore mathjax_ignore" id="where-do-i-begin">
<h1>Where do I begin?<a class="headerlink" href="#where-do-i-begin" title="Permalink to this headline"></a></h1>
<p>The good news is that following this Starting tutorial is a great way to begin making an Evennia game.</p>
<p>The bad news is that everyones different and when it comes to starting your own game there is no
@ -161,7 +163,7 @@ so you can read, understand and replicate example code without being completely
</ul>
<p>Once you are out of the starting tutorial, youll be off to do your own thing.</p>
<ul class="simple">
<li><p>The starting tutorial cannot cover everything. Skim through the <a class="reference internal" href="../../../index.html"><span class="doc">Evennia docs</span></a>.
<li><p>The starting tutorial cannot cover everything. Skim through the <a class="reference internal" href="../../../index.html"><span class="doc std std-doc">Evennia docs</span></a>.
Even if you dont read everything, it gives you a feeling for whats available should you need
to look for something later. Make sure to use the search function.</p></li>
<li><p>You can now start by expanding on the tutorial-game we will have created. In the last part there
@ -246,7 +248,7 @@ then try to answer those questions for the sake of creating our little tutorial
<h3>Versions</h3>
<ul>
<li><a href="Planning-Where-Do-I-Begin.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -47,7 +49,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evennia-starting-tutorial-part-2">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-starting-tutorial-part-2">
<h1>Evennia Starting Tutorial (Part 2)<a class="headerlink" href="#evennia-starting-tutorial-part-2" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">Tutorial Parts</p>
@ -71,9 +73,9 @@ game we want to make. This is a more theoretical part where we wont do
programming.</p>
<ol class="simple">
<li><p>Introduction &amp; Overview (you are here)</p></li>
<li><p><a class="reference internal" href="Planning-Where-Do-I-Begin.html"><span class="doc">Where do I begin</span></a></p></li>
<li><p><a class="reference internal" href="Game-Planning.html"><span class="doc">On planning a game</span></a></p></li>
<li><p><a class="reference internal" href="Planning-Some-Useful-Contribs.html"><span class="doc">Planning to use some useful Contribs</span></a></p></li>
<li><p><a class="reference internal" href="Planning-Where-Do-I-Begin.html"><span class="doc std std-doc">Where do I begin</span></a></p></li>
<li><p><a class="reference internal" href="Game-Planning.html"><span class="doc std std-doc">On planning a game</span></a></p></li>
<li><p><a class="reference internal" href="Planning-Some-Useful-Contribs.html"><span class="doc std std-doc">Planning to use some useful Contribs</span></a></p></li>
</ol>
<p>In the process well go through the common questions of “where to start”
and “what to think about” when creating a multiplayer online text game.</p>
@ -136,7 +138,7 @@ and “what to think about” when creating a multiplayer online text game.</p>
<h3>Versions</h3>
<ul>
<li><a href="Starting-Part2.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="implementing-a-game-rule-system">
<section class="tex2jax_ignore mathjax_ignore" id="implementing-a-game-rule-system">
<h1>Implementing a game rule system<a class="headerlink" href="#implementing-a-game-rule-system" title="Permalink to this headline"></a></h1>
<p>The simplest way to create an online roleplaying game (at least from a code perspective) is to
simply grab a paperback RPG rule book, get a staff of game masters together and start to run scenes
@ -79,23 +81,21 @@ makes it easier to change and update things in one place later.</p></li>
values for Health, a list of skills etc, store those things on the Character - dont 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 <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attributes</span></a>, like <code class="docutils literal notranslate"><span class="pre">character.db.STR=34</span></code> and
choose to either store things as individual <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attributes</span></a>, like <code class="docutils literal notranslate"><span class="pre">character.db.STR=34</span></code> and
<code class="docutils literal notranslate"><span class="pre">character.db.Hunting_skill=20</span></code>. But you could also use some custom storage method, like a
dictionary <code class="docutils literal notranslate"><span class="pre">character.db.skills</span> <span class="pre">=</span> <span class="pre">{&quot;Hunting&quot;:34,</span> <span class="pre">&quot;Fishing&quot;:20,</span> <span class="pre">...}</span></code>. A much more fancy solution is
to look at the Ainneve <a class="reference external" href="https://github.com/evennia/ainneve/blob/master/world/traits.py">Trait
handler</a>. Finally you could even go
with a <a class="reference internal" href="../../../Concepts/New-Models.html"><span class="doc">custom django model</span></a>. Which is the better depends on your game and the
with a <a class="reference internal" href="../../../Concepts/New-Models.html"><span class="doc std std-doc">custom django model</span></a>. Which is the better depends on your game and the
complexity of your system.</p></li>
<li><p>Make a clear <a class="reference external" href="https://en.wikipedia.org/wiki/Application_programming_interface">API</a> into your
rules. That is, make methods/functions that you feed with, say, your Character and which skill you
want to check. That is, you want something similar to this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">world</span> <span class="kn">import</span> <span class="n">rules</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">world</span> <span class="kn">import</span> <span class="n">rules</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">rules</span><span class="o">.</span><span class="n">roll_skill</span><span class="p">(</span><span class="n">character</span><span class="p">,</span> <span class="s2">&quot;hunting&quot;</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">rules</span><span class="o">.</span><span class="n">roll_challenge</span><span class="p">(</span><span class="n">character1</span><span class="p">,</span> <span class="n">character2</span><span class="p">,</span> <span class="s2">&quot;swords&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</li>
</ul>
<p>You might need to make these functions more or less complex depending on your game. For example the
@ -158,21 +158,7 @@ value goes up by 2 points and <code class="docutils literal notranslate"><span c
<h3>Character<a class="headerlink" href="#character" title="Permalink to this headline"></a></h3>
<p>The Character typeclass is simple. It goes in <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code>. There is already
an empty <code class="docutils literal notranslate"><span class="pre">Character</span></code> class there that Evennia will look to and use.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultCharacter</span>
<span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
@ -188,7 +174,7 @@ an empty <code class="docutils literal notranslate"><span class="pre">Character<
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">STR</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">combat</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> the server to load up the new code. Doing <code class="docutils literal notranslate"><span class="pre">examine</span> <span class="pre">self</span></code> will however <em>not</em> show the new
Attributes on yourself. This is because the <code class="docutils literal notranslate"><span class="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
@ -201,75 +187,7 @@ the following command:</p>
<section id="rule-module">
<h3>Rule module<a class="headerlink" href="#rule-module" title="Permalink to this headline"></a></h3>
<p>This is a module <code class="docutils literal notranslate"><span class="pre">mygame/world/rules.py</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="k">def</span> <span class="nf">roll_hit</span><span class="p">():</span>
<span class="s2">&quot;Roll 1d100&quot;</span>
@ -339,7 +257,7 @@ the following command:</p>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">RunTimeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Skillname </span><span class="si">{</span><span class="n">skillname</span><span class="si">}</span><span class="s2"> not found.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>These few functions implement the entirety of our simple rule system. We have a function to check
the “defeat” condition and reset the <code class="docutils literal notranslate"><span class="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 <code class="docutils literal notranslate"><span class="pre">SKILLS</span></code> dictionary makes it easy to
@ -348,30 +266,7 @@ function <code class="docutils literal notranslate"><span class="pre">roll_chall
<p>In this example, the skill function actually does a lot - it not only rolls results, it also informs
everyone of their results via <code class="docutils literal notranslate"><span class="pre">character.msg()</span></code> calls.</p>
<p>Here is an example of usage in a game command:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
<span class="kn">from</span> <span class="nn">world</span> <span class="kn">import</span> <span class="n">rules</span>
<span class="k">class</span> <span class="nc">CmdAttack</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
@ -396,7 +291,7 @@ everyone of their results via <code class="docutils literal notranslate"><span c
<span class="k">if</span> <span class="n">target</span><span class="p">:</span>
<span class="n">rules</span><span class="o">.</span><span class="n">roll_challenge</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="s2">&quot;combat&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<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,
@ -460,7 +355,7 @@ your <code class="docutils literal notranslate"><span class="pre">rules</span></
<h3>Versions</h3>
<ul>
<li><a href="Implementing-a-game-rule-system.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -48,11 +50,11 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evennia-starting-tutorial-part-3">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-starting-tutorial-part-3">
<h1>Evennia Starting Tutorial (Part 3)<a class="headerlink" href="#evennia-starting-tutorial-part-3" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">Tutorial Parts</p>
<dl class="simple">
<p>sidebar:: Tutorial Parts</p>
<blockquote>
<div><dl class="simple">
<dt>Part 1: <a class="reference external" href="../Part1/Starting-Part1.html">What we have</a></dt><dd><p>A tour of Evennia and how to use the tools, including an introduction to Python.</p>
</dd>
<dt>Part 2: <a class="reference external" href="../Part2/Starting-Part2.html">What we want</a></dt><dd><p>Planning our tutorial game and what to think about when planning your own in the future.</p>
@ -64,22 +66,22 @@
<dt>Part 5: <a class="reference external" href="../Part5/Starting-Part5.html">Showing the world</a></dt><dd><p>Taking our new game online and let players try it out</p>
</dd>
</dl>
</aside>
</div></blockquote>
<p>In part three of the Evennia Starting tutorial we will go through the creation of several key parts
of our tutorial game <em>EvAdventure</em>. As we go, we will test each part and create a simple “tech demo” to
show off all the moving parts.</p>
<ol class="simple">
<li><p>Introduction &amp; Overview (you are here)</p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Changing settings</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Applying contribs</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Creating a rule module</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Tweaking the base Typeclasses</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Character creation menu</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Wearing armor and wielding weapons</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Two types of combat</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Monsters and AI</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Questing and rewards</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc">Overview of Tech demo</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Changing settings</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Applying contribs</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Creating a rule module</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Tweaking the base Typeclasses</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Character creation menu</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Wearing armor and wielding weapons</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Two types of combat</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Monsters and AI</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Questing and rewards</span></a></p></li>
<li><p><a class="reference internal" href="../../../Unimplemented.html"><span class="doc std std-doc">Overview of Tech demo</span></a></p></li>
</ol>
<p>If you followed the previous parts of this tutorial you will have some notions about Python and where to find
and make use of things in Evennia. We also have a good idea of the type of game we want.
@ -136,7 +138,7 @@ with using Evennia. This be of much use when doing your own thing later.</p>
<h3>Versions</h3>
<ul>
<li><a href="Starting-Part3.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="turn-based-combat-system">
<section class="tex2jax_ignore mathjax_ignore" id="turn-based-combat-system">
<h1>Turn based Combat System<a class="headerlink" href="#turn-based-combat-system" title="Permalink to this headline"></a></h1>
<p>This tutorial gives an example of a full, if simplified, combat system for Evennia. It was inspired
by the discussions held on the <a class="reference external" href="https://groups.google.com/forum/#%21msg/evennia/wnJNM2sXSfs/-dbLRrgWnYMJ">mailing
@ -68,7 +70,7 @@ allows for emoting as part of combat which is an advantage for roleplay-heavy ga
<p>To implement a freeform combat system all you need is a dice roller and a roleplaying rulebook. See
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py">contrib/dice.py</a> for an
example dice roller. To implement at twitch-based system you basically need a few combat
<a class="reference internal" href="../../../Components/Commands.html"><span class="doc">commands</span></a>, possibly ones with a <a class="reference internal" href="../../Command-Cooldown.html"><span class="doc">cooldown</span></a>. You also need a <a class="reference internal" href="Implementing-a-game-rule-system.html"><span class="doc">game rule
<a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">commands</span></a>, possibly ones with a <a class="reference internal" href="../../Command-Cooldown.html"><span class="doc std std-doc">cooldown</span></a>. You also need a <a class="reference internal" href="Implementing-a-game-rule-system.html"><span class="doc std std-doc">game rule
module</span></a> that makes use of it. We will focus on the turn-based
variety here.</p>
</section>
@ -86,7 +88,7 @@ free.</p></li>
<li><p>The commands are (in our example) simple; they can either <code class="docutils literal notranslate"><span class="pre">hit</span> <span class="pre">&lt;target&gt;</span></code>, <code class="docutils literal notranslate"><span class="pre">feint</span> <span class="pre">&lt;target&gt;</span></code> or
<code class="docutils literal notranslate"><span class="pre">parry</span> <span class="pre">&lt;target&gt;</span></code>. They can also <code class="docutils literal notranslate"><span class="pre">defend</span></code>, a generic passive defense. Finally they may choose to
<code class="docutils literal notranslate"><span class="pre">disengage/flee</span></code>.</p></li>
<li><p>When attacking we use a classic [rock-paper-scissors](https://en.wikipedia.org/wiki/Rock-paper-
<li><p>When attacking we use a classic [rock-paper-scissors](<a class="reference external" href="https://en.wikipedia.org/wiki/Rock-paper-">https://en.wikipedia.org/wiki/Rock-paper-</a>
scissors) mechanic to determine success: <code class="docutils literal notranslate"><span class="pre">hit</span></code> defeats <code class="docutils literal notranslate"><span class="pre">feint</span></code>, which defeats <code class="docutils literal notranslate"><span class="pre">parry</span></code> which defeats
<code class="docutils literal notranslate"><span class="pre">hit</span></code>. <code class="docutils literal notranslate"><span class="pre">defend</span></code> is a general passive action that has a percentage chance to win against <code class="docutils literal notranslate"><span class="pre">hit</span></code>
(only).</p></li>
@ -98,23 +100,23 @@ reported. A new turn then begins.</p></li>
</ul>
<p>For creating the combat system we will need the following components:</p>
<ul class="simple">
<li><p>A combat handler. This is the main mechanic of the system. This is a <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Script</span></a> object
<li><p>A combat handler. This is the main mechanic of the system. This is a <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Script</span></a> object
created for each combat. It is not assigned to a specific object but is shared by the combating
characters and handles all the combat information. Since Scripts are database entities it also means
that the combat will not be affected by a server reload.</p></li>
<li><p>A combat <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc">command set</span></a> with the relevant commands needed for combat, such as the
<li><p>A combat <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc std std-doc">command set</span></a> with the relevant commands needed for combat, such as the
various attack/defend options and the <code class="docutils literal notranslate"><span class="pre">flee/disengage</span></code> command to leave the combat mode.</p></li>
<li><p>A rule resolution system. The basics of making such a module is described in the <a class="reference internal" href="Implementing-a-game-rule-system.html"><span class="doc">rule system
<li><p>A rule resolution system. The basics of making such a module is described in the <a class="reference internal" href="Implementing-a-game-rule-system.html"><span class="doc std std-doc">rule system
tutorial</span></a>. We will only sketch such a module here for our end-turn
combat resolution.</p></li>
<li><p>An <code class="docutils literal notranslate"><span class="pre">attack</span></code> <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">command</span></a> for initiating the combat mode. This is added to the default
<li><p>An <code class="docutils literal notranslate"><span class="pre">attack</span></code> <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">command</span></a> for initiating the combat mode. This is added to the default
command set. It will create the combat handler and add the character(s) to it. It will also assign
the combat command set to the characters.</p></li>
</ul>
</section>
<section id="the-combat-handler">
<h2>The combat handler<a class="headerlink" href="#the-combat-handler" title="Permalink to this headline"></a></h2>
<p>The <em>combat handler</em> is implemented as a stand-alone <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc">Script</span></a>. This Script is created when
<p>The <em>combat handler</em> is implemented as a stand-alone <a class="reference internal" href="../../../Components/Scripts.html"><span class="doc std std-doc">Script</span></a>. This Script is created when
the first Character decides to attack another and is deleted when no one is fighting any more. Each
handler represents one instance of combat and one combat only. Each instance of combat can hold any
number of characters but each character can only be part of one combat at a time (a player would
@ -125,172 +127,12 @@ combat. Vice-versa, all characters holds a back-reference to the current combat
dont use this very much here this might allow the combat commands on the characters to access and
update the combat handler state directly.</p>
<p><em>Note: Another way to implement a combat handler would be to use a normal Python object and handle
time-keeping with the <a class="reference internal" href="../../../Components/TickerHandler.html"><span class="doc">TickerHandler</span></a>. This would require either adding custom hook
time-keeping with the <a class="reference internal" href="../../../Components/TickerHandler.html"><span class="doc std std-doc">TickerHandler</span></a>. This would require either adding custom hook
methods on the character or to implement a custom child of the TickerHandler class to track turns.
Whereas the TickerHandler is easy to use, a Script offers more power in this case.</em></p>
<p>Here is a basic combat handler. Assuming our game folder is named <code class="docutils literal notranslate"><span class="pre">mygame</span></code>, we store it in
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/combat_handler.py</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal"> 10</span>
<span class="normal"> 11</span>
<span class="normal"> 12</span>
<span class="normal"> 13</span>
<span class="normal"> 14</span>
<span class="normal"> 15</span>
<span class="normal"> 16</span>
<span class="normal"> 17</span>
<span class="normal"> 18</span>
<span class="normal"> 19</span>
<span class="normal"> 20</span>
<span class="normal"> 21</span>
<span class="normal"> 22</span>
<span class="normal"> 23</span>
<span class="normal"> 24</span>
<span class="normal"> 25</span>
<span class="normal"> 26</span>
<span class="normal"> 27</span>
<span class="normal"> 28</span>
<span class="normal"> 29</span>
<span class="normal"> 30</span>
<span class="normal"> 31</span>
<span class="normal"> 32</span>
<span class="normal"> 33</span>
<span class="normal"> 34</span>
<span class="normal"> 35</span>
<span class="normal"> 36</span>
<span class="normal"> 37</span>
<span class="normal"> 38</span>
<span class="normal"> 39</span>
<span class="normal"> 40</span>
<span class="normal"> 41</span>
<span class="normal"> 42</span>
<span class="normal"> 43</span>
<span class="normal"> 44</span>
<span class="normal"> 45</span>
<span class="normal"> 46</span>
<span class="normal"> 47</span>
<span class="normal"> 48</span>
<span class="normal"> 49</span>
<span class="normal"> 50</span>
<span class="normal"> 51</span>
<span class="normal"> 52</span>
<span class="normal"> 53</span>
<span class="normal"> 54</span>
<span class="normal"> 55</span>
<span class="normal"> 56</span>
<span class="normal"> 57</span>
<span class="normal"> 58</span>
<span class="normal"> 59</span>
<span class="normal"> 60</span>
<span class="normal"> 61</span>
<span class="normal"> 62</span>
<span class="normal"> 63</span>
<span class="normal"> 64</span>
<span class="normal"> 65</span>
<span class="normal"> 66</span>
<span class="normal"> 67</span>
<span class="normal"> 68</span>
<span class="normal"> 69</span>
<span class="normal"> 70</span>
<span class="normal"> 71</span>
<span class="normal"> 72</span>
<span class="normal"> 73</span>
<span class="normal"> 74</span>
<span class="normal"> 75</span>
<span class="normal"> 76</span>
<span class="normal"> 77</span>
<span class="normal"> 78</span>
<span class="normal"> 79</span>
<span class="normal"> 80</span>
<span class="normal"> 81</span>
<span class="normal"> 82</span>
<span class="normal"> 83</span>
<span class="normal"> 84</span>
<span class="normal"> 85</span>
<span class="normal"> 86</span>
<span class="normal"> 87</span>
<span class="normal"> 88</span>
<span class="normal"> 89</span>
<span class="normal"> 90</span>
<span class="normal"> 91</span>
<span class="normal"> 92</span>
<span class="normal"> 93</span>
<span class="normal"> 94</span>
<span class="normal"> 95</span>
<span class="normal"> 96</span>
<span class="normal"> 97</span>
<span class="normal"> 98</span>
<span class="normal"> 99</span>
<span class="normal">100</span>
<span class="normal">101</span>
<span class="normal">102</span>
<span class="normal">103</span>
<span class="normal">104</span>
<span class="normal">105</span>
<span class="normal">106</span>
<span class="normal">107</span>
<span class="normal">108</span>
<span class="normal">109</span>
<span class="normal">110</span>
<span class="normal">111</span>
<span class="normal">112</span>
<span class="normal">113</span>
<span class="normal">114</span>
<span class="normal">115</span>
<span class="normal">116</span>
<span class="normal">117</span>
<span class="normal">118</span>
<span class="normal">119</span>
<span class="normal">120</span>
<span class="normal">121</span>
<span class="normal">122</span>
<span class="normal">123</span>
<span class="normal">124</span>
<span class="normal">125</span>
<span class="normal">126</span>
<span class="normal">127</span>
<span class="normal">128</span>
<span class="normal">129</span>
<span class="normal">130</span>
<span class="normal">131</span>
<span class="normal">132</span>
<span class="normal">133</span>
<span class="normal">134</span>
<span class="normal">135</span>
<span class="normal">136</span>
<span class="normal">137</span>
<span class="normal">138</span>
<span class="normal">139</span>
<span class="normal">140</span>
<span class="normal">141</span>
<span class="normal">142</span>
<span class="normal">143</span>
<span class="normal">144</span>
<span class="normal">145</span>
<span class="normal">146</span>
<span class="normal">147</span>
<span class="normal">148</span>
<span class="normal">149</span>
<span class="normal">150</span>
<span class="normal">151</span>
<span class="normal">152</span>
<span class="normal">153</span>
<span class="normal">154</span>
<span class="normal">155</span>
<span class="normal">156</span>
<span class="normal">157</span>
<span class="normal">158</span>
<span class="normal">159</span>
<span class="normal">160</span>
<span class="normal">161</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/combat_handler.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/combat_handler.py</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultScript</span>
@ -452,7 +294,7 @@ Whereas the TickerHandler is easy to use, a Script offers more power in this cas
<span class="p">(</span><span class="s2">&quot;defend&quot;</span><span class="p">,</span> <span class="n">character</span><span class="p">,</span> <span class="kc">None</span><span class="p">)]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg_all</span><span class="p">(</span><span class="s2">&quot;Next turn begins ...&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This implements all the useful properties of our combat handler. This Script will survive a reboot
and will automatically re-assert itself when it comes back online. Even the current state of the
combat should be unaffected since it is saved in Attributes at every turn. An important part to note
@ -468,41 +310,7 @@ an exercise.</p>
example) very simple. In a full implementation the commands available might be determined by the
weapon(s) held by the player or by which skills they know.</p>
<p>We create them in <code class="docutils literal notranslate"><span class="pre">mygame/commands/combat.py</span></code>.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span>
@ -538,31 +346,12 @@ weapon(s) held by the player or by which skills they know.</p>
<span class="c1"># tell the handler to check if turn is over</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">combat_handler</span><span class="o">.</span><span class="n">check_end_turn</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The other commands <code class="docutils literal notranslate"><span class="pre">CmdParry</span></code>, <code class="docutils literal notranslate"><span class="pre">CmdFeint</span></code>, <code class="docutils literal notranslate"><span class="pre">CmdDefend</span></code> and <code class="docutils literal notranslate"><span class="pre">CmdDisengage</span></code> look basically the same.
We should also add a custom <code class="docutils literal notranslate"><span class="pre">help</span></code> command to list all the available combat commands and what they
do.</p>
<p>We just need to put them all in a cmdset. We do this at the end of the same module:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
@ -583,7 +372,7 @@ do.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdPose</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdSay</span><span class="p">())</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="rules-module">
<h2>Rules module<a class="headerlink" href="#rules-module" title="Permalink to this headline"></a></h2>
@ -611,83 +400,7 @@ subsequent attack and so on …</em></p>
<li><p><code class="docutils literal notranslate"><span class="pre">flee/disengage</span></code> must succeed two times in a row (i.e. not beaten by a <code class="docutils literal notranslate"><span class="pre">hit</span></code> once during the
turn). If so the character leaves combat.</p></li>
</ul>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span>
<span class="normal">70</span>
<span class="normal">71</span>
<span class="normal">72</span>
<span class="normal">73</span>
<span class="normal">74</span>
<span class="normal">75</span>
<span class="normal">76</span>
<span class="normal">77</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/world/rules.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/world/rules.py</span>
<span class="kn">import</span> <span class="nn">random</span>
@ -765,7 +478,7 @@ turn). If so the character leaves combat.</p></li>
<span class="n">combat_handler</span><span class="o">.</span><span class="n">msg_all</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">char</span><span class="si">}</span><span class="s2"> withdraws from combat.&quot;</span><span class="p">)</span>
<span class="n">combat_handler</span><span class="o">.</span><span class="n">remove_character</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>To make it simple (and to save space), this example rule module actually resolves each interchange
twice - first when it gets to each character and then again when handling the target. Also, since we
use the combat handlers <code class="docutils literal notranslate"><span class="pre">msg_all</span></code> method here, the system will get pretty spammy. To clean it up,
@ -776,43 +489,7 @@ reported once.</p>
<h2>Combat initiator command<a class="headerlink" href="#combat-initiator-command" title="Permalink to this headline"></a></h2>
<p>This is the last component we need, a command to initiate combat. This will tie everything together.
We store this with the other combat commands.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/commands/combat.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_script</span>
@ -850,9 +527,9 @@ We store this with the other combat commands.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You attack </span><span class="si">{</span><span class="n">target</span><span class="si">}</span><span class="s2">! You are in combat.&quot;</span><span class="p">)</span>
<span class="n">target</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="si">}</span><span class="s2"> attacks you! You are in combat.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">attack</span></code> command will not go into the combat cmdset but rather into the default cmdset. See e.g.
the <a class="reference internal" href="../Part1/Adding-Commands.html"><span class="doc">Adding Command Tutorial</span></a> if you are unsure about how to do this.</p>
the <a class="reference internal" href="../Part1/Adding-Commands.html"><span class="doc std std-doc">Adding Command Tutorial</span></a> if you are unsure about how to do this.</p>
</section>
<section id="expanding-the-example">
<h2>Expanding the example<a class="headerlink" href="#expanding-the-example" title="Permalink to this headline"></a></h2>
@ -921,7 +598,7 @@ show others whats going on.</p>
<h3>Versions</h3>
<ul>
<li><a href="Turn-based-Combat-System.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,14 +40,14 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="tutorial-for-basic-mush-like-game">
<section class="tex2jax_ignore mathjax_ignore" id="tutorial-for-basic-mush-like-game">
<h1>Tutorial for basic MUSH like game<a class="headerlink" href="#tutorial-for-basic-mush-like-game" title="Permalink to this headline"></a></h1>
<p>This tutorial lets you code a small but complete and functioning MUSH-like game in Evennia. A
<a class="reference external" href="https://en.wikipedia.org/wiki/MUSH">MUSH</a> is, for our purposes, a class of roleplay-centric games
focused on free form storytelling. Even if you are not interested in MUSH:es, this is still a good
first game-type to try since its not so code heavy. You will be able to use the same principles for
building other types of games.</p>
<p>The tutorial starts from scratch. If you did the <a class="reference internal" href="../Part1/Starting-Part1.html"><span class="doc">First Steps Coding</span></a> tutorial
<p>The tutorial starts from scratch. If you did the <a class="reference internal" href="../Part1/Starting-Part1.html"><span class="doc std std-doc">First Steps Coding</span></a> tutorial
already you should have some ideas about how to do some of the steps already.</p>
<p>The following are the (very simplistic and cut-down) features we will implement (this was taken from
a feature request from a MUSH user new to Evennia). A Character in this system should:</p>
@ -79,18 +81,7 @@ SQLite3 database.</p>
<p>First thing is to choose how our Character class works. We dont need to define a special NPC object
an NPC is after all just a Character without an Account currently controlling them.</p>
<p>Make your changes in the <code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/characters.py</span></code> file:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/characters.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># mygame/typeclasses/characters.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultCharacter</span>
@ -103,19 +94,19 @@ SQLite3 database.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">power</span> <span class="o">=</span> <span class="mi">1</span>
<span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">combat_score</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</td></tr></table></div>
<p>We defined two new <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attributes</span></a> <code class="docutils literal notranslate"><span class="pre">power</span></code> and <code class="docutils literal notranslate"><span class="pre">combat_score</span></code> and set them to default
</div>
<p>We defined two new <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attributes</span></a> <code class="docutils literal notranslate"><span class="pre">power</span></code> and <code class="docutils literal notranslate"><span class="pre">combat_score</span></code> and set them to default
values. Make sure to <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> the server if you had it already running (you need to reload every
time you update your python code, dont worry, no accounts will be disconnected by the reload).</p>
<p>Note that only <em>new</em> characters will see your new Attributes (since the <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> hook is
called when the object is first created, existing Characters wont have it). To update yourself,
run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@typeclass</span><span class="o">/</span><span class="n">force</span> <span class="bp">self</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @typeclass/force self
</pre></div>
</div>
<p>This resets your own typeclass (the <code class="docutils literal notranslate"><span class="pre">/force</span></code> switch is a safety measure to not do this
accidentally), this means that <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code> is re-run.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">examine</span> <span class="bp">self</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> examine self
</pre></div>
</div>
<p>Under the “Persistent attributes” heading you should now find the new Attributes <code class="docutils literal notranslate"><span class="pre">power</span></code> and <code class="docutils literal notranslate"><span class="pre">score</span></code>
@ -134,8 +125,8 @@ example, we could simply set an <code class="docutils literal notranslate"><span
check it. Using this method however will make it easy to add more functionality later.</p>
<p>What we need are the following:</p>
<ul class="simple">
<li><p>One character generation <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Command</span></a> to set the “Power” on the <code class="docutils literal notranslate"><span class="pre">Character</span></code>.</p></li>
<li><p>A chargen <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc">CmdSet</span></a> to hold this command. Lets call it <code class="docutils literal notranslate"><span class="pre">ChargenCmdset</span></code>.</p></li>
<li><p>One character generation <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Command</span></a> to set the “Power” on the <code class="docutils literal notranslate"><span class="pre">Character</span></code>.</p></li>
<li><p>A chargen <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> to hold this command. Lets call it <code class="docutils literal notranslate"><span class="pre">ChargenCmdset</span></code>.</p></li>
<li><p>A custom <code class="docutils literal notranslate"><span class="pre">ChargenRoom</span></code> type that makes this set of commands available to players in such rooms.</p></li>
<li><p>One such room to test things in.</p></li>
</ul>
@ -143,9 +134,9 @@ check it. Using this method however will make it easy to add more functionality
<h3>The +setpower command<a class="headerlink" href="#the-setpower-command" title="Permalink to this headline"></a></h3>
<p>For this tutorial we will add all our new commands to <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code> but you could
split your commands into multiple module if you prefered.</p>
<p>For this tutorial character generation will only consist of one <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Command</span></a> to set the
<p>For this tutorial character generation will only consist of one <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Command</span></a> to set the
Character s “power” stat. It will be called on the following MUSH-like form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">+</span><span class="n">setpower</span> <span class="mi">4</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> +setpower 4
</pre></div>
</div>
<p>Open <code class="docutils literal notranslate"><span class="pre">command.py</span></code> file. It contains documented empty templates for the base command and the
@ -153,40 +144,7 @@ Character s “power” stat. It will be called on the following MUSH-like form:
<code class="docutils literal notranslate"><span class="pre">MuxCommand</span></code> class offers some extra features like stripping whitespace that may be useful - if so,
just import from that instead.</p>
<p>Add the following to the end of the <code class="docutils literal notranslate"><span class="pre">command.py</span></code> file:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># end of command.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># end of command.py</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span> <span class="c1"># just for clarity; already imported above</span>
<span class="k">class</span> <span class="nc">CmdSetPower</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
@ -221,31 +179,21 @@ just import from that instead.</p>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">power</span> <span class="o">=</span> <span class="n">power</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Your Power was set to </span><span class="si">{</span><span class="n">power</span><span class="si">}</span><span class="s2">.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This is a pretty straightforward command. We do some error checking, then set the power on ourself.
We use a <code class="docutils literal notranslate"><span class="pre">help_category</span></code> of “mush” for all our commands, just so they are easy to find and separate
in the help list.</p>
<p>Save the file. We will now add it to a new <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc">CmdSet</span></a> so it can be accessed (in a full
<p>Save the file. We will now add it to a new <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc std std-doc">CmdSet</span></a> so it can be accessed (in a full
chargen system you would of course have more than one command here).</p>
<p>Open <code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdsets.py</span></code> and import your <code class="docutils literal notranslate"><span class="pre">command.py</span></code> module at the top. We also
import the default <code class="docutils literal notranslate"><span class="pre">CmdSet</span></code> class for the next step:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">CmdSet</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">command</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Next scroll down and define a new command set (based on the base <code class="docutils literal notranslate"><span class="pre">CmdSet</span></code> class we just imported at
the end of this file, to hold only our chargen-specific command(s):</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># end of default_cmdsets.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># end of default_cmdsets.py</span>
<span class="k">class</span> <span class="nc">ChargenCmdset</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -256,7 +204,7 @@ the end of this file, to hold only our chargen-specific command(s):</p>
<span class="s2">&quot;This is called at initialization&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">command</span><span class="o">.</span><span class="n">CmdSetPower</span><span class="p">())</span>
</pre></div>
</td></tr></table></div>
</div>
<p>In the future you can add any number of commands to this cmdset, to expand your character generation
system as you desire. Now we need to actually put that cmdset on something so its made available to
users. We could put it directly on the Character, but that would make it available all the time.
@ -266,19 +214,7 @@ Its cleaner to put it on a room, so its only available when players are in
<h3>Chargen areas<a class="headerlink" href="#chargen-areas" title="Permalink to this headline"></a></h3>
<p>We will create a simple Room typeclass to act as a template for all our Chargen areas. Edit
<code class="docutils literal notranslate"><span class="pre">mygame/typeclasses/rooms.py</span></code> next:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands.default_cmdsets</span> <span class="kn">import</span> <span class="n">ChargenCmdset</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">commands.default_cmdsets</span> <span class="kn">import</span> <span class="n">ChargenCmdset</span>
<span class="c1"># ...</span>
<span class="c1"># down at the end of rooms.py</span>
@ -292,10 +228,10 @@ Its cleaner to put it on a room, so its only available when players are in
<span class="s2">&quot;this is called only at first creation&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">ChargenCmdset</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note how new rooms created with this typeclass will always start with <code class="docutils literal notranslate"><span class="pre">ChargenCmdset</span></code> on themselves.
Dont forget the <code class="docutils literal notranslate"><span class="pre">persistent=True</span></code> keyword or you will lose the cmdset after a server reload. For
more information about <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc">Command Sets</span></a> and <a class="reference internal" href="../../../Components/Commands.html"><span class="doc">Commands</span></a>, see the respective
more information about <a class="reference internal" href="../../../Components/Command-Sets.html"><span class="doc std std-doc">Command Sets</span></a> and <a class="reference internal" href="../../../Components/Commands.html"><span class="doc std std-doc">Commands</span></a>, see the respective
links.</p>
</section>
<section id="testing-chargen">
@ -305,7 +241,7 @@ your new python code added to the game. Check your terminal and fix any errors y
traceback lists exactly where the error is found - look line numbers in files you have changed.</p>
<p>We cant test things unless we have some chargen areas to test. Log into the game (you should at
this point be using the new, custom Character class). Lets dig a chargen area to test.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@dig</span> <span class="n">chargen</span><span class="p">:</span><span class="n">rooms</span><span class="o">.</span><span class="n">ChargenRoom</span> <span class="o">=</span> <span class="n">chargen</span><span class="p">,</span><span class="n">finish</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @dig chargen:rooms.ChargenRoom = chargen,finish
</pre></div>
</div>
<p>If you read the help for <code class="docutils literal notranslate"><span class="pre">&#64;dig</span></code> you will find that this will create a new room named <code class="docutils literal notranslate"><span class="pre">chargen</span></code>. The
@ -319,13 +255,13 @@ as <code class="docutils literal notranslate"><span class="pre">chargen;characte
an exit back here named <code class="docutils literal notranslate"><span class="pre">finish</span></code>. If you see errors at this stage, you must fix them in your code.
<code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code>
between fixes. Dont continue until the creation seems to have worked okay.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">chargen</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> chargen
</pre></div>
</div>
<p>This should bring you to the chargen room. Being in there you should now have the <code class="docutils literal notranslate"><span class="pre">+setpower</span></code>
command available, so test it out. When you leave (via the <code class="docutils literal notranslate"><span class="pre">finish</span></code> exit), the command will go away
and trying <code class="docutils literal notranslate"><span class="pre">+setpower</span></code> should now give you a command-not-found error. Use <code class="docutils literal notranslate"><span class="pre">ex</span> <span class="pre">me</span></code> (as a privileged
user) to check so the <code class="docutils literal notranslate"><span class="pre">Power</span></code> <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attribute</span></a> has been set correctly.</p>
user) to check so the <code class="docutils literal notranslate"><span class="pre">Power</span></code> <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a> has been set correctly.</p>
<p>If things are not working, make sure your typeclasses and commands are free of bugs and that you
have entered the paths to the various command sets and commands correctly. Check the logs or command
line for tracebacks and errors.</p>
@ -340,51 +276,12 @@ We also change the default <code class="docutils literal notranslate"><span clas
<h3>Attacking with the +attack command<a class="headerlink" href="#attacking-with-the-attack-command" title="Permalink to this headline"></a></h3>
<p>Attacking in this simple system means rolling a random “combat score” influenced by the <code class="docutils literal notranslate"><span class="pre">power</span></code> stat
set during Character generation:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; +attack
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; +attack
You +attack with a combat score of 12!
</pre></div>
</div>
<p>Go back to <code class="docutils literal notranslate"><span class="pre">mygame/commands/command.py</span></code> and add the command to the end like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">random</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">random</span>
<span class="c1"># ...</span>
@ -425,15 +322,15 @@ You +attack with a combat score of 12!
<span class="n">c_score</span><span class="o">=</span><span class="n">combat_score</span><span class="p">,</span>
<span class="p">),</span> <span class="n">exclude</span><span class="o">=</span><span class="n">caller</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>What we do here is simply to generate a “combat score” using Pythons inbuilt <code class="docutils literal notranslate"><span class="pre">random.randint()</span></code>
function. We then store that and echo the result to everyone involved.</p>
<p>To make the <code class="docutils literal notranslate"><span class="pre">+attack</span></code> command available to you in game, go back to
<code class="docutils literal notranslate"><span class="pre">mygame/commands/default_cmdsets.py</span></code> and scroll down to the <code class="docutils literal notranslate"><span class="pre">CharacterCmdSet</span></code> class. At the correct
place add this line:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">command</span><span class="o">.</span><span class="n">CmdAttack</span><span class="p">())</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">command</span><span class="o">.</span><span class="n">CmdAttack</span><span class="p">())</span>
</pre></div>
</td></tr></table></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code> Evennia and the <code class="docutils literal notranslate"><span class="pre">+attack</span></code> command should be available to you. Run it and use e.g. <code class="docutils literal notranslate"><span class="pre">&#64;ex</span></code> to
make sure the <code class="docutils literal notranslate"><span class="pre">combat_score</span></code> attribute is saved correctly.</p>
</section>
@ -443,9 +340,9 @@ make sure the <code class="docutils literal notranslate"><span class="pre">comba
adding a second command named something like <code class="docutils literal notranslate"><span class="pre">+combatscores</span></code>, but we will instead let the default
<code class="docutils literal notranslate"><span class="pre">look</span></code> command do the heavy lifting for us and display our scores as part of its normal output, like
this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="n">look</span> <span class="n">Tom</span>
<span class="n">Tom</span> <span class="p">(</span><span class="n">combat</span> <span class="n">score</span><span class="p">:</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">great</span> <span class="n">warrior</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; look Tom
Tom (combat score: 3)
This is a great warrior.
</pre></div>
</div>
<p>We dont actually have to modify the <code class="docutils literal notranslate"><span class="pre">look</span></code> command itself however. To understand why, take a look
@ -462,30 +359,7 @@ implementation of <code class="docutils literal notranslate"><span class="pre">r
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L1438">here</a>). If you
want to make bigger changes you could copy &amp; paste the whole default thing into our overloading
method. In our case the change is small though:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Character</span><span class="p">(</span><span class="n">DefaultCharacter</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> [...]</span>
<span class="sd"> &quot;&quot;&quot;</span>
@ -510,7 +384,7 @@ method. In our case the change is small though:</p>
<span class="n">text</span> <span class="o">+=</span> <span class="n">cscore</span>
<span class="k">return</span> <span class="n">text</span>
</pre></div>
</td></tr></table></div>
</div>
<p>What we do is to simply let the default <code class="docutils literal notranslate"><span class="pre">return_appearance</span></code> do its thing (<code class="docutils literal notranslate"><span class="pre">super</span></code> will call the
parents version of the same method). We then split out the first line of this text, append our
<code class="docutils literal notranslate"><span class="pre">combat_score</span></code> and put it back together again.</p>
@ -532,58 +406,16 @@ should also be able to set its Power and order it around.</p>
and put a custom NPC-specific cmdset on all NPCs. This cmdset could hold all manipulation commands.
Since we expect NPC manipulation to be a common occurrence among the user base however, we will
instead put all relevant NPC commands in the default command set and limit eventual access with
<a class="reference external" href="Components/Locks.html#Permissions">Permissions and Locks</a>.</p>
<a class="reference internal" href="../../../Components/Permissions.html"><span class="doc std std-doc">Permissions and Locks</span></a>.</p>
<section id="creating-an-npc-with-createnpc">
<h3>Creating an NPC with +createNPC<a class="headerlink" href="#creating-an-npc-with-createnpc" title="Permalink to this headline"></a></h3>
<p>We need a command for creating the NPC, this is a very straightforward command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="o">+</span><span class="n">createnpc</span> <span class="n">Anna</span>
<span class="n">You</span> <span class="n">created</span> <span class="n">the</span> <span class="n">NPC</span> <span class="s1">&#39;Anna&#39;</span><span class="o">.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; +createnpc Anna
You created the NPC &#39;Anna&#39;.
</pre></div>
</div>
<p>At the end of <code class="docutils literal notranslate"><span class="pre">command.py</span></code>, create our new command:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span>
<span class="k">class</span> <span class="nc">CmdCreateNPC</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
@ -627,14 +459,14 @@ instead put all relevant NPC commands in the default command set and limit event
<span class="n">npc</span><span class="o">=</span><span class="n">name</span><span class="p">,</span>
<span class="p">),</span> <span class="n">exclude</span><span class="o">=</span><span class="n">caller</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Here we define a <code class="docutils literal notranslate"><span class="pre">+createnpc</span></code> (<code class="docutils literal notranslate"><span class="pre">+createNPC</span></code> works too) that is callable by everyone <em>not</em> having the
<code class="docutils literal notranslate"><span class="pre">nonpcs</span></code><a class="reference external" href="Components/Locks.html#Permissions">permission</a>” (in Evennia, a “permission” can just as well be used to
<code class="docutils literal notranslate"><span class="pre">nonpcs</span></code><a class="reference internal" href="../../../Components/Permissions.html"><span class="doc std std-doc">permission</span></a>” (in Evennia, a “permission” can just as well be used to
block access, it depends on the lock we define). We create the NPC object in the callers current
location, using our custom <code class="docutils literal notranslate"><span class="pre">Character</span></code> typeclass to do so.</p>
<p>We set an extra lock condition on the NPC, which we will use to check who may edit the NPC later
we allow the creator to do so, and anyone with the Builders permission (or higher). See
<a class="reference internal" href="../../../Components/Locks.html"><span class="doc">Locks</span></a> for more information about the lock system.</p>
<a class="reference internal" href="../../../Components/Locks.html"><span class="doc std std-doc">Locks</span></a> for more information about the lock system.</p>
<p>Note that we just give the object default permissions (by not specifying the <code class="docutils literal notranslate"><span class="pre">permissions</span></code> keyword
to the <code class="docutils literal notranslate"><span class="pre">create_object()</span></code> call). In some games one might want to give the NPC the same permissions
as the Character creating them, this might be a security risk though.</p>
@ -646,92 +478,21 @@ as the Character creating them, this might be a security risk though.</p>
<p>Since we re-used our custom character typeclass, our new NPC already has a <em>Power</em> value - it
defaults to 1. How do we change this?</p>
<p>There are a few ways we can do this. The easiest is to remember that the <code class="docutils literal notranslate"><span class="pre">power</span></code> attribute is just a
simple <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc">Attribute</span></a> stored on the NPC object. So as a Builder or Admin we could set this
simple <a class="reference internal" href="../../../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a> stored on the NPC object. So as a Builder or Admin we could set this
right away with the default <code class="docutils literal notranslate"><span class="pre">&#64;set</span></code> command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nd">@set</span> <span class="n">mynpc</span><span class="o">/</span><span class="n">power</span> <span class="o">=</span> <span class="mi">6</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> @set mynpc/power = 6
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">&#64;set</span></code> command is too generally powerful though, and thus only available to staff. We will add a
custom command that only changes the things we want players to be allowed to change. We could in
principle re-work our old <code class="docutils literal notranslate"><span class="pre">+setpower</span></code> command, but lets try something more useful. Lets make a
<code class="docutils literal notranslate"><span class="pre">+editNPC</span></code> command.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="o">+</span><span class="n">editNPC</span> <span class="n">Anna</span><span class="o">/</span><span class="n">power</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">Set</span> <span class="n">Anna</span><span class="s1">&#39;s property &#39;</span><span class="n">power</span><span class="s1">&#39; to 10.</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; +editNPC Anna/power = 10
Set Anna&#39;s property &#39;power&#39; to 10.
</pre></div>
</div>
<p>This is a slightly more complex command. It goes at the end of your <code class="docutils literal notranslate"><span class="pre">command.py</span></code> file as before.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span>
<span class="normal">70</span>
<span class="normal">71</span>
<span class="normal">72</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdEditNPC</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdEditNPC</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> edit an existing NPC</span>
@ -804,7 +565,7 @@ principle re-work our old <code class="docutils literal notranslate"><span class
<span class="p">(</span><span class="n">npc</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">propname</span><span class="p">,</span>
<span class="n">npc</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">propname</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s2">&quot;N/A&quot;</span><span class="p">)))</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This command example shows off the use of more advanced parsing but otherwise its mostly error
checking. It searches for the given npc in the same room, and checks so the caller actually has
permission to “edit” it before continuing. An account without the proper permission wont even be
@ -824,48 +585,12 @@ anyone to use the NPC.</p>
it doesnt have access to are Session and Player-based cmdsets (which means, among other things that
they cannot chat on channels, but they could do that if you just added those commands). This makes
the <code class="docutils literal notranslate"><span class="pre">+npc</span></code> command simple:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>+npc Anna = say Hello!
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>+npc Anna = say Hello!
Anna says, &#39;Hello!&#39;
</pre></div>
</div>
<p>Again, add to the end of your <code class="docutils literal notranslate"><span class="pre">command.py</span></code> module:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdNPC</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CmdNPC</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> controls an NPC</span>
@ -903,13 +628,13 @@ Anna says, &#39;Hello!&#39;
<span class="n">npc</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cmdname</span><span class="p">)</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;You told </span><span class="si">{</span><span class="n">npc</span><span class="o">.</span><span class="n">key</span><span class="si">}</span><span class="s2"> to do &#39;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">cmdname</span><span class="si">}</span><span class="s2">&#39;.&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note that if you give an erroneous command, you will not see any error message, since that error
will be returned to the npc object, not to you. If you want players to see this, you can give the
callers session ID to the <code class="docutils literal notranslate"><span class="pre">execute_cmd</span></code> call, like this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">npc</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cmdname</span><span class="p">,</span> <span class="n">sessid</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">sessid</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">npc</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cmdname</span><span class="p">,</span> <span class="n">sessid</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">sessid</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Another thing to remember is however that this is a very simplistic way to control NPCs. Evennia
supports full puppeting very easily. An Account (assuming the “puppet” permission was set correctly)
could simply do <code class="docutils literal notranslate"><span class="pre">&#64;ic</span> <span class="pre">mynpc</span></code> and be able to play the game “as” that NPC. This is in fact just what
@ -927,9 +652,9 @@ generation.</p>
<p>The simple “Power” game mechanic should be easily expandable to something more full-fledged and
useful, same is true for the combat score principle. The <code class="docutils literal notranslate"><span class="pre">+attack</span></code> could be made to target a
specific player (or npc) and automatically compare their relevant attributes to determine a result.</p>
<p>To continue from here, you can take a look at the <a class="reference internal" href="../Part1/Tutorial-World-Introduction.html"><span class="doc">Tutorial World</span></a>. For
more specific ideas, see the <a class="reference internal" href="../../Howto-Overview.html"><span class="doc">other tutorials and hints</span></a> as well
as the <a class="reference internal" href="../../../Components/Components-Overview.html"><span class="doc">Evennia Component overview</span></a>.</p>
<p>To continue from here, you can take a look at the <a class="reference internal" href="../Part1/Tutorial-World-Introduction.html"><span class="doc std std-doc">Tutorial World</span></a>. For
more specific ideas, see the <a class="reference internal" href="../../Howto-Overview.html"><span class="doc std std-doc">other tutorials and hints</span></a> as well
as the <a class="reference internal" href="../../../Components/Components-Overview.html"><span class="doc std std-doc">Evennia Component overview</span></a>.</p>
</section>
</section>
@ -1000,7 +725,7 @@ as the <a class="reference internal" href="../../../Components/Components-Overvi
<h3>Versions</h3>
<ul>
<li><a href="Tutorial-for-basic-MUSH-like-game.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,11 +40,11 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evennia-starting-tutorial-part-4">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-starting-tutorial-part-4">
<h1>Evennia Starting Tutorial (Part 4)<a class="headerlink" href="#evennia-starting-tutorial-part-4" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">Tutorial Parts</p>
<dl class="simple">
<p>sidebar:: Tutorial Parts</p>
<blockquote>
<div><dl class="simple">
<dt>Part 1: <a class="reference external" href="../Part1/Starting-Part1.html">What we have</a></dt><dd><p>A tour of Evennia and how to use the tools, including an introduction to Python.</p>
</dd>
<dt>Part 2: <a class="reference external" href="../Part2/Starting-Part2.html">What we want</a></dt><dd><p>Planning our tutorial game and what to think about when planning your own in the future.</p>
@ -54,7 +56,7 @@
<dt>Part 5: <a class="reference external" href="../Part5/Starting-Part5.html">Showing the world</a></dt><dd><p>Taking our new game online and let players try it out</p>
</dd>
</dl>
</aside>
</div></blockquote>
<p>We now have the code underpinnings of everything we need. We have also tested the various components
and has a simple tech-demo to show it all works together. But there is no real coherence to it at this
point - we need to actually make a world.
@ -103,7 +105,7 @@ and batchcode processors.</p>
<h3>Versions</h3>
<ul>
<li><a href="Starting-Part4.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="add-a-simple-new-web-page">
<section class="tex2jax_ignore mathjax_ignore" id="add-a-simple-new-web-page">
<h1>Add a simple new web page<a class="headerlink" href="#add-a-simple-new-web-page" title="Permalink to this headline"></a></h1>
<p>Evennia leverages <a class="reference external" href="https://docs.djangoproject.com">Django</a> which is a web development framework.
Huge professional websites are made in Django and there is extensive documentation (and books) on it
@ -56,19 +58,14 @@ cool stuff with the page in the view, like adding dynamic content or change it o
<code class="docutils literal notranslate"><span class="pre">mygame/web</span></code> folder and add a new module there named <code class="docutils literal notranslate"><span class="pre">story.py</span></code> (you could also put it in its own
folder if you wanted to be neat. Dont forget to add an empty <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file if you do, to tell
Python you can import from the new folder). Heres how it looks:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/story.py</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in mygame/web/story.py</span>
<span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="kn">import</span> <span class="n">render</span>
<span class="k">def</span> <span class="nf">storypage</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
<span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s2">&quot;story.html&quot;</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>This view takes advantage of a shortcut provided to use by Django, <em>render</em>. This shortcut gives the
template some information from the request, for instance, the game name, and then renders it.</p>
</section>
@ -79,17 +76,7 @@ Django parlance). You can specify such places in your settings (see the <code cl
<code class="docutils literal notranslate"><span class="pre">default_settings.py</span></code> for more info), but here well use an existing one. Go to
<code class="docutils literal notranslate"><span class="pre">mygame/template/overrides/website/</span></code> and create a page <code class="docutils literal notranslate"><span class="pre">story.html</span></code> there.</p>
<p>This is not a HTML tutorial, so well go simple:</p>
<div class="highlight-html notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>{% extends &quot;base.html&quot; %}
<div class="highlight-html notranslate"><div class="highlight"><pre><span></span>{% extends &quot;base.html&quot; %}
{% block content %}
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;row&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;col&quot;</span><span class="p">&gt;</span>
@ -101,16 +88,10 @@ Django parlance). You can specify such places in your settings (see the <code cl
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
{% endblock %}
</pre></div>
</td></tr></table></div>
</div>
<p>Since weve used the <em>render</em> shortcut, Django will allow us to extend our base styles easily.</p>
<p>If youd rather not take advantage of Evennias base styles, you can do something like this instead:</p>
<div class="highlight-html notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span>
<div class="highlight-html notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>A story about a tree<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>
@ -118,7 +99,7 @@ Django parlance). You can specify such places in your settings (see the <code cl
<span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="the-url">
<h2>The URL<a class="headerlink" href="#the-url" title="Permalink to this headline"></a></h2>
@ -130,13 +111,7 @@ Open it now.</p>
<p>Django looks for the variable <code class="docutils literal notranslate"><span class="pre">urlpatterns</span></code> in this file. You want to add your new pattern to the
<code class="docutils literal notranslate"><span class="pre">custom_patterns</span></code> list we have prepared - that is then merged with the default <code class="docutils literal notranslate"><span class="pre">urlpatterns</span></code>. Heres
how it could look:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">web</span> <span class="kn">import</span> <span class="n">story</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">web</span> <span class="kn">import</span> <span class="n">story</span>
<span class="c1"># ...</span>
@ -144,7 +119,7 @@ how it could look:</p>
<span class="n">url</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;story&#39;</span><span class="p">,</span> <span class="n">story</span><span class="o">.</span><span class="n">storypage</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;Story&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</td></tr></table></div>
</div>
<p>That is, we import our story view module from where we created it earlier and then create an <code class="docutils literal notranslate"><span class="pre">url</span></code>
instance. The first argument to <code class="docutils literal notranslate"><span class="pre">url</span></code> is the pattern of the url we want to find (<code class="docutils literal notranslate"><span class="pre">&quot;story&quot;</span></code>) (this is
a regular expression if you are familiar with those) and then our view function we want to direct
@ -203,7 +178,7 @@ to.</p>
<h3>Versions</h3>
<ul>
<li><a href="Add-a-simple-new-web-page.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="evennia-starting-tutorial-part-5">
<section class="tex2jax_ignore mathjax_ignore" id="evennia-starting-tutorial-part-5">
<h1>Evennia Starting Tutorial (part 5)<a class="headerlink" href="#evennia-starting-tutorial-part-5" title="Permalink to this headline"></a></h1>
<aside class="sidebar">
<p class="sidebar-title">Tutorial Parts</p>
@ -101,7 +103,7 @@ to bring your game online so you can invite your first players.</p>
<h3>Versions</h3>
<ul>
<li><a href="Starting-Part5.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>

View file

@ -14,6 +14,8 @@
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
@ -38,13 +40,13 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="web-tutorial">
<section class="tex2jax_ignore mathjax_ignore" id="web-tutorial">
<h1>Web Tutorial<a class="headerlink" href="#web-tutorial" title="Permalink to this headline"></a></h1>
<p>Evennia uses the <a class="reference external" href="https://www.djangoproject.com/">Django</a> web framework as the basis of both its
database configuration and the website it provides. While a full understanding of Django requires
reading the Django documentation, we have provided this tutorial to get you running with the basics
and how they pertain to Evennia. This text details getting everything set up. The
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc">Web-based Character view Tutorial</span></a> gives a more explicit example of making a
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc std std-doc">Web-based Character view Tutorial</span></a> gives a more explicit example of making a
custom web page connected to your game, and you may want to read that after finishing this guide.</p>
<section id="a-basic-overview">
<h2>A Basic Overview<a class="headerlink" href="#a-basic-overview" title="Permalink to this headline"></a></h2>
@ -61,7 +63,7 @@ like <a class="reference external" href="https://en.wikipedia.org/wiki/CSS">CSS<
and Image files (You may note your mygame/web folder does not have a <code class="docutils literal notranslate"><span class="pre">static</span></code> or <code class="docutils literal notranslate"><span class="pre">template</span></code> folder.
This is intended and explained further below). Django applications may also have a <code class="docutils literal notranslate"><span class="pre">models.py</span></code> file
for storing information in the database. We will not change any models here, take a look at the
<a class="reference internal" href="../../../Concepts/New-Models.html"><span class="doc">New Models</span></a> page (as well as the <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/">Django docs</a> on models) if you are interested.</p>
<a class="reference internal" href="../../../Concepts/New-Models.html"><span class="doc std std-doc">New Models</span></a> page (as well as the <a class="reference external" href="https://docs.djangoproject.com/en/1.7/topics/db/models/">Django docs</a> on models) if you are interested.</p>
<p>There is also a root <code class="docutils literal notranslate"><span class="pre">urls.py</span></code> that determines the URL structure for the entire project. A starter
<code class="docutils literal notranslate"><span class="pre">urls.py</span></code> is included in the default game template, and automatically imports all of Evennias
default URLs for you. This is located in <code class="docutils literal notranslate"><span class="pre">web/urls.py</span></code>.</p>
@ -115,8 +117,8 @@ everything) in the <code class="docutils literal notranslate"><span class="pre">
scratch.</p>
</div></blockquote>
</section>
<section id="changing-the-front-page-s-text">
<h2>Changing the Front Pages Text<a class="headerlink" href="#changing-the-front-page-s-text" title="Permalink to this headline"></a></h2>
<section id="changing-the-front-pages-text">
<h2>Changing the Front Pages Text<a class="headerlink" href="#changing-the-front-pages-text" title="Permalink to this headline"></a></h2>
<p>The default front page for Evennia contains information about the Evennia project. Youll probably
want to replace this information with information about your own project. Changing the page template
is done in a similar way to changing static resources.</p>
@ -127,7 +129,7 @@ means that when you edit a template, the changes are instant. You dont have t
run any extra commands to see these changes - reloading the web page in your browser is enough.</p>
<p>To replace the index pages text, well need to find the template for it. Well go into more detail
about how to determine which template is used for rendering a page in the
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc">Web-based Character view Tutorial</span></a>. For now, you should know that the template we want to change
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc std std-doc">Web-based Character view Tutorial</span></a>. For now, you should know that the template we want to change
is stored in <code class="docutils literal notranslate"><span class="pre">evennia/web/website/templates/website/index.html</span></code>.</p>
<p>To replace this template file, you will put your changed template inside the
<code class="docutils literal notranslate"><span class="pre">web/template_overrides/website</span></code> directory in your game folder. In the same way as with static
@ -140,7 +142,7 @@ original file already has all the markup and tags, ready for editing.</p>
<section id="further-reading">
<h2>Further reading<a class="headerlink" href="#further-reading" title="Permalink to this headline"></a></h2>
<p>For further hints on working with the web presence, you could now continue to the
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc">Web-based Character view Tutorial</span></a> where you learn to make a web page that
<a class="reference internal" href="../../Web-Character-View-Tutorial.html"><span class="doc std std-doc">Web-based Character view Tutorial</span></a> where you learn to make a web page that
displays in-game character stats. You can also look at <a class="reference external" href="https://docs.djangoproject.com/en/1.7/intro/tutorial01/">Djangos own
tutorial</a> to get more insight in how Django
works and what possibilities exist.</p>
@ -172,7 +174,7 @@ works and what possibilities exist.</p>
<li><a class="reference internal" href="#">Web Tutorial</a><ul>
<li><a class="reference internal" href="#a-basic-overview">A Basic Overview</a></li>
<li><a class="reference internal" href="#changing-the-logo-on-the-front-page">Changing the logo on the front page</a></li>
<li><a class="reference internal" href="#changing-the-front-page-s-text">Changing the Front Pages Text</a></li>
<li><a class="reference internal" href="#changing-the-front-pages-text">Changing the Front Pages Text</a></li>
<li><a class="reference internal" href="#further-reading">Further reading</a></li>
</ul>
</li>
@ -198,7 +200,7 @@ works and what possibilities exist.</p>
<h3>Versions</h3>
<ul>
<li><a href="Web-Tutorial.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>