<h1>A voice operated elevator using events<aclass="headerlink"href="#a-voice-operated-elevator-using-events"title="Permalink to this headline">¶</a></h1>
<p>This tutorial will walk you through the steps to create a voice-operated elevator, using the <aclass="reference internal"href="Contrib-Ingame-Python.html"><spanclass="doc std std-doc">in-
game Python system</span></a>. This tutorial assumes the in-game Python
system is installed per the instructions in that doc. <strong>You do not need to read</strong> the entire
<p>Let’s go into limbo (<codeclass="docutils literal notranslate"><spanclass="pre">#2</span></code>) to add our elevator. We’ll add it to the north. To create this room,
<p>It is. But we need to have exits that will represent the way inside the elevator and out. What we
will do, at every floor, will be to change these exits so they become connected to the right room.
You’ll see this process a bit later.</p>
<p>We have two more rooms to create: our floor 2 and 3. This time, we’ll use <codeclass="docutils literal notranslate"><spanclass="pre">dig</span></code>, because we don’t
<h2>Our first callback in the elevator<aclass="headerlink"href="#our-first-callback-in-the-elevator"title="Permalink to this headline">¶</a></h2>
<p>Let’s go to the elevator (you could use <codeclass="docutils literal notranslate"><spanclass="pre">tel</span><spanclass="pre">#3</span></code> if you have the same IDs I have).</p>
<aclass="reference internal"href="Contrib-Ingame-Python-Tutorial-Dialogue.html"><spanclass="doc std std-doc">the other in-game Python tutorial about adding dialogues in events</span></a>, you
may remember what we need to do. If not, here’s a summary: we need to run some code when somebody
speaks in the room. So we need to create a callback (the callback will contain our lines of code).
We just need to know on which event this should be set. You can enter <codeclass="docutils literal notranslate"><spanclass="pre">call</span><spanclass="pre">here</span></code> to see the
possible events in this room.</p>
<p>In the table, you should see the “say” event, which is called when somebody says something in the
room. So we’ll need to add a callback to this event. Don’t worry if you’re a bit lost, just follow
the following steps, the way they connect together will become more obvious.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You just said </span><spanclass="si">{</span><spanclass="n">message</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<p>You can paste this line in-game, then type the <codeclass="docutils literal notranslate"><spanclass="pre">:wq</span></code> command to exit the editor and save your
modifications.</p>
<p>Let’s check. Try to say “hello” in the room. You should see the standard message, but nothing
more. Now try to say “1”. Below the standard message, you should see:</p>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Which floor do you want?"</span><spanclass="p">)</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"The elevator already is at this floor."</span><spanclass="p">)</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="c1"># 'floor' contains the new room where the elevator should be</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors of the elevator close with a clank."</span><spanclass="p">)</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors of the elevator open to </span><spanclass="si">{floor}</span><spanclass="s2">."</span><spanclass="p">,</span>
<li><p>We first obtain the objects of both exits and our three floors. We use the <codeclass="docutils literal notranslate"><spanclass="pre">get()</span></code> eventfunc,
which is a shortcut to obtaining objects. We usually use it to retrieve specific objects with an
ID. We put the floors in a dictionary. The keys of the dictionary are the floor number (as str),
the values are room objects.</p></li>
<li><p>Remember, the <codeclass="docutils literal notranslate"><spanclass="pre">message</span></code> variable contains the message spoken in the room. So either “1”, “2”, or
“3”. We still need to check it, however, because if the character says something like “1 2” in the
room, our callback will be executed. Let’s be sure what she says is a floor number.</p></li>
<li><p>We then check if the elevator is already at this floor. Notice that we use <codeclass="docutils literal notranslate"><spanclass="pre">TO_EXIT.location</span></code>.
<codeclass="docutils literal notranslate"><spanclass="pre">TO_EXIT</span></code> contains our “north” exit, leading inside of our elevator. Therefore, its <codeclass="docutils literal notranslate"><spanclass="pre">location</span></code> will
be the room where the elevator currently is.</p></li>
<li><p>If the floor is a different one, have the elevator “move”, changing just the location and
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">BACK_EXIT</span></code> (that is “north”) should change its location. The elevator shouldn’t be
accessible through our old floor.</p></li>
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">TO_EXIT</span></code> (that is “south”, the exit leading out of the elevator) should have a different
destination. When we go out of the elevator, we should find ourselves in the new floor, not the old
<li><p>Chained events always have the name <codeclass="docutils literal notranslate"><spanclass="pre">"chain_X"</span></code>. Usually, X is a number, but you can give the
<p>The callback is added to the <codeclass="docutils literal notranslate"><spanclass="pre">"chain_1"</span></code> event, an event that will not be automatically called by the
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors of the elevator open to </span><spanclass="si">{floor}</span><spanclass="s2">."</span><spanclass="p">,</span>
<p>Paste this code into the editor, then use <codeclass="docutils literal notranslate"><spanclass="pre">:wq</span></code> to save and quit the editor.</p>
<p>Now let’s edit our callback in the “say” event. We’ll have to change it a bit:</p>
<ulclass="simple">
<li><p>The callback will have to check the elevator isn’t already moving.</p></li>
<li><p>It must change the exits when the elevator move.</p></li>
<li><p>It has to call the <codeclass="docutils literal notranslate"><spanclass="pre">"chain_1"</span></code> event we have defined. It should call it 15 seconds later.</p></li>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Which floor do you want?"</span><spanclass="p">)</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"The elevator is between floors."</span><spanclass="p">)</span>
<spanclass="n">character</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"The elevator already is at this floor."</span><spanclass="p">)</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="c1"># 'floor' contains the new room where the elevator should be</span>
<spanclass="n">room</span><spanclass="o">.</span><spanclass="n">msg_contents</span><spanclass="p">(</span><spanclass="s2">"The doors of the elevator close with a clank."</span><spanclass="p">)</span>
<li><p>We added a little test to make sure the elevator wasn’t already moving. If it is, the
<codeclass="docutils literal notranslate"><spanclass="pre">BACK_EXIT.location</span></code> (the “south” exit leading out of the elevator) should be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. We’ll remove
the exit while the elevator is moving.</p></li>
<li><p>When the doors close, we set both exits’<codeclass="docutils literal notranslate"><spanclass="pre">location</span></code> to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. Which “removes” them from their
room but doesn’t destroy them. The exits still exist but they don’t connect anything. If you say
“2” in the elevator and look around while the elevator is moving, you won’t see any exits.</p></li>
<li><p>Instead of opening the doors immediately, we call <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code>. We give it the object containing
the event to be called (here, our elevator), the name of the event to be called (here, “chain_1”)
and the number of seconds from now when the event should be called (here, <codeclass="docutils literal notranslate"><spanclass="pre">15</span></code>).</p></li>
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">chain_1</span></code> callback we have created contains the code to “re-open” the elevator doors. That
is, besides displaying a message, it reset the exits’<codeclass="docutils literal notranslate"><spanclass="pre">location</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">destination</span></code>.</p></li>
<div><p>Note: we don’t define the variables again in our chained event, we just call them. When we
execute <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code>, a copy of our current variables is placed in the database. These variables
will be restored and accessible again when the chained event is called.</p>
<p>You can use the <codeclass="docutils literal notranslate"><spanclass="pre">call/tasks</span></code> command to see the tasks waiting to be executed. For instance, say “2”
in the room, notice the doors closing, and then type the <codeclass="docutils literal notranslate"><spanclass="pre">call/tasks</span></code> command. You will see a task
in the elevator, waiting to call the <codeclass="docutils literal notranslate"><spanclass="pre">chain_1</span></code> event.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">message</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{character}</span><spanclass="s2"> walks out of the elevator."</span>
<p>Again, save and quit the editor by entering <codeclass="docutils literal notranslate"><spanclass="pre">:wq</span></code>. You can create a new character to see it leave.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">message</span><spanclass="o">=</span><spanclass="s2">"</span><spanclass="si">{character}</span><spanclass="s2"> walks into the elevator."</span>
<li><p><strong>A:</strong> you can use every variable type you like in your original callback. However, if you
execute <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code>, since your variables are stored in the database, they will need to respect the
constraints on persistent attributes. A callback will not be stored in this way, for instance.
This variable will not be available in your chained event.</p></li>
<li><p><strong>Q:</strong> when you say I can call my chained events something else than “chain_1”, “chain_2” and
<li><p><strong>A:</strong> chained events have names beginning by <codeclass="docutils literal notranslate"><spanclass="pre">"chain_"</span></code>. This is useful for you and for the
system. But after the underscore, you can give a more useful name, like <codeclass="docutils literal notranslate"><spanclass="pre">"chain_open_doors"</span></code> in our
<li><p><strong>A:</strong> no, you can call it right away. Just leave the third parameter of <codeclass="docutils literal notranslate"><spanclass="pre">call_event</span></code> out (it
will default to 0, meaning the chained event will be called right away). This will not create a