mirror of
https://github.com/evennia/evennia.git
synced 2026-03-19 06:16:31 +01:00
753 lines
No EOL
62 KiB
HTML
753 lines
No EOL
62 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>3. Intro to using Python with Evennia — Evennia 1.0 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="4. Overview of your new Game Dir" href="Beginner-Tutorial-Gamedir-Overview.html" />
|
||
<link rel="prev" title="2. The Tutorial World" href="Beginner-Tutorial-Tutorial-World.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="Beginner-Tutorial-Gamedir-Overview.html" title="4. Overview of your new Game Dir"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Tutorial-World.html" title="2. The Tutorial World"
|
||
accesskey="P">previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part1-Overview.html" accesskey="U">Part 1: What we have</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><span class="section-number">3. </span>Intro to using Python with Evennia</a></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
|
||
<div class="documentwrapper">
|
||
<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>
|
||
<h3><a href="../../../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">3. Intro to using Python with Evennia</a><ul>
|
||
<li><a class="reference internal" href="#evennia-hello-world">3.1. Evennia Hello world</a></li>
|
||
<li><a class="reference internal" href="#making-some-text-graphics">3.2. Making some text ‘graphics’</a><ul>
|
||
<li><a class="reference internal" href="#format">3.2.1. .format()</a></li>
|
||
<li><a class="reference internal" href="#f-strings">3.2.2. f-strings</a></li>
|
||
<li><a class="reference internal" href="#colored-text">3.2.3. Colored text</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#importing-code-from-other-modules">3.3. Importing code from other modules</a><ul>
|
||
<li><a class="reference internal" href="#our-first-own-function">3.3.1. Our first own function</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#sending-text-to-others">3.4. Sending text to others</a></li>
|
||
<li><a class="reference internal" href="#parsing-python-errors">3.5. Parsing Python errors</a></li>
|
||
<li><a class="reference internal" href="#passing-arguments-to-functions">3.6. Passing arguments to functions</a></li>
|
||
<li><a class="reference internal" href="#finding-others-to-send-to">3.7. Finding others to send to</a></li>
|
||
<li><a class="reference internal" href="#multi-line-py">3.8. Multi-line py</a></li>
|
||
<li><a class="reference internal" href="#other-ways-to-test-python-code">3.9. Other ways to test Python code</a></li>
|
||
<li><a class="reference internal" href="#ipython">3.10. ipython</a></li>
|
||
<li><a class="reference internal" href="#conclusions">3.11. Conclusions</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Tutorial-World.html"
|
||
title="previous chapter"><span class="section-number">2. </span>The Tutorial World</a></p>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="Beginner-Tutorial-Gamedir-Overview.html"
|
||
title="next chapter"><span class="section-number">4. </span>Overview of your new Game Dir</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="../../../_sources/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.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="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="intro-to-using-python-with-evennia">
|
||
<h1><span class="section-number">3. </span>Intro to using Python with Evennia<a class="headerlink" href="#intro-to-using-python-with-evennia" title="Permalink to this headline">¶</a></h1>
|
||
<p>Time to dip our toe into some coding! Evennia is written and extended in <a class="reference external" href="https://python.org">Python</a>,
|
||
which is a mature and professional programming language that is very fast to work with.</p>
|
||
<p>That said, even though Python is widely considered easy to learn, we can only cover the most immediately
|
||
important aspects of Python in this series of starting tutorials. Hopefully we can get you started
|
||
but then you’ll need to continue learning from there. See our <a class="reference internal" href="../../../Links.html"><span class="doc std std-doc">link section</span></a> for finding
|
||
more reference material and dedicated Python tutorials.</p>
|
||
<blockquote>
|
||
<div><p>While this will be quite basic if you are an experienced developer, you may want to at least
|
||
stay around for the first few sections where we cover how to run Python from inside Evennia.</p>
|
||
</div></blockquote>
|
||
<p>First, if you were quelling yourself to play the tutorial world, make sure to get your
|
||
superuser powers back:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> unquell
|
||
</pre></div>
|
||
</div>
|
||
<section id="evennia-hello-world">
|
||
<h2><span class="section-number">3.1. </span>Evennia Hello world<a class="headerlink" href="#evennia-hello-world" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">py</span></code> Command (or <code class="docutils literal notranslate"><span class="pre">!</span></code>, which is an alias) allows you as a superuser to execute raw Python from in-
|
||
game. This is useful for quick testing. From the game’s input line, enter the following:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("Hello World!")
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Command input</p>
|
||
<p>The line with <code class="docutils literal notranslate"><span class="pre">></span></code> indicates input to enter in-game, while the lines below are the
|
||
expected return from that input.</p>
|
||
</aside>
|
||
<p>You will see</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> print("Hello world!")
|
||
Hello World!
|
||
</pre></div>
|
||
</div>
|
||
<p>To understand what is going on: some extra info: The <code class="docutils literal notranslate"><span class="pre">print(...)</span></code> <em>function</em> is the basic, in-built
|
||
way to output text in Python. We are sending “Hello World” as an <em>argument</em> to this function. The quotes <code class="docutils literal notranslate"><span class="pre">"..."</span></code>
|
||
mean that you are inputting a <em>string</em> (i.e. text). You could also have used single-quotes <code class="docutils literal notranslate"><span class="pre">'...'</span></code>,
|
||
Python accepts both. A third variant is triple-quotes (<code class="docutils literal notranslate"><span class="pre">"""..."""</span></code> or <code class="docutils literal notranslate"><span class="pre">'''...'''</span></code>, which work across multiple
|
||
lines and are common for larger text-blocks. The way we use the <code class="docutils literal notranslate"><span class="pre">py</span></code> command right now only supports
|
||
single-line input however.</p>
|
||
</section>
|
||
<section id="making-some-text-graphics">
|
||
<h2><span class="section-number">3.2. </span>Making some text ‘graphics’<a class="headerlink" href="#making-some-text-graphics" title="Permalink to this headline">¶</a></h2>
|
||
<p>When making a text-game you will, unsurprisingly, be working a lot with text. Even if you have the occational
|
||
button or even graphical element, the normal process is for the user to input commands as
|
||
text and get text back. As we saw above, a piece of text is called a <em>string</em> in Python and is enclosed in
|
||
either single- or double-quotes.</p>
|
||
<p>Strings can be added together:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("This is a " + "breaking change.")
|
||
This is a breaking change.
|
||
</pre></div>
|
||
</div>
|
||
<p>A string multiplied with a number will repeat that string as many times:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("|" + "-" * 40 + "|")
|
||
|----------------------------------------|
|
||
</pre></div>
|
||
</div>
|
||
<p>or</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("A" + "a" * 5 + "rgh!")
|
||
Aaaaaargh!
|
||
</pre></div>
|
||
</div>
|
||
<section id="format">
|
||
<h3><span class="section-number">3.2.1. </span>.format()<a class="headerlink" href="#format" title="Permalink to this headline">¶</a></h3>
|
||
<p>While combining different strings is useful, even more powerful is the ability to modify the contents
|
||
of the string in-place. There are several ways to do this in Python and we’ll show two of them here. The first
|
||
is to use the <code class="docutils literal notranslate"><span class="pre">.format</span></code> <em>method</em> of the string:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("This is a {} idea!".format("good"))
|
||
This is a good idea!
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Functions and Methods</p>
|
||
<ul class="simple">
|
||
<li><p>Function: Something that performs and action when you call it with zero or more <code class="docutils literal notranslate"><span class="pre">arguments</span></code>. A function is stand-alone in a python module, like <code class="docutils literal notranslate"><span class="pre">print()</span></code></p></li>
|
||
<li><p>Method: A function that sits “on” an object, like <code class="docutils literal notranslate"><span class="pre">obj.msg()</span></code>.</p></li>
|
||
</ul>
|
||
</aside>
|
||
<p>A method can be thought of as a resource “on” another object. The method knows on which object it
|
||
sits and can thus affect it in various ways. You access it with the period <code class="docutils literal notranslate"><span class="pre">.</span></code>. In this case, the
|
||
string has a resource <code class="docutils literal notranslate"><span class="pre">format(...)</span></code> that modifies it. More specifically, it replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> marker
|
||
inside the string with the value passed to the format. You can do so many times:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("This is a {} idea!".format("bad"))
|
||
This is a bad idea!
|
||
</pre></div>
|
||
</div>
|
||
<p>or</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("This is the {} and {} {} idea!".format("first", "second", "great"))
|
||
This is the first and second great idea!
|
||
</pre></div>
|
||
</div>
|
||
<blockquote>
|
||
<div><p>Note the double-parenthesis at the end - the first closes the <code class="docutils literal notranslate"><span class="pre">format(...</span></code> method and the outermost
|
||
closes the <code class="docutils literal notranslate"><span class="pre">print(...</span></code>. Not closing them will give you a scary <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>. We will talk a
|
||
little more about errors in the next section, for now just fix until it prints as expected.</p>
|
||
</div></blockquote>
|
||
<p>Here we passed three comma-separated strings as <em>arguments</em> to the string’s <code class="docutils literal notranslate"><span class="pre">format</span></code> method. These
|
||
replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> markers in the same order as they were given.</p>
|
||
<p>The input does not have to be strings either:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("STR: {}, DEX: {}, INT: {}".format(12, 14, 8))
|
||
STR: 12, DEX: 14, INT: 8
|
||
</pre></div>
|
||
</div>
|
||
<p>To separate two Python instructions on the same line, you use the semi-colon, <code class="docutils literal notranslate"><span class="pre">;</span></code>. Try this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py a = "awesome sauce" ; print("This is {}!".format(a))
|
||
This is awesome sauce!
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>MUD clients and semi-colon</p>
|
||
<p>Some MUD clients use the semi-colon <code class="docutils literal notranslate"><span class="pre">;</span></code> to split client-inputs
|
||
into separate sends. If so, the above will give an error. Most clients allow you to
|
||
run in ‘verbatim’ mode or to remap to use some other separator than <code class="docutils literal notranslate"><span class="pre">;</span></code>. If you still have
|
||
trouble, use the Evennia web client.</p>
|
||
</div>
|
||
<p>What happened here was that we <em>assigned</em> the string <code class="docutils literal notranslate"><span class="pre">"awesome</span> <span class="pre">sauce"</span></code> to a <em>variable</em> we chose
|
||
to name <code class="docutils literal notranslate"><span class="pre">a</span></code>. In the next statement, Python remembered what <code class="docutils literal notranslate"><span class="pre">a</span></code> was and we passed that into <code class="docutils literal notranslate"><span class="pre">format()</span></code>
|
||
to get the output. If you replaced the value of <code class="docutils literal notranslate"><span class="pre">a</span></code> with something else in between, <em>that</em> would be printed instead.</p>
|
||
<p>Here’s the stat-example again, moving the stats to variables (here we just set them, but in a real
|
||
game they may be changed over time, or modified by circumstance):</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py stren, dext, intel = 13, 14, 8 ; print("STR: {}, DEX: {}, INT: {}".format(stren, dext, intel))
|
||
STR: 13, DEX: 14, INT: 8
|
||
</pre></div>
|
||
</div>
|
||
<p>The point is that even if the values of the stats change, the print() statement would not change - it just keeps pretty-printing whatever is given to it.</p>
|
||
<p>You can also use named markers, like this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > py print("STR: {stren}, INT: {intel}, STR again: {stren}".format(dext=10, intel=18, stren=9))
|
||
STR: 9, INT: 18, Str again: 9
|
||
</pre></div>
|
||
</div>
|
||
<p>the <code class="docutils literal notranslate"><span class="pre">key=value</span></code> pairs we add are called <em>keyword arguments</em> for the <code class="docutils literal notranslate"><span class="pre">format()</span></code> method. Each named argument will go to the matching <code class="docutils literal notranslate"><span class="pre">{key}</span></code> in the string. When using keywords, the order we add them doesn’t matter. We have no <code class="docutils literal notranslate"><span class="pre">{dext}</span></code> and two <code class="docutils literal notranslate"><span class="pre">{stren}</span></code> in the string, and that works fine.</p>
|
||
</section>
|
||
<section id="f-strings">
|
||
<h3><span class="section-number">3.2.2. </span>f-strings<a class="headerlink" href="#f-strings" title="Permalink to this headline">¶</a></h3>
|
||
<p>Using <code class="docutils literal notranslate"><span class="pre">.format()</span></code> is convenient (and there is a <a class="reference external" href="https://www.w3schools.com/python/ref_string_format.asp">lot more</a> you can do with it). But the <em>f-string</em> can be even more convenient. An
|
||
f-string looks like a normal string … except there is an <code class="docutils literal notranslate"><span class="pre">f</span></code> front of it, like this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>f"this is now an f-string."
|
||
</pre></div>
|
||
</div>
|
||
<p>An f-string on its own is just like any other string. But let’s redo the example we did before, using an f-string:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py a = "awesome sauce" ; print(f"This is {a}!")
|
||
This is awesome sauce!
|
||
</pre></div>
|
||
</div>
|
||
<p>We insert that <code class="docutils literal notranslate"><span class="pre">a</span></code> variable directly into the f-string using <code class="docutils literal notranslate"><span class="pre">{a}</span></code>. Fewer parentheses to
|
||
remember and arguable easier to read as well.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py stren, dext, intel = 13, 14, 8 ; print(f"STR: {stren}, DEX: {dext}, INT: {intel}")
|
||
STR: 13, DEX: 14, INT: 8
|
||
</pre></div>
|
||
</div>
|
||
<p>We will be exploring more complex string concepts when we get to creating Commands and need to
|
||
parse and understand player input.</p>
|
||
</section>
|
||
<section id="colored-text">
|
||
<h3><span class="section-number">3.2.3. </span>Colored text<a class="headerlink" href="#colored-text" title="Permalink to this headline">¶</a></h3>
|
||
<p>Python itself knows nothing about colored text, this is an Evennia thing. Evennia supports the
|
||
standard color schemes of traditional MUDs.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("|rThis is red text!|n This is normal color.")
|
||
</pre></div>
|
||
</div>
|
||
<p>Adding that <code class="docutils literal notranslate"><span class="pre">|r</span></code> at the start will turn our output bright red. <code class="docutils literal notranslate"><span class="pre">|R</span></code> will make it dark red. <code class="docutils literal notranslate"><span class="pre">|n</span></code>
|
||
gives the normal text color. You can also use RGB (Red-Green-Blue) values from 0-5 (Xterm256 colors):</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py print("|043This is a blue-green color.|[530|003 Now dark blue text on orange background.")
|
||
</pre></div>
|
||
</div>
|
||
<blockquote>
|
||
<div><p>If you don’t see the expected color, your client or terminal may not support Xterm256 (or
|
||
color at all). Use the Evennia webclient.</p>
|
||
</div></blockquote>
|
||
<p>Use the commands <code class="docutils literal notranslate"><span class="pre">color</span> <span class="pre">ansi</span></code> or <code class="docutils literal notranslate"><span class="pre">color</span> <span class="pre">xterm</span></code> to see which colors are available. Experiment! You can also read a lot more in the <a class="reference internal" href="../../../Concepts/Colors.html"><span class="doc std std-doc">Colors</span></a> documentation.</p>
|
||
</section>
|
||
</section>
|
||
<section id="importing-code-from-other-modules">
|
||
<h2><span class="section-number">3.3. </span>Importing code from other modules<a class="headerlink" href="#importing-code-from-other-modules" title="Permalink to this headline">¶</a></h2>
|
||
<p>As we saw in the previous sections, we used <code class="docutils literal notranslate"><span class="pre">.format</span></code> to format strings and <code class="docutils literal notranslate"><span class="pre">me.msg</span></code> to access
|
||
the <code class="docutils literal notranslate"><span class="pre">msg</span></code> method on <code class="docutils literal notranslate"><span class="pre">me</span></code>. This use of the full-stop character is used to access all sorts of resources,
|
||
including that in other Python modules.</p>
|
||
<p>Keep your game running, then open a text editor of your choice. If your game folder is called
|
||
<code class="docutils literal notranslate"><span class="pre">mygame</span></code>, create a new text file <code class="docutils literal notranslate"><span class="pre">test.py</span></code> in the subfolder <code class="docutils literal notranslate"><span class="pre">mygame/world</span></code>. This is how the file
|
||
structure should look:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mygame</span><span class="o">/</span>
|
||
<span class="n">world</span><span class="o">/</span>
|
||
<span class="n">test</span><span class="o">.</span><span class="n">py</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>For now, only add one line to <code class="docutils literal notranslate"><span class="pre">test.py</span></code>:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">"Hello World!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Python module</p>
|
||
<p>This is a text file with the <code class="docutils literal notranslate"><span class="pre">.py</span></code> file ending. A module
|
||
contains Python source code and from within Python one can
|
||
access its contents by importing it via its python-path.</p>
|
||
</aside>
|
||
<p>Don’t forget to <em>save</em> the file. We just created our first Python <em>module</em>!
|
||
To use this in-game we have to <em>import</em> it. Try this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test
|
||
Hello World
|
||
</pre></div>
|
||
</div>
|
||
<p>If you make some error (we’ll cover how to handle errors below), fix the error in the module and
|
||
run the <code class="docutils literal notranslate"><span class="pre">reload</span></code> command in-game for your changes to take effect.</p>
|
||
<p>So importing <code class="docutils literal notranslate"><span class="pre">world.test</span></code> actually means importing <code class="docutils literal notranslate"><span class="pre">world/test.py</span></code>. Think of the period <code class="docutils literal notranslate"><span class="pre">.</span></code> as
|
||
replacing <code class="docutils literal notranslate"><span class="pre">/</span></code> (or <code class="docutils literal notranslate"><span class="pre">\</span></code> for Windows) in your path.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">.py</span></code> ending of <code class="docutils literal notranslate"><span class="pre">test.py</span></code> is never included in this “Python-path”, but <em>only</em> files with that ending can be imported this way. Where is <code class="docutils literal notranslate"><span class="pre">mygame</span></code> in that Python-path? The answer is that Evennia has already told Python that your <code class="docutils literal notranslate"><span class="pre">mygame</span></code> folder is a good place to look for imports. So we should not include <code class="docutils literal notranslate"><span class="pre">mygame</span></code> in the path - Evennia handles this for us.</p>
|
||
<p>When you import the module, the top “level” of it will execute. In this case, it will immediately
|
||
print “Hello World”.</p>
|
||
<p>Now try to run this a second time:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test
|
||
</pre></div>
|
||
</div>
|
||
<p>You will <em>not</em> see any output this or any subsequent times! This is not a bug. Rather it is because of how Python importing works - it stores all imported modules and will avoid importing them more than once. So your <code class="docutils literal notranslate"><span class="pre">print</span></code> will only run the first time, when the module is first imported.</p>
|
||
<p>Try this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> reload
|
||
</pre></div>
|
||
</div>
|
||
<p>And then</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test
|
||
Hello World!
|
||
</pre></div>
|
||
</div>
|
||
<p>Now we see it again. The <code class="docutils literal notranslate"><span class="pre">reload</span></code> wiped the server’s memory of what was imported, so it had to
|
||
import it anew. You’d have to do this every time you wanted the print to show though, which is
|
||
not very useful.</p>
|
||
<blockquote>
|
||
<div><p>We’ll get back to more advanced ways to import code in <a class="reference internal" href="Beginner-Tutorial-Python-classes-and-objects.html#importing-things"><span class="std std-doc">a later lesson</span></a> - this is an important topic. But for now, let’s press on and resolve this particular problem.</p>
|
||
</div></blockquote>
|
||
<section id="our-first-own-function">
|
||
<h3><span class="section-number">3.3.1. </span>Our first own function<a class="headerlink" href="#our-first-own-function" title="Permalink to this headline">¶</a></h3>
|
||
<p>We want to be able to print our hello-world message at any time, not just once after a server
|
||
reload. Change your <code class="docutils literal notranslate"><span class="pre">mygame/world/test.py</span></code> file to look like this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Hello World!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>As we are moving to multi-line Python code, there are some important things to remember:</p>
|
||
<ul class="simple">
|
||
<li><p>Capitalization matters in Python. It must be <code class="docutils literal notranslate"><span class="pre">def</span></code> and not <code class="docutils literal notranslate"><span class="pre">DEF</span></code>, <code class="docutils literal notranslate"><span class="pre">who</span></code> is not the same as <code class="docutils literal notranslate"><span class="pre">Who</span></code>.</p></li>
|
||
<li><p>Indentation matters in Python. The second line must be indented or it’s not valid code. You should
|
||
also use a consistent indentation length. We <em>strongly</em> recommend that you, for your own sanity’s sake,
|
||
set up your editor to always indent <em>4 spaces</em> (<strong>not</strong> a single tab-character) when you press the TAB key.</p></li>
|
||
</ul>
|
||
<p>So about that function. Line 1:</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">def</span></code> is short for “define” and defines a <em>function</em> (or a <em>method</em>, if sitting on an object).
|
||
This is a <a class="reference external" href="https://docs.python.org/2.5/ref/keywords.html">reserved Python keyword</a>; try not to use
|
||
these words anywhere else.</p></li>
|
||
<li><p>A function name can not have spaces but otherwise we could have called it almost anything. We call it <code class="docutils literal notranslate"><span class="pre">hello_world</span></code>. Evennia follows <span class="xref myst">Python’s standard naming style</span> with lowercase letters and underscores. We recommend you do the same.</p></li>
|
||
<li><p>The colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>) at the end of line 1 indicates that the header of the function is complete.</p></li>
|
||
</ul>
|
||
<p>Line 2:</p>
|
||
<ul class="simple">
|
||
<li><p>The indentation marks the beginning of the actual operating code of the function (the function’s
|
||
<em>body</em>). If we wanted more lines to belong to this function those lines would all have to
|
||
start at least at this indentation level.</p></li>
|
||
</ul>
|
||
<p>Now let’s try this out. First <code class="docutils literal notranslate"><span class="pre">reload</span></code> your game to have it pick up
|
||
our updated Python module, then import it.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> reload
|
||
> py import world.test
|
||
</pre></div>
|
||
</div>
|
||
<p>Nothing happened! That is because the function in our module won’t do anything just by importing it (this
|
||
is what we wanted). It will only act when we <em>call</em> it. So we need to first import the module and then access the
|
||
function within:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test ; world.test.hello_world()
|
||
Hello world!
|
||
</pre></div>
|
||
</div>
|
||
<p>There is our “Hello World”! As mentioned earlier, use use semi-colon to put multiple
|
||
Python-statements on one line. Note also the previous warning about mud-clients using the <code class="docutils literal notranslate"><span class="pre">;</span></code> to their
|
||
own ends.</p>
|
||
<p>So what happened there? First we imported <code class="docutils literal notranslate"><span class="pre">world.test</span></code> as usual. But this time we continued and
|
||
accessed the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function <em>inside</em> the newly imported module.</p>
|
||
<p>By adding <code class="docutils literal notranslate"><span class="pre">()</span></code> to the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function we <em>call</em> it, that is we run the body of the function and
|
||
print our text. We can now redo this as many times as we want without having to <code class="docutils literal notranslate"><span class="pre">reload</span></code> in between:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test ; world.test.hello_world()
|
||
Hello world!
|
||
> py import world.test ; world.test.hello_world()
|
||
Hello world!
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="sending-text-to-others">
|
||
<h2><span class="section-number">3.4. </span>Sending text to others<a class="headerlink" href="#sending-text-to-others" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">print</span></code> command is a standard Python structure. We can use that here in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command since
|
||
we can se the output. It’s great for debugging and quick testing. But if you need to send a text
|
||
to an actual player, <code class="docutils literal notranslate"><span class="pre">print</span></code> won’t do, because it doesn’t know <em>who</em> to send to. Try this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py me.msg("Hello world!")
|
||
Hello world!
|
||
</pre></div>
|
||
</div>
|
||
<p>This looks the same as the <code class="docutils literal notranslate"><span class="pre">print</span></code> result, but we are now actually messaging a specific <em>object</em>,
|
||
<code class="docutils literal notranslate"><span class="pre">me</span></code>. The <code class="docutils literal notranslate"><span class="pre">me</span></code> is a shortcut to ‘us’, the one running the <code class="docutils literal notranslate"><span class="pre">py</span></code> command. It is not some special
|
||
Python thing, but something Evennia just makes available in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command for convenience
|
||
(<code class="docutils literal notranslate"><span class="pre">self</span></code> is an alias).</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">me</span></code> is an example of an <em>Object instance</em>. Objects are fundamental in Python and Evennia.
|
||
The <code class="docutils literal notranslate"><span class="pre">me</span></code> object also contains a lot of useful resources for doing
|
||
things with that object. We access those resources with ‘<code class="docutils literal notranslate"><span class="pre">.</span></code>’.</p>
|
||
<p>One such resource is <code class="docutils literal notranslate"><span class="pre">msg</span></code>, which works like <code class="docutils literal notranslate"><span class="pre">print</span></code> except it sends the text to the object it
|
||
is attached to. So if we, for example, had an object <code class="docutils literal notranslate"><span class="pre">you</span></code>, doing <code class="docutils literal notranslate"><span class="pre">you.msg(...)</span></code> would send a message
|
||
to the object <code class="docutils literal notranslate"><span class="pre">you</span></code>.</p>
|
||
<p>For now, <code class="docutils literal notranslate"><span class="pre">print</span></code> and <code class="docutils literal notranslate"><span class="pre">me.msg</span></code> behaves the same, just remember that <code class="docutils literal notranslate"><span class="pre">print</span></code> is mainly used for
|
||
debugging and <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> will be more useful for you in the future.</p>
|
||
</section>
|
||
<section id="parsing-python-errors">
|
||
<h2><span class="section-number">3.5. </span>Parsing Python errors<a class="headerlink" href="#parsing-python-errors" title="Permalink to this headline">¶</a></h2>
|
||
<p>Let’s try this new text-sending in the function we just created. Go back to
|
||
your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> file and Replace the function with this instead:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
|
||
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Hello World!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Save your file and <code class="docutils literal notranslate"><span class="pre">reload</span></code> your server to tell Evennia to re-import new code,
|
||
then run it like before:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > py import world.test ; world.test.hello_world()
|
||
</pre></div>
|
||
</div>
|
||
<p>No go - this time you get an error!</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">File</span> <span class="s2">"./world/test.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">2</span><span class="p">,</span> <span class="ow">in</span> <span class="n">hello_world</span>
|
||
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Hello World!"</span><span class="p">)</span>
|
||
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">'me'</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Errors in the logs</p>
|
||
<p>In regular use, tracebacks will often appear in the log rather than
|
||
in the game. Use <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--log</span></code> to view the log in the terminal. Make
|
||
sure to scroll back if you expect an error and don’t see it. Use
|
||
<code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> (or <code class="docutils literal notranslate"><span class="pre">Cmd-C</span></code> on Mac) to exit the log-view.</p>
|
||
</aside>
|
||
<p>This is called a <em>traceback</em>. Python’s errors are very friendly and will most of the time tell you
|
||
exactly what and where things go wrong. It’s important that you learn to parse tracebacks so you
|
||
know how to fix your code.</p>
|
||
<p>A traceback is to be read from the <em>bottom up</em>:</p>
|
||
<ul class="simple">
|
||
<li><p>(line 3) An error of type <code class="docutils literal notranslate"><span class="pre">NameError</span></code> is the problem …</p></li>
|
||
<li><p>(line 3) … more specifically it is due to the variable <code class="docutils literal notranslate"><span class="pre">me</span></code> not being defined.</p></li>
|
||
<li><p>(line 2) This happened on the line <code class="docutils literal notranslate"><span class="pre">me.msg("Hello</span> <span class="pre">world!")</span></code> …</p></li>
|
||
<li><p>(line 1) … which is on line <code class="docutils literal notranslate"><span class="pre">2</span></code> of the file <code class="docutils literal notranslate"><span class="pre">./world/test.py</span></code>.</p></li>
|
||
</ul>
|
||
<p>In our case the traceback is short. There may be many more lines above it, tracking just how
|
||
different modules called each other until the program got to the faulty line. That can
|
||
sometimes be useful information, but reading from the bottom is always a good start.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">NameError</span></code> we see here is due to a module being its own isolated thing. It knows nothing about
|
||
the environment into which it is imported. It knew what <code class="docutils literal notranslate"><span class="pre">print</span></code> is because that is a special
|
||
<a class="reference external" href="https://docs.python.org/2.5/ref/keywords.html">reserved Python keyword</a>. But <code class="docutils literal notranslate"><span class="pre">me</span></code> is <em>not</em> such a
|
||
reserved word (as mentioned, it’s just something Evennia came up with for convenience in the <code class="docutils literal notranslate"><span class="pre">py</span></code>
|
||
command). As far as the module is concerned <code class="docutils literal notranslate"><span class="pre">me</span></code> is an unfamiliar name, appearing out of nowhere.
|
||
Hence the <code class="docutils literal notranslate"><span class="pre">NameError</span></code>.</p>
|
||
</section>
|
||
<section id="passing-arguments-to-functions">
|
||
<h2><span class="section-number">3.6. </span>Passing arguments to functions<a class="headerlink" href="#passing-arguments-to-functions" title="Permalink to this headline">¶</a></h2>
|
||
<p>We know that <code class="docutils literal notranslate"><span class="pre">me</span></code> exists at the point when we run the <code class="docutils literal notranslate"><span class="pre">py</span></code> command, because we can do <code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">me.msg("Hello</span> <span class="pre">World!")</span></code>
|
||
with no problem. So let’s <em>pass</em> that me along to the function so it knows what it should be.
|
||
Go back to your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> and change it to this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
|
||
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Hello World!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We now added an <em>argument</em> to the function. We could have named it anything. Whatever <code class="docutils literal notranslate"><span class="pre">who</span></code> is,
|
||
we will call a method <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> on it.</p>
|
||
<p>As usual, <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server to make sure the new code is available.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py import world.test ; world.test.hello_world(me)
|
||
Hello World!
|
||
</pre></div>
|
||
</div>
|
||
<p>Now it worked. We <em>passed</em> <code class="docutils literal notranslate"><span class="pre">me</span></code> to our function. It will appear inside the function renamed as <code class="docutils literal notranslate"><span class="pre">who</span></code> and
|
||
now the function works and prints as expected. Note how the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function doesn’t care <em>what</em> you
|
||
pass into it as long as it has a <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> method on it. So you could reuse this function over and over for other
|
||
suitable targets.</p>
|
||
<blockquote>
|
||
<div><p><strong>Extra Credit:</strong> As an exercise, try to pass something else into <code class="docutils literal notranslate"><span class="pre">hello_world</span></code>. Try for example
|
||
to pass the number <code class="docutils literal notranslate"><span class="pre">5</span></code> or the string <code class="docutils literal notranslate"><span class="pre">"foo"</span></code>. You’ll get errors telling you that they don’t have
|
||
the attribute <code class="docutils literal notranslate"><span class="pre">msg</span></code>. They don’t care about <code class="docutils literal notranslate"><span class="pre">me</span></code> itself not being a string or a number. If you are
|
||
familiar with other programming languages (especially C/Java) you may be tempted to start <em>validating</em>
|
||
<code class="docutils literal notranslate"><span class="pre">who</span></code> to make sure it’s of the right type before you send it. This is usually not recommended in Python.
|
||
Python philosophy is to <a class="reference external" href="https://docs.python.org/2/tutorial/errors.html">handle</a> the error if it happens
|
||
rather than to add a lot of code to prevent it from happening. See <a class="reference external" href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a>
|
||
and the concept of <em>Leap before you Look</em>.</p>
|
||
</div></blockquote>
|
||
</section>
|
||
<section id="finding-others-to-send-to">
|
||
<h2><span class="section-number">3.7. </span>Finding others to send to<a class="headerlink" href="#finding-others-to-send-to" title="Permalink to this headline">¶</a></h2>
|
||
<p>Let’s wrap up this first Python <code class="docutils literal notranslate"><span class="pre">py</span></code> crash-course by finding someone else to send to.</p>
|
||
<p>In Evennia’s <code class="docutils literal notranslate"><span class="pre">contrib/</span></code> folder (<code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/mirror.py</span></code>) is a handy little
|
||
object called the <code class="docutils literal notranslate"><span class="pre">TutorialMirror</span></code>. The mirror will echo whatever is being sent to it to
|
||
the room it is in.</p>
|
||
<p>On the game command-line, let’s create a mirror:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> create/drop mirror:contrib.tutorial_examples.mirror.TutorialMirror
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Creating objects</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">create</span></code> command was first used to create boxes in the
|
||
<a class="reference internal" href="Beginner-Tutorial-Building-Quickstart.html"><span class="doc std std-doc">Building Stuff</span></a> tutorial. You should now recognize
|
||
that it uses a “python-path” to tell Evennia where to load the mirror’s code from.</p>
|
||
</aside>
|
||
<p>A mirror should appear in your location.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> look mirror
|
||
mirror shows your reflection:
|
||
This is User #1
|
||
</pre></div>
|
||
</div>
|
||
<p>What you are seeing is actually your own avatar in the game, the same thing that is available as <code class="docutils literal notranslate"><span class="pre">me</span></code> in the <code class="docutils literal notranslate"><span class="pre">py</span></code>
|
||
command.</p>
|
||
<p>What we are aiming for now is the equivalent of <code class="docutils literal notranslate"><span class="pre">mirror.msg("Mirror</span> <span class="pre">Mirror</span> <span class="pre">on</span> <span class="pre">the</span> <span class="pre">wall")</span></code>. But the first thing that
|
||
comes to mind will not work:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py mirror.msg("Mirror, Mirror on the wall ...")
|
||
NameError: name 'mirror' is not defined.
|
||
</pre></div>
|
||
</div>
|
||
<p>This is not surprising: Python knows nothing about “mirrors” or locations or anything. The <code class="docutils literal notranslate"><span class="pre">me</span></code> we’ve been using
|
||
is, as mentioned, just a convenient thing the Evennia devs makes available to the <code class="docutils literal notranslate"><span class="pre">py</span></code> command. They couldn’t possibly
|
||
predict that you wanted to talk to mirrors.</p>
|
||
<p>Instead we will need to <em>search</em> for that <code class="docutils literal notranslate"><span class="pre">mirror</span></code> object before we can send to it.
|
||
Make sure you are in the same location as the mirror and try:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py me.search("mirror")
|
||
mirror
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">me.search("name")</span></code> will, by default, search and <em>return</em> an object with the given name found in <em>the same location</em>
|
||
as the <code class="docutils literal notranslate"><span class="pre">me</span></code> object is. If it can’t find anything you’ll see an error.</p>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">Function returns</p>
|
||
<p>Whereas a function like <code class="docutils literal notranslate"><span class="pre">print</span></code> only prints its arguments, it’s very common
|
||
for functions/methods to <code class="docutils literal notranslate"><span class="pre">return</span></code> a result of some kind. Think of the function
|
||
as a machine - you put something in and out comes a result you can use. In the case
|
||
of <code class="docutils literal notranslate"><span class="pre">me.search</span></code>, it will perform a database search and spit out the object it finds.</p>
|
||
</aside>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py me.search("dummy")
|
||
Could not find 'dummy'.
|
||
</pre></div>
|
||
</div>
|
||
<p>Wanting to find things in the same location is very common, but as we continue we’ll
|
||
find that Evennia provides ample tools for tagging, searching and finding things from all over your game.</p>
|
||
<p>Now that we know how to find the ‘mirror’ object, we just need to use that instead of <code class="docutils literal notranslate"><span class="pre">me</span></code>!</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py mirror = self.search("mirror") ; mirror.msg("Mirror, Mirror on the wall ...")
|
||
mirror echoes back to you:
|
||
"Mirror, Mirror on the wall ..."
|
||
</pre></div>
|
||
</div>
|
||
<p>The mirror is useful for testing because its <code class="docutils literal notranslate"><span class="pre">.msg</span></code> method just echoes whatever is sent to it back to the room. More common
|
||
would be to talk to a player character, in which case the text you sent would have appeared in their game client.</p>
|
||
</section>
|
||
<section id="multi-line-py">
|
||
<h2><span class="section-number">3.8. </span>Multi-line py<a class="headerlink" href="#multi-line-py" title="Permalink to this headline">¶</a></h2>
|
||
<p>So far we have use <code class="docutils literal notranslate"><span class="pre">py</span></code> in single-line mode, using <code class="docutils literal notranslate"><span class="pre">;</span></code> to separate multiple inputs. This is very convenient
|
||
when you want to do some quick testing. But you can also start a full multi-line Python interactive interpreter
|
||
inside Evennia.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> py
|
||
Evennia Interactive Python mode
|
||
Python 3.11.0 (default, Nov 22 2022, 11:21:55)
|
||
[GCC 8.2.0] on Linux
|
||
[py mode - quit() to exit]
|
||
</pre></div>
|
||
</div>
|
||
<p>(the details of the output will vary with your Python version and OS). You are now in python interpreter mode. It means
|
||
that <em>everything</em> you insert from now on will become a line of Python (you can no longer look around or do other
|
||
commands).</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> print("Hello World")
|
||
|
||
>>> print("Hello World")
|
||
Hello World
|
||
[py mode - quit() to exit]
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that we didn’t need to put <code class="docutils literal notranslate"><span class="pre">py</span></code> in front now. The system will also echo your input (that’s the bit after the <code class="docutils literal notranslate"><span class="pre">>>></span></code>). For brevity in this tutorual we’ll turn the echo off. First exit <code class="docutils literal notranslate"><span class="pre">py</span></code> and then start again with the <code class="docutils literal notranslate"><span class="pre">/noecho</span></code> flag.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> quit()
|
||
Closing the Python console.
|
||
> py/noecho
|
||
Evennia Interactive Python mode (no echoing of prompts)
|
||
Python 3.11.0 (default, Nov 22 2022, 11:21:56)
|
||
[GCC 8.2.0] on Linux
|
||
[py mode - quit() to exit]
|
||
</pre></div>
|
||
</div>
|
||
<aside class="sidebar">
|
||
<p class="sidebar-title">interactive py</p>
|
||
<ul class="simple">
|
||
<li><p>Start with <code class="docutils literal notranslate"><span class="pre">py</span></code>.</p></li>
|
||
<li><p>Use <code class="docutils literal notranslate"><span class="pre">py/noecho</span></code> if you don’t want your input to be echoed for every line.</p></li>
|
||
<li><p><em>All</em> your inputs will now be interpreted as Python code.</p></li>
|
||
<li><p>Exit with <code class="docutils literal notranslate"><span class="pre">quit()</span></code>.</p></li>
|
||
</ul>
|
||
</aside>
|
||
<p>We can now enter multi-line Python code:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> a = "Test"
|
||
> print(f"This is a {a}.")
|
||
This is a Test.
|
||
</pre></div>
|
||
</div>
|
||
<p>Let’s try to define a function:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> def hello_world(who, txt):
|
||
...
|
||
> who.msg(txt)
|
||
...
|
||
>
|
||
[py mode - quit() to exit]
|
||
</pre></div>
|
||
</div>
|
||
<p>Some important things above:</p>
|
||
<ul class="simple">
|
||
<li><p>Definining a function with <code class="docutils literal notranslate"><span class="pre">def</span></code> means we are starting a new code block. Python works so that you mark the content
|
||
of the block with indention. So the next line must be manually indented (4 spaces is a good standard) in order
|
||
for Python to know it’s part of the function body.</p></li>
|
||
<li><p>We expand the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function with another argument <code class="docutils literal notranslate"><span class="pre">txt</span></code>. This allows us to send any text, not just
|
||
“Hello World” over and over.</p></li>
|
||
<li><p>To tell <code class="docutils literal notranslate"><span class="pre">py</span></code> that no more lines will be added to the function body, we end with an empty input. When the normal prompt returns, we know we are done.</p></li>
|
||
</ul>
|
||
<p>Now we have defined a new function. Let’s try it out:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> hello_world(me, "Hello world to me!")
|
||
Hello world to me!
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">me</span></code> is still available to us, so we pass that as the <code class="docutils literal notranslate"><span class="pre">who</span></code> argument, along with a little longer
|
||
string. Let’s combine this with searching for the mirror.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> mirror = me.search("mirror")
|
||
> hello_world(mirror, "Mirror, Mirror on the wall ...")
|
||
mirror echoes back to you:
|
||
"Mirror, Mirror on the wall ..."
|
||
</pre></div>
|
||
</div>
|
||
<p>Exit the <code class="docutils literal notranslate"><span class="pre">py</span></code> mode with</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> quit()
|
||
Closing the Python console.
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="other-ways-to-test-python-code">
|
||
<h2><span class="section-number">3.9. </span>Other ways to test Python code<a class="headerlink" href="#other-ways-to-test-python-code" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">py</span></code> command is very powerful for experimenting with Python in-game. It’s great for quick testing.
|
||
But you are still limited to working over telnet or the webclient, interfaces that doesn’t know anything
|
||
about Python per-se.</p>
|
||
<p>Outside the game, go to the terminal where you ran Evennia (or any terminal where the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> command
|
||
is available).</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">cd</span></code> to your game dir.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code></p></li>
|
||
</ul>
|
||
<p>A Python shell opens. This works like <code class="docutils literal notranslate"><span class="pre">py</span></code> did inside the game, with the exception that you don’t have
|
||
<code class="docutils literal notranslate"><span class="pre">me</span></code> available out of the box. If you want <code class="docutils literal notranslate"><span class="pre">me</span></code>, you need to first find yourself:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> import evennia
|
||
> me = evennia.search_object("YourChar")[0]
|
||
</pre></div>
|
||
</div>
|
||
<p>Here we make use of one of evennia’s search functions, available by importing <code class="docutils literal notranslate"><span class="pre">evennia</span></code> directly.
|
||
We will cover more advanced searching later, but suffice to say, you put your own character name instead of
|
||
“YourChar” above.</p>
|
||
<blockquote>
|
||
<div><p>The <code class="docutils literal notranslate"><span class="pre">[0]</span></code> at the end is because <code class="docutils literal notranslate"><span class="pre">.search_object</span></code> returns a list of objects and we want to
|
||
get at the first of them (counting starts from 0).</p>
|
||
</div></blockquote>
|
||
<p>Use <code class="docutils literal notranslate"><span class="pre">Ctrl-D</span></code> (<code class="docutils literal notranslate"><span class="pre">Cmd-D</span></code> on Mac) or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit the Python console.</p>
|
||
</section>
|
||
<section id="ipython">
|
||
<h2><span class="section-number">3.10. </span>ipython<a class="headerlink" href="#ipython" title="Permalink to this headline">¶</a></h2>
|
||
<p>The default Python shell is quite limited and ugly. It’s <em>highly</em> recommended to install <code class="docutils literal notranslate"><span class="pre">ipython</span></code> instead. This
|
||
is a much nicer, third-party Python interpreter with colors and many usability improvements.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>pip install ipython
|
||
</pre></div>
|
||
</div>
|
||
<p>If <code class="docutils literal notranslate"><span class="pre">ipython</span></code> is installed, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code> will use it automatically.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia shell
|
||
...
|
||
IPython 7.4.0 -- An enhanced Interactive Python. Type '?' for help
|
||
In [1]: You now have Tab-completion:
|
||
|
||
> import evennia
|
||
> evennia.<TAB>
|
||
</pre></div>
|
||
</div>
|
||
<p>That is, enter <code class="docutils literal notranslate"><span class="pre">evennia.</span></code> and then press the TAB key - you will be given a list of all the resources
|
||
available on the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> object. This is great for exploring what Evennia has to offer. For example,
|
||
use your arrow keys to scroll to <code class="docutils literal notranslate"><span class="pre">search_object()</span></code> to fill it in.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>> evennia.search_object?
|
||
</pre></div>
|
||
</div>
|
||
<p>Adding a <code class="docutils literal notranslate"><span class="pre">?</span></code> and pressing return will give you the full documentation for <code class="docutils literal notranslate"><span class="pre">.search_object</span></code>. Use <code class="docutils literal notranslate"><span class="pre">??</span></code> if you
|
||
want to see the entire source code.</p>
|
||
<p>As for the normal python interpreter, use <code class="docutils literal notranslate"><span class="pre">Ctrl-D</span></code>/<code class="docutils literal notranslate"><span class="pre">Cmd-D</span></code> or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit ipython.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Persistent code</p>
|
||
<p>Common for both <code class="docutils literal notranslate"><span class="pre">py</span></code> and <code class="docutils literal notranslate"><span class="pre">python</span></code>/<code class="docutils literal notranslate"><span class="pre">ipython</span></code> is that the code you write is not persistent - it will
|
||
be gone after you shut down the interpreter (but ipython will remember your input history). For making long-lasting
|
||
Python code, we need to save it in a Python module, like we did for <code class="docutils literal notranslate"><span class="pre">world/test.py</span></code>.</p>
|
||
</div>
|
||
</section>
|
||
<section id="conclusions">
|
||
<h2><span class="section-number">3.11. </span>Conclusions<a class="headerlink" href="#conclusions" title="Permalink to this headline">¶</a></h2>
|
||
<p>This covers quite a lot of basic Python usage. We printed and formatted strings, defined our own
|
||
first function, fixed an error and even searched and talked to a mirror! Being able to access
|
||
python inside and outside of the game is an important skill for testing and debugging, but in
|
||
practice you will be writing most your code in Python modules.</p>
|
||
<p>To that end we also created a first new Python module in the <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> game dir, then imported and used it. Now let’s look at the rest of the stuff you’ve got going on inside that <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> folder …</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</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="Beginner-Tutorial-Gamedir-Overview.html" title="4. Overview of your new Game Dir"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="Beginner-Tutorial-Tutorial-World.html" title="2. The Tutorial World"
|
||
>previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and Howto’s</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part1-Overview.html" >Part 1: What we have</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><span class="section-number">3. </span>Intro to using Python with Evennia</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2022, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |