mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 05:46:31 +01:00
456 lines
No EOL
42 KiB
HTML
456 lines
No EOL
42 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>Coordinates — Evennia 0.9.5 documentation</title>
|
||
<link rel="stylesheet" href="_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||
<script src="_static/jquery.js"></script>
|
||
<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" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="genindex.html" title="General Index"
|
||
accesskey="I">index</a></li>
|
||
<li class="right" >
|
||
<a href="py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Coordinates</a></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="coordinates">
|
||
<h1>Coordinates<a class="headerlink" href="#coordinates" title="Permalink to this headline">¶</a></h1>
|
||
</section>
|
||
<section class="tex2jax_ignore mathjax_ignore" id="adding-room-coordinates-in-your-game">
|
||
<h1>Adding room coordinates in your game<a class="headerlink" href="#adding-room-coordinates-in-your-game" title="Permalink to this headline">¶</a></h1>
|
||
<p>This tutorial is moderately difficult in content. You might want to be familiar and at ease with
|
||
some Python concepts (like properties) and possibly Django concepts (like queries), although this
|
||
tutorial will try to walk you through the process and give enough explanations each time. If you
|
||
don’t feel very confident with math, don’t hesitate to pause, go to the example section, which shows
|
||
a tiny map, and try to walk around the code or read the explanation.</p>
|
||
<p>Evennia doesn’t have a coordinate system by default. Rooms and other objects are linked by location
|
||
and content:</p>
|
||
<ul class="simple">
|
||
<li><p>An object can be in a location, that is, another object. Like an exit in a room.</p></li>
|
||
<li><p>An object can access its content. A room can see what objects uses it as location (that would
|
||
include exits, rooms, characters and so on).</p></li>
|
||
</ul>
|
||
<p>This system allows for a lot of flexibility and, fortunately, can be extended by other systems.
|
||
Here, I offer you a way to add coordinates to every room in a way most compliant with Evennia
|
||
design. This will also show you how to use coordinates, find rooms around a given point for
|
||
instance.</p>
|
||
<section id="coordinates-as-tags">
|
||
<h2>Coordinates as tags<a class="headerlink" href="#coordinates-as-tags" title="Permalink to this headline">¶</a></h2>
|
||
<p>The first concept might be the most surprising at first glance: we will create coordinates as
|
||
<a class="reference internal" href="Tags.html"><span class="doc std std-doc">tags</span></a>.</p>
|
||
<blockquote>
|
||
<div><p>Why not attributes, wouldn’t that be easier?</p>
|
||
</div></blockquote>
|
||
<p>It would. We could just do something like <code class="docutils literal notranslate"><span class="pre">room.db.x</span> <span class="pre">=</span> <span class="pre">3</span></code>. The advantage of using tags is that it
|
||
will be easy and effective to search. Although this might not seem like a huge advantage right now,
|
||
with a database of thousands of rooms, it might make a difference, particularly if you have a lot of
|
||
things based on coordinates.</p>
|
||
<p>Rather than giving you a step-by-step process, I’ll show you the code. Notice that we use
|
||
properties to easily access and update coordinates. This is a Pythonic approach. Here’s our first
|
||
<code class="docutils literal notranslate"><span class="pre">Room</span></code> class, that you can modify in <code class="docutils literal notranslate"><span class="pre">typeclasses/rooms.py</span></code>:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in typeclasses/rooms.py</span>
|
||
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">DefaultRoom</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Rooms are like any Object, except their location is None</span>
|
||
<span class="sd"> (which is default). They also use basetype_setup() to</span>
|
||
<span class="sd"> add locks so they cannot be puppeted or picked up.</span>
|
||
<span class="sd"> (to change that, use at_object_creation instead)</span>
|
||
|
||
<span class="sd"> See examples/object.py for a list of</span>
|
||
<span class="sd"> properties and methods available on all Objects.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="nd">@property</span>
|
||
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Return the X coordinate or None."""</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||
|
||
<span class="nd">@x</span><span class="o">.</span><span class="n">setter</span>
|
||
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
|
||
<span class="sd">"""Change the X coordinate."""</span>
|
||
<span class="n">old</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">old</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</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="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
|
||
<span class="nd">@property</span>
|
||
<span class="k">def</span> <span class="nf">y</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Return the Y coordinate or None."""</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||
|
||
<span class="nd">@y</span><span class="o">.</span><span class="n">setter</span>
|
||
<span class="k">def</span> <span class="nf">y</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
|
||
<span class="sd">"""Change the Y coordinate."""</span>
|
||
<span class="n">old</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">old</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">y</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</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="nb">str</span><span class="p">(</span><span class="n">y</span><span class="p">),</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</span>
|
||
|
||
<span class="nd">@property</span>
|
||
<span class="k">def</span> <span class="nf">z</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Return the Z coordinate or None."""</span>
|
||
<span class="n">z</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">z</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||
|
||
<span class="nd">@z</span><span class="o">.</span><span class="n">setter</span>
|
||
<span class="k">def</span> <span class="nf">z</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">z</span><span class="p">):</span>
|
||
<span class="sd">"""Change the Z coordinate."""</span>
|
||
<span class="n">old</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">old</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">z</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</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="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">),</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If you aren’t familiar with the concept of properties in Python, I encourage you to read a good
|
||
tutorial on the subject. <a class="reference external" href="https://www.programiz.com/python-programming/property">This article on Python properties</a>
|
||
is well-explained and should help you understand the idea.</p>
|
||
<p>Let’s look at our properties for <code class="docutils literal notranslate"><span class="pre">x</span></code>. First of all is the read property.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="nd">@property</span>
|
||
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="sd">"""Return the X coordinate or None."""</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>What it does is pretty simple:</p>
|
||
<ol class="simple">
|
||
<li><p>It gets the tag of category <code class="docutils literal notranslate"><span class="pre">"coordx"</span></code>. It’s the tag category where we store our X coordinate.
|
||
The <code class="docutils literal notranslate"><span class="pre">tags.get</span></code> method will return <code class="docutils literal notranslate"><span class="pre">None</span></code> if the tag can’t be found.</p></li>
|
||
<li><p>We convert the value to an integer, if it’s a <code class="docutils literal notranslate"><span class="pre">str</span></code>. Remember that tags can only contain <code class="docutils literal notranslate"><span class="pre">str</span></code>,
|
||
so we’ll need to convert it.</p></li>
|
||
</ol>
|
||
<blockquote>
|
||
<div><p>I thought tags couldn’t contain values?</p>
|
||
</div></blockquote>
|
||
<p>Well, technically, they can’t: they’re either here or not. But using tag categories, as we have
|
||
done, we get a tag, knowing only its category. That’s the basic approach to coordinates in this
|
||
tutorial.</p>
|
||
<p>Now, let’s look at the method that will be called when we wish to set <code class="docutils literal notranslate"><span class="pre">x</span></code> in our room:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="nd">@x</span><span class="o">.</span><span class="n">setter</span>
|
||
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
|
||
<span class="sd">"""Change the X coordinate."""</span>
|
||
<span class="n">old</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">old</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</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="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<ol class="simple">
|
||
<li><p>First, we remove the old X coordinate, if it exists. Otherwise, we’d end up with two tags in our
|
||
room with “coordx” as their category, which wouldn’t do at all.</p></li>
|
||
<li><p>Then we add the new tag, giving it the proper category.</p></li>
|
||
</ol>
|
||
<blockquote>
|
||
<div><p>Now what?</p>
|
||
</div></blockquote>
|
||
<p>If you add this code and reload your game, once you’re logged in with a character in a room as its
|
||
location, you can play around:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="n">here</span><span class="o">.</span><span class="n">x</span>
|
||
<span class="nd">@py</span> <span class="n">here</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="nd">@py</span> <span class="n">here</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="nd">@py</span> <span class="n">here</span><span class="o">.</span><span class="n">z</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span>
|
||
<span class="nd">@py</span> <span class="n">here</span><span class="o">.</span><span class="n">z</span> <span class="o">=</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The code might not be that easy to read, but you have to admit it’s fairly easy to use.</p>
|
||
</section>
|
||
<section id="some-additional-searches">
|
||
<h2>Some additional searches<a class="headerlink" href="#some-additional-searches" title="Permalink to this headline">¶</a></h2>
|
||
<p>Having coordinates is useful for several reasons:</p>
|
||
<ol class="simple">
|
||
<li><p>It can help in shaping a truly logical world, in its geography, at least.</p></li>
|
||
<li><p>It can allow to look for specific rooms at given coordinates.</p></li>
|
||
<li><p>It can be good in order to quickly find the rooms around a location.</p></li>
|
||
<li><p>It can even be great in path-finding (finding the shortest path between two rooms).</p></li>
|
||
</ol>
|
||
<p>So far, our coordinate system can help with 1., but not much else. Here are some methods that we
|
||
could add to the <code class="docutils literal notranslate"><span class="pre">Room</span></code> typeclass. These methods will just be search methods. Notice that they are
|
||
class methods, since we want to get rooms.</p>
|
||
<section id="finding-one-room">
|
||
<h3>Finding one room<a class="headerlink" href="#finding-one-room" title="Permalink to this headline">¶</a></h3>
|
||
<p>First, a simple one: how to find a room at a given coordinate? Say, what is the room at X=0, Y=0,
|
||
Z=0?</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">):</span>
|
||
<span class="c1"># ...</span>
|
||
<span class="nd">@classmethod</span>
|
||
<span class="k">def</span> <span class="nf">get_room_at</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Return the room at the given location or None if not found.</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> x (int): the X coord.</span>
|
||
<span class="sd"> y (int): the Y coord.</span>
|
||
<span class="sd"> z (int): the Z coord.</span>
|
||
|
||
<span class="sd"> Return:</span>
|
||
<span class="sd"> The room at this location (Room) or None if not found.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">rooms</span> <span class="o">=</span> <span class="bp">cls</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="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</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="nb">str</span><span class="p">(</span><span class="n">y</span><span class="p">),</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</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="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">),</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">rooms</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">rooms</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
|
||
<span class="k">return</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This solution includes a bit of <a class="reference external" href="https://docs.djangoproject.com/en/1.11/topics/db/queries/">Django
|
||
queries</a>.
|
||
Basically, what we do is reach for the object manager and search for objects with the matching tags.
|
||
Again, don’t spend too much time worrying about the mechanism, the method is quite easy to use:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Room</span><span class="o">.</span><span class="n">get_room_at</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Notice that this is a class method: you will call it from <code class="docutils literal notranslate"><span class="pre">Room</span></code> (the class), not an instance.
|
||
Though you still can:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>@py here.get_room_at(3, 8, 0)
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="finding-several-rooms">
|
||
<h3>Finding several rooms<a class="headerlink" href="#finding-several-rooms" title="Permalink to this headline">¶</a></h3>
|
||
<p>Here’s another useful method that allows us to look for rooms around a given coordinate. This is
|
||
more advanced search and doing some calculation, beware! Look at the following section if you’re
|
||
lost.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">sqrt</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">DefaultRoom</span><span class="p">):</span>
|
||
|
||
<span class="c1"># ...</span>
|
||
|
||
<span class="nd">@classmethod</span>
|
||
<span class="k">def</span> <span class="nf">get_rooms_around</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">,</span> <span class="n">distance</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> Return the list of rooms around the given coordinates.</span>
|
||
|
||
<span class="sd"> This method returns a list of tuples (distance, room) that</span>
|
||
<span class="sd"> can easily be browsed. This list is sorted by distance (the</span>
|
||
<span class="sd"> closest room to the specified position is always at the top</span>
|
||
<span class="sd"> of the list).</span>
|
||
|
||
<span class="sd"> Args:</span>
|
||
<span class="sd"> x (int): the X coord.</span>
|
||
<span class="sd"> y (int): the Y coord.</span>
|
||
<span class="sd"> z (int): the Z coord.</span>
|
||
<span class="sd"> distance (int): the maximum distance to the specified position.</span>
|
||
|
||
<span class="sd"> Returns:</span>
|
||
<span class="sd"> A list of tuples containing the distance to the specified</span>
|
||
<span class="sd"> position and the room at this distance. Several rooms</span>
|
||
<span class="sd"> can be at equal distance from the position.</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="c1"># Performs a quick search to only get rooms in a square</span>
|
||
<span class="n">x_r</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]))</span>
|
||
<span class="n">x_r</span> <span class="o">+=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
|
||
<span class="n">y_r</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">y</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]))</span>
|
||
<span class="n">y_r</span> <span class="o">+=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
|
||
<span class="n">z_r</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]))</span>
|
||
<span class="n">z_r</span> <span class="o">+=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">distance</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
|
||
<span class="n">wide</span> <span class="o">=</span> <span class="bp">cls</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__in</span><span class="o">=</span><span class="n">x_r</span><span class="p">,</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span>
|
||
<span class="n">db_tags__db_key__in</span><span class="o">=</span><span class="n">y_r</span><span class="p">,</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span>
|
||
<span class="n">db_tags__db_key__in</span><span class="o">=</span><span class="n">z_r</span><span class="p">,</span> <span class="n">db_tags__db_category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># We now need to filter down this list to find out whether</span>
|
||
<span class="c1"># these rooms are really close enough, and at what distance</span>
|
||
<span class="c1"># In short: we change the square to a circle.</span>
|
||
<span class="n">rooms</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">wide</span><span class="p">:</span>
|
||
<span class="n">x2</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">room</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordx"</span><span class="p">))</span>
|
||
<span class="n">y2</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">room</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordy"</span><span class="p">))</span>
|
||
<span class="n">z2</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">room</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">category</span><span class="o">=</span><span class="s2">"coordz"</span><span class="p">))</span>
|
||
<span class="n">distance_to_room</span> <span class="o">=</span> <span class="n">sqrt</span><span class="p">(</span>
|
||
<span class="p">(</span><span class="n">x2</span> <span class="o">-</span> <span class="n">x</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="n">y2</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="n">z2</span> <span class="o">-</span> <span class="n">z</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">distance_to_room</span> <span class="o"><=</span> <span class="n">distance</span><span class="p">:</span>
|
||
<span class="n">rooms</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">distance_to_room</span><span class="p">,</span> <span class="n">room</span><span class="p">))</span>
|
||
|
||
<span class="c1"># Finally sort the rooms by distance</span>
|
||
<span class="n">rooms</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">tup</span><span class="p">:</span> <span class="n">tup</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="k">return</span> <span class="n">rooms</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This gets more serious.</p>
|
||
<ol class="simple">
|
||
<li><p>We have specified coordinates as parameters. We determine a broad range using the distance.
|
||
That is, for each coordinate, we create a list of possible matches. See the example below.</p></li>
|
||
<li><p>We then search for the rooms within this broader range. It gives us a square
|
||
around our location. Some rooms are definitely outside the range. Again, see the example below
|
||
to follow the logic.</p></li>
|
||
<li><p>We filter down the list and sort it by distance from the specified coordinates.</p></li>
|
||
</ol>
|
||
<p>Notice that we only search starting at step 2. Thus, the Django search doesn’t look and cache all
|
||
objects, just a wider range than what would be really necessary. This method returns a circle of
|
||
coordinates around a specified point. Django looks for a square. What wouldn’t fit in the circle
|
||
is removed at step 3, which is the only part that includes systematic calculation. This method is
|
||
optimized to be quick and efficient.</p>
|
||
</section>
|
||
<section id="an-example">
|
||
<h3>An example<a class="headerlink" href="#an-example" title="Permalink to this headline">¶</a></h3>
|
||
<p>An example might help. Consider this very simple map (a textual description follows):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">4</span> <span class="n">A</span> <span class="n">B</span> <span class="n">C</span> <span class="n">D</span>
|
||
<span class="mi">3</span> <span class="n">E</span> <span class="n">F</span> <span class="n">G</span> <span class="n">H</span>
|
||
<span class="mi">2</span> <span class="n">I</span> <span class="n">J</span> <span class="n">K</span> <span class="n">L</span>
|
||
<span class="mi">1</span> <span class="n">M</span> <span class="n">N</span> <span class="n">O</span> <span class="n">P</span>
|
||
<span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The X coordinates are given below. The Y coordinates are given on the left. This is a simple
|
||
square with 16 rooms: 4 on each line, 4 lines of them. All the rooms are identified by letters in
|
||
this example: the first line at the top has rooms A to D, the second E to H, the third I to L and
|
||
the fourth M to P. The bottom-left room, X=1 and Y=1, is M. The upper-right room X=4 and Y=4 is D.</p>
|
||
<p>So let’s say we want to find all the neighbors, distance 1, from the room J. J is at X=2, Y=2.</p>
|
||
<p>So we use:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Room.get_rooms_around(x=2, y=2, z=0, distance=1)
|
||
# we'll assume a z coordinate of 0 for simplicity
|
||
</pre></div>
|
||
</div>
|
||
<ol class="simple">
|
||
<li><p>First, this method gets all the rooms in a square around J. So it gets E F G, I J K, M N O. If
|
||
you want, draw the square around these coordinates to see what’s happening.</p></li>
|
||
<li><p>Next, we browse over this list and check the real distance between J (X=2, Y=2) and the room.
|
||
The four corners of the square are not in this circle. For instance, the distance between J and M
|
||
is not 1. If you draw a circle of center J and radius 1, you’ll notice that the four corners of our
|
||
square (E, G, M and O) are not in this circle. So we remove them.</p></li>
|
||
<li><p>We sort by distance from J.</p></li>
|
||
</ol>
|
||
<p>So in the end we might obtain something like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span>
|
||
<span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">J</span><span class="p">),</span> <span class="c1"># yes, J is part of this circle after all, with a distance of 0</span>
|
||
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">F</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">I</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">K</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">N</span><span class="p">),</span>
|
||
<span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can try with more examples if you want to see this in action.</p>
|
||
</section>
|
||
<section id="to-conclude">
|
||
<h3>To conclude<a class="headerlink" href="#to-conclude" title="Permalink to this headline">¶</a></h3>
|
||
<p>You can definitely use this system to map other objects, not just rooms. You can easily remove the
|
||
`Z coordinate too, if you simply need X and Y.</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="index.html">
|
||
<img class="logo" src="_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div id="searchbox" style="display: none" role="search">
|
||
<h3 id="searchlabel">Quick search</h3>
|
||
<div class="searchformwrapper">
|
||
<form class="search" action="search.html" method="get">
|
||
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<p><h3><a href="index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">Coordinates</a></li>
|
||
<li><a class="reference internal" href="#adding-room-coordinates-in-your-game">Adding room coordinates in your game</a><ul>
|
||
<li><a class="reference internal" href="#coordinates-as-tags">Coordinates as tags</a></li>
|
||
<li><a class="reference internal" href="#some-additional-searches">Some additional searches</a><ul>
|
||
<li><a class="reference internal" href="#finding-one-room">Finding one room</a></li>
|
||
<li><a class="reference internal" href="#finding-several-rooms">Finding several rooms</a></li>
|
||
<li><a class="reference internal" href="#an-example">An example</a></li>
|
||
<li><a class="reference internal" href="#to-conclude">To conclude</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="_sources/Coordinates.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div><h3>Links</h3>
|
||
<ul>
|
||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||
<li><a href="http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb">IRC</a> -
|
||
<a href="https://discord.gg/NecFePw">Discord</a> -
|
||
<a href="https://groups.google.com/forum/#%21forum/evennia">Forums</a>
|
||
</li>
|
||
<li><a href="http://evennia.blogspot.com/">Evennia Dev blog</a> </li>
|
||
</ul>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="../1.0-dev/index.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="Coordinates.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
</ul>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="genindex.html" title="General Index"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Coordinates</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |