evennia/docs/0.9.5/Dynamic-In-Game-Map.html
2020-11-14 11:55:52 +01:00

846 lines
No EOL
66 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dynamic In Game Map &#8212; 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>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Implementing a game rule system" href="Implementing-a-game-rule-system.html" />
<link rel="prev" title="Static In Game Map" href="Static-In-Game-Map.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="right" >
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Static-In-Game-Map.html" title="Static In Game Map"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Tutorials.html" accesskey="U">Tutorials</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Dynamic In Game Map</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="dynamic-in-game-map">
<h1>Dynamic In Game Map<a class="headerlink" href="#dynamic-in-game-map" title="Permalink to this headline"></a></h1>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p>An often desired feature in a MUD is to show an in-game map to help navigation. The <a class="reference internal" href="Static-In-Game-Map.html"><span class="doc">Static in-game
map</span></a> tutorial solves this by creating a <em>static</em> map, meaning the map is pre-
drawn once and for all - the rooms are then created to match that map. When walking around, parts of
the static map is then cut out and displayed next to the room description.</p>
<p>In this tutorial well instead do it the other way around; We will dynamically draw the map based on
the relationships we find between already existing rooms.</p>
</div>
<div class="section" id="the-grid-of-rooms">
<h2>The Grid of Rooms<a class="headerlink" href="#the-grid-of-rooms" title="Permalink to this headline"></a></h2>
<p>There are at least two requirements needed for this tutorial to work.</p>
<ol class="simple">
<li><p>The structure of your mud has to follow a logical layout. Evennia supports the layout of your
world to be logically impossible with rooms looping to themselves or exits leading to the other
side of the map. Exits can also be named anything, from “jumping out the window” to “into the fifth
dimension”. This tutorial assumes you can only move in the cardinal directions (N, E, S and W).</p></li>
<li><p>Rooms must be connected and linked together for the map to be generated correctly. Vanilla
Evennia comes with a admin command <a class="reference external" href="Default-Command-Help.html#tunnel-cmdtunnel">&#64;tunnel</a> that allows a
user to create rooms in the cardinal directions, but additional work is needed to assure that rooms
are connected. For example, if you <code class="docutils literal notranslate"><span class="pre">&#64;tunnel</span> <span class="pre">east</span></code> and then immediately do <code class="docutils literal notranslate"><span class="pre">&#64;tunnel</span> <span class="pre">west</span></code> youll find
that you have created two completely stand-alone rooms. So care is needed if you want to create a
“logical” layout. In this tutorial we assume you have such a grid of rooms that we can generate the
map from.</p></li>
</ol>
</div>
<div class="section" id="concept">
<h2>Concept<a class="headerlink" href="#concept" title="Permalink to this headline"></a></h2>
<p>Before getting into the code, it is beneficial to understand and conceptualize how this is going to
work. The idea is analogous to a worm that starts at your current position. It chooses a direction
and walks outward from it, mapping its route as it goes. Once it has traveled a pre-set distance
it stops and starts over in another direction. An important note is that we want a system which is
easily callable and not too complicated. Therefore we will wrap this entire code into a custom
Python class (not a typeclass as this doesnt use any core objects from evennia itself).</p>
<p>We are going to create something that displays like this when you type look:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">Hallway</span>
<span class="p">[</span><span class="o">.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="p">]</span>
<span class="p">[</span><span class="o">@</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">]</span>
<span class="p">[</span><span class="o">.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="p">]</span>
<span class="n">The</span> <span class="n">distant</span> <span class="n">echoes</span> <span class="n">of</span> <span class="n">the</span> <span class="n">forgotten</span>
<span class="n">wail</span> <span class="n">throughout</span> <span class="n">the</span> <span class="n">empty</span> <span class="n">halls</span><span class="o">.</span>
<span class="n">Exits</span><span class="p">:</span> <span class="n">North</span><span class="p">,</span> <span class="n">East</span><span class="p">,</span> <span class="n">South</span>
</pre></div>
</div>
<p>Your current location is defined by <code class="docutils literal notranslate"><span class="pre">[&#64;]</span></code> while the <code class="docutils literal notranslate"><span class="pre">[.]</span></code>s are other rooms that the “worm” has seen
since departing from your location.</p>
</div>
<div class="section" id="setting-up-the-map-display">
<h2>Setting up the Map Display<a class="headerlink" href="#setting-up-the-map-display" title="Permalink to this headline"></a></h2>
<p>First we must define the components for displaying the map. For the “worm” to know what symbol to
draw on the map we will have it check an Attribute on the room it visits called <code class="docutils literal notranslate"><span class="pre">sector_type</span></code>. For
this tutorial we understand two symbols - a normal room and the room with us in it. We also define a
fallback symbol for rooms without said Attribute - that way the map will still work even if we
didnt prepare the room correctly. Assuming your game folder is named <code class="docutils literal notranslate"><span class="pre">mygame</span></code>, we create this code
in <code class="docutils literal notranslate"><span class="pre">mygame/world/map.py.</span></code></p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/map.py</span>
<span class="c1"># the symbol is identified with a key &quot;sector_type&quot; on the</span>
<span class="c1"># Room. Keys None and &quot;you&quot; must always exist.</span>
<span class="n">SYMBOLS</span> <span class="o">=</span> <span class="p">{</span> <span class="bp">None</span> <span class="p">:</span> <span class="s1">&#39; . &#39;</span><span class="p">,</span> <span class="c1"># for rooms without sector_type Attribute</span>
<span class="s1">&#39;you&#39;</span> <span class="p">:</span> <span class="s1">&#39;[@]&#39;</span><span class="p">,</span>
<span class="s1">&#39;SECT_INSIDE&#39;</span><span class="p">:</span> <span class="s1">&#39;[.]&#39;</span> <span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>Since trying to access an unset Attribute returns <code class="docutils literal notranslate"><span class="pre">None</span></code>, this means rooms without the <code class="docutils literal notranslate"><span class="pre">sector_type</span></code>
Atttribute will show as <code class="docutils literal notranslate"><span class="pre">.</span></code>. Next we start building the custom class <code class="docutils literal notranslate"><span class="pre">Map</span></code>. It will hold all
methods we need.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/map.py</span>
<span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</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">caller</span><span class="p">,</span> <span class="n">max_width</span><span class="o">=</span><span class="mi">9</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">9</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">caller</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_width</span> <span class="o">=</span> <span class="n">max_width</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_length</span> <span class="o">=</span> <span class="n">max_length</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> <span class="bp">None</span>
</pre></div>
</td></tr></table></div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">self.caller</span></code> is normally your Character object, the one using the map.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.max_width/length</span></code> determine the max width and length of the map that will be generated. Note
that its important that these variables are set to <em>odd</em> numbers to make sure the display area has
a center point.</p></li>
<li><p><code class="docutils literal notranslate"> <span class="pre">self.worm_has_mapped</span></code> is building off the worm analogy above. This dictionary will store all
rooms the “worm” has mapped as well as its relative position within the grid. This is the most
important variable as it acts as a checker and address book that is able to tell us where the
worm has been and what it has mapped so far.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.curX/Y</span></code> are coordinates representing the worms current location on the grid.</p></li>
</ul>
<p>Before any sort of mapping can actually be done we need to create an empty display area and do some
sanity checks on it by using the following methods.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/map.py</span>
<span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="c1"># [... continued]</span>
<span class="k">def</span> <span class="nf">create_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># This method simply creates an empty grid/display area</span>
<span class="c1"># with the specified variables from __init__(self):</span>
<span class="n">board</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_width</span><span class="p">):</span>
<span class="n">board</span><span class="o">.</span><span class="n">append</span><span class="p">([])</span>
<span class="k">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_length</span><span class="p">):</span>
<span class="n">board</span><span class="p">[</span><span class="n">row</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">board</span>
<span class="k">def</span> <span class="nf">check_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># this method simply checks the grid to make sure</span>
<span class="c1"># that both max_l and max_w are odd numbers.</span>
<span class="k">return</span> <span class="bp">True</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_length</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_width</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span>\
<span class="k">else</span> <span class="bp">False</span>
</pre></div>
</td></tr></table></div>
<p>Before we can set our worm on its way, we need to know some of the computer science behind all this
called Graph Traversing. In Pseudo code what we are trying to accomplish is this:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># pseudo code</span>
<span class="k">def</span> <span class="nf">draw_room_on_map</span><span class="p">(</span><span class="n">room</span><span class="p">,</span> <span class="n">max_distance</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">room</span><span class="p">)</span>
<span class="k">if</span> <span class="n">max_distance</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">for</span> <span class="nb">exit</span> <span class="ow">in</span> <span class="n">room</span><span class="o">.</span><span class="n">exits</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_drawn</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">):</span>
<span class="c1"># skip drawing if we already visited the destination</span>
<span class="k">continue</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># first time here!</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw_room_on_map</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">,</span> <span class="n">max_distance</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>The beauty of Python is that our actual code of doing this doesnt differ much if at all from this
Pseudo code example.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">max_distance</span></code> is a variable indicating to our Worm how many rooms AWAY from your current location
will it map. Obviously the larger the number the more time it will take if your current location has
many many rooms around you.</p></li>
</ul>
<p>The first hurdle here is what value to use for max_distance. There is no reason for the worm to
travel further than what is actually displayed to you. For example, if your current location is
placed in the center of a display area of size <code class="docutils literal notranslate"><span class="pre">max_length</span> <span class="pre">=</span> <span class="pre">max_width</span> <span class="pre">=</span> <span class="pre">9</span></code>, then the worm need only
go <code class="docutils literal notranslate"><span class="pre">4</span></code> spaces in either direction:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">@</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">][</span><span class="o">.</span><span class="p">]</span>
<span class="mi">4</span> <span class="mi">3</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">0</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 max_distance can be set dynamically based on the size of the display area. As your width/length
changes it becomes a simple algebraic linear relationship which is simply <code class="docutils literal notranslate"><span class="pre">max_distance</span> <span class="pre">=</span> <span class="pre">(min(max_width,</span> <span class="pre">max_length)</span> <span class="pre">-1)</span> <span class="pre">/</span> <span class="pre">2</span></code>.</p>
</div>
<div class="section" id="building-the-mapper">
<h2>Building the Mapper<a class="headerlink" href="#building-the-mapper" title="Permalink to this headline"></a></h2>
<p>Now we can start to fill our Map object with some methods. We are still missing a few methods that
are very important:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">self.draw(self,</span> <span class="pre">room)</span></code> - responsible for actually drawing room to grid.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.has_drawn(self,</span> <span class="pre">room)</span></code> - checks to see if the room has been mapped and worm has already been
here.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.median(self,</span> <span class="pre">number)</span></code> - a simple utility method that finds the median (middle point) from 0,
n</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.update_pos(self,</span> <span class="pre">room,</span> <span class="pre">exit_name)</span></code> - updates the worms physical position by reassigning
self.curX/Y. .accordingly</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.start_loc_on_grid(self)</span></code> - the very first initial draw on the grid representing your
location in the middle of the grid</p></li>
<li><p>self.show_map<code class="docutils literal notranslate"> <span class="pre">-</span> <span class="pre">after</span> <span class="pre">everything</span> <span class="pre">is</span> <span class="pre">done</span> <span class="pre">convert</span> <span class="pre">the</span> <span class="pre">map</span> <span class="pre">into</span> <span class="pre">a</span> <span class="pre">readable</span> <span class="pre">string</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">self.draw_room_on_map(self,</span> <span class="pre">room,</span> <span class="pre">max_distance)</span></code> - the main method that ties it all together.`</p></li>
</ul>
<p>Now that we know which methods we need, lets refine our initial <code class="docutils literal notranslate"><span class="pre">__init__(self)</span></code> to pass some
conditional statements and set it up to start building the display.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#mygame/world/map.py</span>
<span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</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">caller</span><span class="p">,</span> <span class="n">max_width</span><span class="o">=</span><span class="mi">9</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">9</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">caller</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_width</span> <span class="o">=</span> <span class="n">max_width</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_length</span> <span class="o">=</span> <span class="n">max_length</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_grid</span><span class="p">():</span>
<span class="c1"># we have to store the grid into a variable</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_grid</span><span class="p">()</span>
<span class="c1"># we use the algebraic relationship</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw_room_on_map</span><span class="p">(</span><span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="p">,</span>
<span class="p">((</span><span class="nb">min</span><span class="p">(</span><span class="n">max_width</span><span class="p">,</span> <span class="n">max_length</span><span class="p">)</span> <span class="o">-</span><span class="mi">1</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>Here we check to see if the parameters for the grid are okay, then we create an empty canvas and map
our initial location as the first room!</p>
<p>As mentioned above, the code for the <code class="docutils literal notranslate"><span class="pre">self.draw_room_on_map()</span></code> is not much different than the Pseudo
code. The method is shown below:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/world/map.py, in the Map class</span>
<span class="k">def</span> <span class="nf">draw_room_on_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">,</span> <span class="n">max_distance</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">room</span><span class="p">)</span>
<span class="k">if</span> <span class="n">max_distance</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">for</span> <span class="nb">exit</span> <span class="ow">in</span> <span class="n">room</span><span class="o">.</span><span class="n">exits</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">exit</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;north&quot;</span><span class="p">,</span> <span class="s2">&quot;east&quot;</span><span class="p">,</span> <span class="s2">&quot;west&quot;</span><span class="p">,</span> <span class="s2">&quot;south&quot;</span><span class="p">):</span>
<span class="c1"># we only map in the cardinal directions. Mapping up/down would be</span>
<span class="c1"># an interesting learning project for someone who wanted to try it.</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_drawn</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">):</span>
<span class="c1"># we&#39;ve been to the destination already, skip ahead.</span>
<span class="k">continue</span>
<span class="bp">self</span><span class="o">.</span><span class="n">update_pos</span><span class="p">(</span><span class="n">room</span><span class="p">,</span> <span class="nb">exit</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw_room_on_map</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">,</span> <span class="n">max_distance</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
<p>The first thing the “worm” does is to draw your current location in <code class="docutils literal notranslate"><span class="pre">self.draw</span></code>. Lets define that…</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#in mygame/word/map.py, in the Map class</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">):</span>
<span class="c1"># draw initial ch location on map first!</span>
<span class="k">if</span> <span class="n">room</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">location</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">start_loc_on_grid</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># map all other rooms</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span>
<span class="c1"># this will use the sector_type Attribute or None if not set.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">][</span><span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span> <span class="o">=</span> <span class="n">SYMBOLS</span><span class="p">[</span><span class="n">room</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">sector_type</span><span class="p">]</span>
</pre></div>
</td></tr></table></div>
<p>In <code class="docutils literal notranslate"><span class="pre">self.start_loc_on_grid()</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">median</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num</span><span class="p">):</span>
<span class="n">lst</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">num</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lst</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">return</span> <span class="p">(</span><span class="n">lst</span><span class="p">[</span><span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">lst</span><span class="p">[</span><span class="n">m</span><span class="o">//</span><span class="mi">2</span><span class="p">])</span> <span class="o">/</span> <span class="mf">2.0</span>
<span class="k">def</span> <span class="nf">start_loc_on_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_width</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_length</span><span class="p">)</span>
<span class="c1"># x and y are floats by default, can&#39;t index lists with float types</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</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="o">=</span> <span class="n">SYMBOLS</span><span class="p">[</span><span class="s1">&#39;you&#39;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="c1"># updating worms current location</span>
</pre></div>
</td></tr></table></div>
<p>After the system has drawn the current map it checks to see if the <code class="docutils literal notranslate"><span class="pre">max_distance</span></code> is <code class="docutils literal notranslate"><span class="pre">0</span></code> (since this
is the inital start phase it is not). Now we handle the iteration once we have each individual exit
in the room. The first thing it does is check if the room the Worm is in has been mapped already..
lets define that…</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">has_drawn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">True</span> <span class="k">if</span> <span class="n">room</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span> <span class="k">else</span> <span class="bp">False</span>
</pre></div>
</td></tr></table></div>
<p>If <code class="docutils literal notranslate"><span class="pre">has_drawn</span></code> returns <code class="docutils literal notranslate"><span class="pre">False</span></code> that means the worm has found a room that hasnt been mapped yet. It
will then move there. The self.curX/Y sort of lags behind, so we have to make sure to track the
position of the worm; we do this in <code class="docutils literal notranslate"><span class="pre">self.update_pos()</span></code> below.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">update_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">,</span> <span class="n">exit_name</span><span class="p">):</span>
<span class="c1"># this ensures the coordinates stays up to date</span>
<span class="c1"># to where the worm is currently at.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> \
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
<span class="c1"># now we have to actually move the pointer</span>
<span class="c1"># variables depending on which &#39;exit&#39; it found</span>
<span class="k">if</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;east&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;west&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;north&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;south&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>
</td></tr></table></div>
<p>Once the system updates the position of the worm it feeds the new room back into the original
<code class="docutils literal notranslate"><span class="pre">draw_room_on_map()</span></code> and starts the process all over again..</p>
<p>That is essentially the entire thing. The final method is to bring it all together and make a nice
presentational string out of it using the <code class="docutils literal notranslate"><span class="pre">self.show_map()</span></code> method.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">show_map</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">map_string</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">grid</span><span class="p">:</span>
<span class="n">map_string</span> <span class="o">+=</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
<span class="n">map_string</span> <span class="o">+=</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="k">return</span> <span class="n">map_string</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="using-the-map">
<h2>Using the Map<a class="headerlink" href="#using-the-map" title="Permalink to this headline"></a></h2>
<p>In order for the map to get triggered we store it on the Room typeclass. If we put it in
<code class="docutils literal notranslate"><span class="pre">return_appearance</span></code> we will get the map back every time we look at the room.</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">return_appearance</span></code> is a default Evennia hook available on all objects; it is called e.g. by the
<code class="docutils literal notranslate"><span class="pre">look</span></code> command to get the description of something (the room in this case).</p>
</div></blockquote>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># in mygame/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="kn">from</span> <span class="nn">world.map</span> <span class="kn">import</span> <span class="n">Map</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="k">def</span> <span class="nf">return_appearance</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">looker</span><span class="p">):</span>
<span class="c1"># [...]</span>
<span class="n">string</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">Map</span><span class="p">(</span><span class="n">looker</span><span class="p">)</span><span class="o">.</span><span class="n">show_map</span><span class="p">()</span>
<span class="c1"># Add all the normal stuff like room description,</span>
<span class="c1"># contents, exits etc.</span>
<span class="n">string</span> <span class="o">+=</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span> <span class="o">+</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">return_appearance</span><span class="p">(</span><span class="n">looker</span><span class="p">)</span>
<span class="k">return</span> <span class="n">string</span>
</pre></div>
</td></tr></table></div>
<p>Obviously this method of generating maps doesnt take into account of any doors or exits that are
hidden.. etc.. but hopefully it serves as a good base to start with. Like previously mentioned, it
is very important to have a solid foundation on rooms before implementing this. You can try this on
vanilla evennia by using &#64;tunnel and essentially you can just create a long straight/edgy non-
looping rooms that will show on your in-game map.</p>
<p>The above example will display the map above the room description. You could also use an
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/evennia.utils.evtable">EvTable</a> to place description and map next to each other. Some other
things you can do is to have a <a class="reference internal" href="Commands.html"><span class="doc">Command</span></a> that displays with a larger radius, maybe with a
legend and other features.</p>
<p>Below is the whole <code class="docutils literal notranslate"><span class="pre">map.py</span></code> for your reference. You need to update your <code class="docutils literal notranslate"><span class="pre">Room</span></code> typeclass (see above)
to actually call it. Remember that to see different symbols for a location you also need to set the
<code class="docutils literal notranslate"><span class="pre">sector_type</span></code> Attribute on the room to one of the keys in the <code class="docutils literal notranslate"><span class="pre">SYMBOLS</span></code> dictionary. So in this
example, to make a room be mapped as <code class="docutils literal notranslate"><span class="pre">[.]</span></code> you would set the rooms <code class="docutils literal notranslate"><span class="pre">sector_type</span></code> to
<code class="docutils literal notranslate"><span class="pre">&quot;SECT_INSIDE&quot;</span></code>. Try it out with <code class="docutils literal notranslate"><span class="pre">&#64;set</span> <span class="pre">here/sector_type</span> <span class="pre">=</span> <span class="pre">&quot;SECT_INSIDE&quot;</span></code>. If you wanted all new
rooms to have a given sector symbol, you could change the default in the <code class="docutils literal notranslate"><span class="pre">SYMBOLS´</span> <span class="pre">dictionary</span> <span class="pre">below,</span> <span class="pre">or</span> <span class="pre">you</span> <span class="pre">could</span> <span class="pre">add</span> <span class="pre">the</span> <span class="pre">Attribute</span> <span class="pre">in</span> <span class="pre">the</span> <span class="pre">Room's</span> </code>at_object_creation` method.</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#mygame/world/map.py</span>
<span class="c1"># These are keys set with the Attribute sector_type on the room.</span>
<span class="c1"># The keys None and &quot;you&quot; must always exist.</span>
<span class="n">SYMBOLS</span> <span class="o">=</span> <span class="p">{</span> <span class="bp">None</span> <span class="p">:</span> <span class="s1">&#39; . &#39;</span><span class="p">,</span> <span class="c1"># for rooms without a sector_type attr</span>
<span class="s1">&#39;you&#39;</span> <span class="p">:</span> <span class="s1">&#39;[@]&#39;</span><span class="p">,</span>
<span class="s1">&#39;SECT_INSIDE&#39;</span><span class="p">:</span> <span class="s1">&#39;[.]&#39;</span> <span class="p">}</span>
<span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</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">caller</span><span class="p">,</span> <span class="n">max_width</span><span class="o">=</span><span class="mi">9</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">9</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">caller</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_width</span> <span class="o">=</span> <span class="n">max_width</span>
<span class="bp">self</span><span class="o">.</span><span class="n">max_length</span> <span class="o">=</span> <span class="n">max_length</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_grid</span><span class="p">():</span>
<span class="c1"># we actually have to store the grid into a variable</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_grid</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw_room_on_map</span><span class="p">(</span><span class="n">caller</span><span class="o">.</span><span class="n">location</span><span class="p">,</span>
<span class="p">((</span><span class="nb">min</span><span class="p">(</span><span class="n">max_width</span><span class="p">,</span> <span class="n">max_length</span><span class="p">)</span> <span class="o">-</span><span class="mi">1</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">update_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">,</span> <span class="n">exit_name</span><span class="p">):</span>
<span class="c1"># this ensures the pointer variables always</span>
<span class="c1"># stays up to date to where the worm is currently at.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> \
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
<span class="c1"># now we have to actually move the pointer</span>
<span class="c1"># variables depending on which &#39;exit&#39; it found</span>
<span class="k">if</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;east&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;west&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;north&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">exit_name</span> <span class="o">==</span> <span class="s1">&#39;south&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">draw_room_on_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">,</span> <span class="n">max_distance</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw</span><span class="p">(</span><span class="n">room</span><span class="p">)</span>
<span class="k">if</span> <span class="n">max_distance</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">for</span> <span class="nb">exit</span> <span class="ow">in</span> <span class="n">room</span><span class="o">.</span><span class="n">exits</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">exit</span><span class="o">.</span><span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;north&quot;</span><span class="p">,</span> <span class="s2">&quot;east&quot;</span><span class="p">,</span> <span class="s2">&quot;west&quot;</span><span class="p">,</span> <span class="s2">&quot;south&quot;</span><span class="p">):</span>
<span class="c1"># we only map in the cardinal directions. Mapping up/down would be</span>
<span class="c1"># an interesting learning project for someone who wanted to try it.</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_drawn</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">):</span>
<span class="c1"># we&#39;ve been to the destination already, skip ahead.</span>
<span class="k">continue</span>
<span class="bp">self</span><span class="o">.</span><span class="n">update_pos</span><span class="p">(</span><span class="n">room</span><span class="p">,</span> <span class="nb">exit</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">draw_room_on_map</span><span class="p">(</span><span class="nb">exit</span><span class="o">.</span><span class="n">destination</span><span class="p">,</span> <span class="n">max_distance</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">):</span>
<span class="c1"># draw initial caller location on map first!</span>
<span class="k">if</span> <span class="n">room</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">location</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">start_loc_on_grid</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># map all other rooms</span>
<span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="p">[</span><span class="n">room</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span>
<span class="c1"># this will use the sector_type Attribute or None if not set.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">][</span><span class="bp">self</span><span class="o">.</span><span class="n">curY</span><span class="p">]</span> <span class="o">=</span> <span class="n">SYMBOLS</span><span class="p">[</span><span class="n">room</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">sector_type</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">median</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num</span><span class="p">):</span>
<span class="n">lst</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">num</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lst</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">return</span> <span class="p">(</span><span class="n">lst</span><span class="p">[</span><span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">lst</span><span class="p">[</span><span class="n">m</span><span class="o">//</span><span class="mi">2</span><span class="p">])</span> <span class="o">/</span> <span class="mf">2.0</span>
<span class="k">def</span> <span class="nf">start_loc_on_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_width</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_length</span><span class="p">)</span>
<span class="c1"># x and y are floats by default, can&#39;t index lists with float types</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grid</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="o">=</span> <span class="n">SYMBOLS</span><span class="p">[</span><span class="s1">&#39;you&#39;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">curX</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">curY</span> <span class="o">=</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="c1"># updating worms current location</span>
<span class="k">def</span> <span class="nf">has_drawn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">True</span> <span class="k">if</span> <span class="n">room</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">worm_has_mapped</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span> <span class="k">else</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">create_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># This method simply creates an empty grid</span>
<span class="c1"># with the specified variables from __init__(self):</span>
<span class="n">board</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_width</span><span class="p">):</span>
<span class="n">board</span><span class="o">.</span><span class="n">append</span><span class="p">([])</span>
<span class="k">for</span> <span class="n">column</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_length</span><span class="p">):</span>
<span class="n">board</span><span class="p">[</span><span class="n">row</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">board</span>
<span class="k">def</span> <span class="nf">check_grid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># this method simply checks the grid to make sure</span>
<span class="c1"># both max_l and max_w are odd numbers</span>
<span class="k">return</span> <span class="bp">True</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_length</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span> <span class="ow">or</span> \
<span class="bp">self</span><span class="o">.</span><span class="n">max_width</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">else</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">show_map</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">map_string</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">grid</span><span class="p">:</span>
<span class="n">map_string</span> <span class="o">+=</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
<span class="n">map_string</span> <span class="o">+=</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="k">return</span> <span class="n">map_string</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="final-comments">
<h2>Final Comments<a class="headerlink" href="#final-comments" title="Permalink to this headline"></a></h2>
<p>The Dynamic map could be expanded with further capabilities. For example, it could mark exits or
allow NE, SE etc directions as well. It could have colors for different terrain types. One could
also look into up/down directions and figure out how to display that in a good way.</p>
</div>
</div>
<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="#">Dynamic In Game Map</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#the-grid-of-rooms">The Grid of Rooms</a></li>
<li><a class="reference internal" href="#concept">Concept</a></li>
<li><a class="reference internal" href="#setting-up-the-map-display">Setting up the Map Display</a></li>
<li><a class="reference internal" href="#building-the-mapper">Building the Mapper</a></li>
<li><a class="reference internal" href="#using-the-map">Using the Map</a></li>
<li><a class="reference internal" href="#final-comments">Final Comments</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Static-In-Game-Map.html"
title="previous chapter">Static In Game Map</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Implementing-a-game-rule-system.html"
title="next chapter">Implementing a game rule system</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="_sources/Dynamic-In-Game-Map.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div>
<h3>Versions</h3>
<ul>
<li><a href="../1.0-dev/index.html">1.0-dev (develop branch)</a></li>
<li><a href="Dynamic-In-Game-Map.html">0.9.5 (master 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="right" >
<a href="Implementing-a-game-rule-system.html" title="Implementing a game rule system"
>next</a> |</li>
<li class="right" >
<a href="Static-In-Game-Map.html" title="Static In Game Map"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Evennia 0.9.5</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Tutorials.html" >Tutorials</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Dynamic In Game Map</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>