<h1><spanclass="section-number">11. </span>Searching for things<aclass="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>
<pclass="sidebar-title">Python code vs using the py command</p>
<p>Most of these tools are intended to be used in Python code, as you create your game. We
give examples of how to test things out from the <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> command, but that’s just for experimenting and normally not how you code your game.</p>
<h2><spanclass="section-number">11.1. </span>Searching using Object.search<aclass="headerlink"href="#searching-using-object-search"title="Permalink to this headline">¶</a></h2>
<p>On the <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> is a <codeclass="docutils literal notranslate"><spanclass="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, and if you are using <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> you can use yourself:</p>
<li><p>This searches by <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">alias</span></code> of the object. Strings are always case-insensitive, so searching for <codeclass="docutils literal notranslate"><spanclass="pre">"rose"</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">"Rose"</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">"rOsE"</span></code> give the same results.</p></li>
<li><p>By default it will always search for objects among those in <codeclass="docutils literal notranslate"><spanclass="pre">obj.location.contents</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">obj.contents</span></code> (that is, things in obj’s inventory or in the same room).</p></li>
<li><p>It will always return exactly one match. If it found zero or more than one match, the return is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. This is different from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search</span></code> (see below), which always returns a list.</p></li>
<li><p>On a no-match or multimatch, <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> will automatically send an error message to <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>. So you don’t have to worry about reporting messages if the result is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>.</p></li>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"Found match for </span><spanclass="si">{</span><spanclass="n">query</span><spanclass="si">}</span><spanclass="s2">: </span><spanclass="si">{</span><spanclass="n">result</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<p>If you want to test this command out, add it to the default cmdset (see <aclass="reference internal"href="Beginner-Tutorial-Adding-Commands.html"><spanclass="doc std std-doc">the Command tutorial</span></a> for more details) and then reload the server with <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code>:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/commands/default_cmdsets.py</span>
<p>Remember, <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> is the one calling the command. This is usually a Character, which
inherits from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>. So it has <codeclass="docutils literal notranslate"><spanclass="pre">.search()</span></code> available on it.</p>
<p>This simple little Command takes its arguments and searches for a match. If it can’t find it, <codeclass="docutils literal notranslate"><spanclass="pre">result</span></code> will be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. The error has already been reported to <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> so we just abort with <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code>.</p>
<p>With the <codeclass="docutils literal notranslate"><spanclass="pre">global_search</span></code> flag, you can use <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> to find anything, not just stuff in the same room:</p>
<p>This will only return a match if “MyStone” is in the room (or in your inventory) <em>and</em> is one of the four provided candidate objects. This is quite powerful, here’s how you’d find something only in your inventory:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">swords</span><spanclass="o">=</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">search</span><spanclass="p">(</span><spanclass="s2">"Sword"</span><spanclass="p">,</span><spanclass="n">quiet</span><spanclass="o">=</span><spanclass="kc">True</span><spanclass="p">)</span><spanclass="c1"># returns a list!</span>
<p>With <codeclass="docutils literal notranslate"><spanclass="pre">quiet=True</span></code> the user will not be notified on zero or multi-match errors. Instead you are expected to handle this yourself. Furthermore, what is returned is now a list of zero, one or more matches!</p>
<h2><spanclass="section-number">11.2. </span>Main search functions<aclass="headerlink"href="#main-search-functions"title="Permalink to this headline">¶</a></h2>
<p>The base search tools of Evennia are the <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_*</span></code> functions, such as <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_object</span></code>. These are normally used in your code, but you can also try them out in-game using <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code>:</p>
<p>What is returned from the main search functions is actually a <codeclass="docutils literal notranslate"><spanclass="pre">queryset</span></code>. They can be treated like lists except that they can’t modified in-place. We’ll discuss querysets in the <aclass="reference internal"href="Beginner-Tutorial-Django-queries.html"><spanclass="doc std std-doc">next lesson</span></a></p>
</aside>
<p>This searches for objects based on <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">alias</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> method we talked about in the previous section in fact wraps <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_object</span></code> and handles its output in various ways. Here’s the same example in Python code, for example as part of a command or coded system:</p>
<p>Above we find first the rose and then an Account. You can try both using <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code>:</p>
<p>In the example above we used <codeclass="docutils literal notranslate"><spanclass="pre">[0]</span></code> to only get the first match of the queryset, which in this case gives us the rose and your Account respectively. Note that if you don’t find any matches, using <codeclass="docutils literal notranslate"><spanclass="pre">[0]</span></code> like this leads to an error, so it’s mostly useful for debugging.</p>
<p>If you 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. This is too detailed for testing out just with <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code>, but good to know if you want to make your own search methods:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">the_one_ring</span><spanclass="o">=</span><spanclass="n">evennia</span><spanclass="o">.</span><spanclass="n">search_object</span><spanclass="p">(</span><spanclass="s2">"The one Ring"</span><spanclass="p">)</span>
<p>There are equivalent search functions for all the main resources. You can find a listing of them <aclass="reference internal"href="../../../Evennia-API.html"><spanclass="doc std std-doc">in the Search functions section</span></a> of the API front page.</p>
<h2><spanclass="section-number">11.3. </span>What can be searched for<aclass="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>
<li><p><aclass="reference internal"href="../../../Components/Msg.html"><spanclass="doc std std-doc">Messages</span></a> (used by <codeclass="docutils literal notranslate"><spanclass="pre">page</span></code> command by default)</p></li>
<li><p><aclass="reference internal"href="../../../Components/Help-System.html"><spanclass="doc std std-doc">Help Entries</span></a> (help entries created manually)</p></li>
</ul>
<p>Most of the time you’ll likely spend your time searching for Objects and the occasional Accounts.</p>
<p>So to find an entity, what can be searched for?</p>
<sectionid="search-by-key">
<h3><spanclass="section-number">11.3.1. </span>Search by key<aclass="headerlink"href="#search-by-key"title="Permalink to this headline">¶</a></h3>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is the name of the entity. Searching for this is always case-insensitive.</p>
</section>
<sectionid="search-by-aliases">
<h3><spanclass="section-number">11.3.2. </span>Search by aliases<aclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> these will searched too, you can’t easily search only for aliases. Let’s add an alias to our rose with the default <codeclass="docutils literal notranslate"><spanclass="pre">alias</span></code> command:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>> alias rose = flower
</pre></div>
</div>
<p>Alternatively you can achieve the same thing manually (this is what the <codeclass="docutils literal notranslate"><spanclass="pre">alias</span></code> command does for you automatically):</p>
<p>If the above example <codeclass="docutils literal notranslate"><spanclass="pre">rose</span></code> has a <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code><codeclass="docutils literal notranslate"><spanclass="pre">"Rose"</span></code>, it can now also be found by searching for its alias <codeclass="docutils literal notranslate"><spanclass="pre">flower</span></code>.</p>
<div><p>All default commands uses the same search functionality, so you can now do <codeclass="docutils literal notranslate"><spanclass="pre">look</span><spanclass="pre">flower</span></code> to look at the rose as well.</p>
<h3><spanclass="section-number">11.3.3. </span>Search by location<aclass="headerlink"href="#search-by-location"title="Permalink to this headline">¶</a></h3>
<p>Only Objects (things inheriting from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.DefaultObject</span></code>) has a <codeclass="docutils literal notranslate"><spanclass="pre">.location</span></code> property.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">Object.search</span></code> method will automatically limit its search by the object’s location, so assuming you are in the same room as the rose, this will work:</p>
<p>In general, the <codeclass="docutils literal notranslate"><spanclass="pre">Object.search</span></code> is a shortcut for doing the very common searches of things in the same location, whereas the <codeclass="docutils literal notranslate"><spanclass="pre">search_object</span></code> finds objects anywhere.</p>
<p>Think of a <aclass="reference internal"href="../../../Components/Tags.html"><spanclass="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>
<p>Go back to the location of your <codeclass="docutils literal notranslate"><spanclass="pre">rose</span></code> and let’s create a few more plants:</p>
<p>Tags can also have categories. By default this category is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> , which is considered a category of its own. Here are some examples of using categories in plain Python code (you can also try this out with <codeclass="docutils literal notranslate"><spanclass="pre">py</span></code> if you want to create the objects first):</p>
<p>Note that if you specify the tag with a category, you <em>must</em> also include its category when searching, otherwise the tag-category of <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> will be searched.</p>
<h3><spanclass="section-number">11.3.5. </span>Search by Attribute<aclass="headerlink"href="#search-by-attribute"title="Permalink to this headline">¶</a></h3>
<p>We can also search by the <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> associated with entities.</p>
<div><p>Searching by Attribute can be very practical. But if you want to group entities or search very often, using Tags and search by Tags is faster and more resource-efficient.</p>
<h3><spanclass="section-number">11.3.6. </span>Search by Typeclass<aclass="headerlink"href="#search-by-typeclass"title="Permalink to this headline">¶</a></h3>
<p>Sometimes it’s useful to limit your search by which Typeclass they have.</p>
<p>Let’s say you for example have two types of flower, <codeclass="docutils literal notranslate"><spanclass="pre">CursedFlower</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">BlessedFlower</span></code> defined under <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses.flowers.py</span></code>. Each class contains custom code that grants curses and blessings respectively. You may have two <codeclass="docutils literal notranslate"><spanclass="pre">rose</span></code> objects, and the player doesn’t know which one is the bad or the good one. To separate them in your search, you can make sure to get the right one like this (in Python code)</p>
<p>If you e.g. have the <codeclass="docutils literal notranslate"><spanclass="pre">BlessedRose</span></code> class already imported you can also pass it directly:</p>
<p>A common use case is finding <em>all</em> items of a given typeclass, no matter what they are named. For this you don’t use <codeclass="docutils literal notranslate"><spanclass="pre">search_object</span></code>, but search with the typeclass directly:</p>
<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. See <aclass="reference internal"href="Beginner-Tutorial-Django-queries.html"><spanclass="doc std std-doc">the next lesson</span></a>, where we’ll explore this way to searching in more detail.</p>
</section>
<sectionid="search-by-dbref">
<h3><spanclass="section-number">11.3.7. </span>Search by dbref<aclass="headerlink"href="#search-by-dbref"title="Permalink to this headline">¶</a></h3>
<asideclass="sidebar">
<pclass="sidebar-title">Will I run out of dbrefs?</p>
<p>Since dbrefs are not reused, do you need to worry about your database ids ‘running out’ in the future? <aclass="reference internal"href="../../../Components/Typeclasses.html#will-i-run-out-of-dbrefs"><spanclass="std std-doc">No, and here’s why</span></a>.</p>
</aside>
<p>The database id or <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code> is unique and never-reused within each database table. In search methods you can replace the search for <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> with the dbref to search for. This must be written as a string <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code>:</p>
<p>Since <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code> is always unique, this search is always global.</p>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<p>Relying on #dbrefs</p>
<p>In legacy code bases you may be used to relying a lot on #dbrefs to find and track things. Looking something up by #dbref can be practical - if used occationally. It is however considered <strong>bad practice</strong> to <em>rely</em> on hard-coded #dbrefs in Evennia. Especially to expect end users to know them. It makes your code fragile and hard to maintain, while tying your code to the exact layout of the database. In 99% of use cases you should organize your code such that you pass the actual objects around and search by key/tags/attribute instead.</p>
</div>
</section>
</section>
<sectionid="finding-objects-relative-each-other">
<h2><spanclass="section-number">11.4. </span>Finding objects relative each other<aclass="headerlink"href="#finding-objects-relative-each-other"title="Permalink to this headline">¶</a></h2>
<p>It’s important to understand how objects relate to one another when searching.
Let’s consider a <codeclass="docutils literal notranslate"><spanclass="pre">chest</span></code> with a <codeclass="docutils literal notranslate"><spanclass="pre">coin</span></code> inside it. The chest stands in a room <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>. In the dungeon is also a <codeclass="docutils literal notranslate"><spanclass="pre">door</span></code>. This is an exit leading outside.</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">chest</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">chest.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> since it’s not inside something else.</p></li>
<p>One can use this to find what is inside what. For example, <codeclass="docutils literal notranslate"><spanclass="pre">coin.location.location</span></code> is the <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>.
We can also find what is inside each object. This is a list of things.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[chest,</span><spanclass="pre">door]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">chest.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[coin]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code>, the empty list since there’s nothing ‘inside’ the coin.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code> too.</p></li>
</ul>
<p>A convenient helper is <codeclass="docutils literal notranslate"><spanclass="pre">.contents_get</span></code> - this allows to restrict what is returned:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.contents_get(exclude=chest)</span></code> - this returns everything in the room except the chest (maybe it’s hidden?)</p></li>
</ul>
<p>There is a special property for finding exits:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.exits</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[door]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.exits</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code> (same for all the other objects)</p></li>
</ul>
<p>There is a property <codeclass="docutils literal notranslate"><spanclass="pre">.destination</span></code> which is only used by exits:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.destination</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">outside</span></code> (or wherever the door leads)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.destination</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> (same for all the other non-exit objects)</p></li>
</ul>
<p>You can also include this information in searches:</p>