mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Some cleanup in the beginner tutorial's first lessons
This commit is contained in:
parent
cd7f34ee14
commit
e492a92b61
6 changed files with 82 additions and 170 deletions
|
|
@ -7,6 +7,7 @@
|
|||
- Fix: More unit tests for scripts (Storsorken)
|
||||
- Docs: Made separate doc pages for Exits, Characters and Rooms. Expanded on how
|
||||
to change the description of an in-game object with templating.
|
||||
- Docs: Fixed a multitude of doc issues.
|
||||
|
||||
## Evennia 1.2.1
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ To test it, let's tell Evennia to apply the Funcparser on every outgoing message
|
|||
|
||||
After a reload, you can try this in-game
|
||||
|
||||
```{shell}
|
||||
```shell
|
||||
> say I got $randint(1,5) gold!
|
||||
You say "I got 3 gold!"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -36,37 +36,36 @@ You need to know how to find your Terminal/Console in your OS. The Evennia serve
|
|||
|
||||
> Note that we usually only show forward-slashes `/` for file system paths. Windows users should mentally convert this to back-slashes `\` instead.
|
||||
|
||||
### A fresh game dir?
|
||||
|
||||
You should make sure you have successfully [installed Evennia](../../Setup/Installation.md). If you followed the instructions you will already have created a game-dir. You could re-use that or make a new one only for this tutorial, it's up to you.
|
||||
|
||||
If you already have a game dir and want a separate one for the tutorial, use `evennia stop` to halt the running server and then [Initialize a new game dir](../../Setup/Installation.md#initialize-a-new-game) somewhere else (_not_ inside the previous game dir!). We refer to it everywhere as `mygame`, so you may want to use that name too.
|
||||
|
||||
### A MUD client
|
||||
|
||||
You might already have a MUD-client you prefer. Check out the [grid of supported clients](../../Setup/Client-Support-Grid.md).
|
||||
If telnet's not your thing, you can also just use Evennia's web client in your browser.
|
||||
|
||||
Make sure you know how to connect to and log in to your locally running Evennia server.
|
||||
|
||||
> In this documentation we often use the terms 'MUD', 'MU' or 'MU*' interchangeably to represent all the historically different forms of text-based multiplayer game-styles, like MUD, MUX, MUSH, MUCK, MOO and others. Evennia can be used to create all those game-styles and more.
|
||||
|
||||
### A text Editor or IDE
|
||||
|
||||
You need a text-editor to edit Python source files. Most everything that can edit and output raw
|
||||
text works (so not Word).
|
||||
You need a text-editor to edit Python source files. Most everything that can edit and output raw text works (so not Word).
|
||||
|
||||
- [Here's a blog post summing up some of the alternatives](https://www.elegantthemes.com/blog/resources/best-code-editors) - these things don't change much from year to year. Popular choices for Python are PyCharm, VSCode, Atom, Sublime Text and Notepad++. Evennia is to a very large degree coded in VIM, but that's not suitable for beginners.
|
||||
|
||||
```{important} Use spaces, not tabs
|
||||
Make sure to configure your editor so that pressing TAB inserts _4 spaces_ rather than a Tab-character. Since Python is whitespace-aware, this will make your life a lot easier.
|
||||
```
|
||||
> Make sure to configure your editor so that pressing TAB inserts _4 spaces_ rather than a Tab-character. Since Python is whitespace-aware, this will make your life a lot easier.
|
||||
|
||||
### A fresh game dir?
|
||||
|
||||
You should make sure you have [installed Evennia](../../Setup/Installation.md). If you followed the instructions you will already have created a game-dir.
|
||||
|
||||
You could re-use that or make a new one only for this tutorial, it's up to you.
|
||||
|
||||
If you already have a game dir and want a separate one for the tutorial, use `evennia stop` to halt the running server and then [Initialize a new game dir](../../Setup/Installation.md#initialize-a-new-game) somewhere else (_not_ inside the previous game dir!). We refer to it everywhere as `mygame`, so you may want to do the same.
|
||||
|
||||
You should now be ready to move on to the [first lesson](Part1/Beginner-Tutorial-Part1-Overview.md)
|
||||
You should now be ready to move on to the [first part of the tutorial](Part1/Beginner-Tutorial-Part1-Overview.md) (in the future, use the `previous | next` buttons on the top/bottom of the page to progress)!
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Click here to expand a list of all Beginner-Tutorial sections (all parts).
|
||||
Click here to see the full index of all parts and lessons of the Beginner-Tutorial.
|
||||
</summary>
|
||||
|
||||
```{toctree}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@
|
|||
<br>Taking our new game online and let players try it out
|
||||
```
|
||||
|
||||
In this first part we'll focus on what we get out of the box in Evennia - we'll get used to the tools,
|
||||
and how to find things we are looking for. We will also dive into some of things you'll
|
||||
need to know to fully utilize the system, including giving you a brief rundown of Python concepts. If you are
|
||||
an experienced Python programmer, some sections may feel a bit basic, but you will at least not have seen
|
||||
these concepts in the context of Evennia before.
|
||||
In this first part we'll focus on what we get out of the box in Evennia - we'll get used to the tools and how to find things we are looking for. We will also dive into some of things you'll need to know to fully utilize the system, including giving you a brief rundown of Python concepts. If you are an experienced Python programmer, some sections may feel a bit basic, but seeing things in the context of Evennia will still be worth learning.
|
||||
|
||||
## Lessons
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
# Intro to using Python with Evennia
|
||||
|
||||
Time to dip our toe into some coding! Evennia is written and extended in [Python](https://python.org),
|
||||
which is a mature and professional programming language that is very fast to work with.
|
||||
Time to dip our toe into some coding! Evennia is written and extended in [Python](https://python.org). Python is a mature and professional programming language that is very fast to work with.
|
||||
|
||||
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 [link section](../../../Links.md) for finding
|
||||
more reference material and dedicated Python tutorials.
|
||||
That said, even though Python is widely considered easy to learn, we can only cover the basics in these lessons. While we will hopefully get you started with the most important bits you need, you may likely need to compliment with some learning on your own. Luckily there's a vast amount of free online learning resources available for Python. See our [link section](../../../Links.md) for some examples.
|
||||
|
||||
> 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.
|
||||
> 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.
|
||||
|
||||
First, if you were quelling yourself to play the tutorial world, make sure to get your
|
||||
superuser powers back:
|
||||
|
|
@ -34,19 +29,15 @@ You will see
|
|||
> print("Hello world!")
|
||||
Hello World!
|
||||
|
||||
To understand what is going on: some extra info: The `print(...)` *function* is the basic, in-built
|
||||
way to output text in Python. We are sending "Hello World" as an _argument_ to this function. The quotes `"..."`
|
||||
mean that you are inputting a *string* (i.e. text). You could also have used single-quotes `'...'`,
|
||||
Python accepts both. A third variant is triple-quotes (`"""..."""` or `'''...'''`, which work across multiple
|
||||
lines and are common for larger text-blocks. The way we use the `py` command right now only supports
|
||||
single-line input however.
|
||||
The `print(...)` *function* is the basic, in-built way to output text in Python. We are sending "Hello World" as a single _argument_ to this function. If we were to send multiple arguments, they'd be separated by commas.
|
||||
|
||||
The quotes `"..."` mean that you are inputting a *string* (i.e. text). You could also have used single-quotes `'...'` - Python accepts both.
|
||||
|
||||
> A third way to enter Python strings is to use triple-quotes (`"""..."""` or `'''...'''`. This is used for longer strings stretching across multiple lines. When we insert code directly to `py` like this we can only use one line though.
|
||||
|
||||
## Making some text 'graphics'
|
||||
|
||||
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 _string_ in Python and is enclosed in
|
||||
either single- or double-quotes.
|
||||
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 _string_ in Python and is enclosed in either single- or double-quotes.
|
||||
|
||||
Strings can be added together:
|
||||
|
||||
|
|
@ -65,38 +56,30 @@ A string multiplied with a number will repeat that string as many times:
|
|||
|
||||
### .format()
|
||||
|
||||
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 `.format` _method_ of the string:
|
||||
```{sidebar} Functions and Methods
|
||||
- Function: Something that performs an action when you call it with zero or more `arguments`. A function is stand-alone in a python module, like `print()`
|
||||
- Method: A function that sits "on" an object. It is accessed via the `.` operator, like `obj.msg()` or, in this case, `<string>.format()`.
|
||||
```
|
||||
|
||||
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 `.format` _method_ of the string:
|
||||
|
||||
> py print("This is a {} idea!".format("good"))
|
||||
This is a good idea!
|
||||
|
||||
```{sidebar} Functions and Methods
|
||||
- Function: Something that performs and action when you call it with zero or more `arguments`. A function is stand-alone in a python module, like `print()`
|
||||
- Method: A function that sits "on" an object, like `obj.msg()`.
|
||||
|
||||
```
|
||||
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 `.`. In this case, the string has a resource `format(...)` that modifies it. More specifically, it replaced the `{}` marker inside the string with the value passed to the format. You can do so many times:
|
||||
|
||||
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 `.`. In this case, the
|
||||
string has a resource `format(...)` that modifies it. More specifically, it replaced the `{}` marker
|
||||
inside the string with the value passed to the format. You can do so many times:
|
||||
|
||||
> py print("This is a {} idea!".format("bad"))
|
||||
This is a bad idea!
|
||||
> py print("This is a {} idea!".format("good"))
|
||||
This is a good idea!
|
||||
|
||||
or
|
||||
|
||||
> py print("This is the {} and {} {} idea!".format("first", "second", "great"))
|
||||
This is the first and second great idea!
|
||||
|
||||
> Note the double-parenthesis at the end - the first closes the `format(...` method and the outermost
|
||||
closes the `print(...`. Not closing them will give you a scary `SyntaxError`. We will talk a
|
||||
little more about errors in the next section, for now just fix until it prints as expected.
|
||||
> Note the double-parenthesis at the end - the first closes the `format(...` method and the outermost closes the `print(...`. Not closing them will give you a scary `SyntaxError`. We will talk a little more about errors in the next section, for now just fix until it prints as expected.
|
||||
|
||||
Here we passed three comma-separated strings as _arguments_ to the string's `format` method. These
|
||||
replaced the `{}` markers in the same order as they were given.
|
||||
Here we passed three comma-separated strings as _arguments_ to the string's `format` method. These replaced the `{}` markers in the same order as they were given.
|
||||
|
||||
The input does not have to be strings either:
|
||||
|
||||
|
|
@ -111,17 +94,12 @@ To separate two Python instructions on the same line, you use the semi-colon, `;
|
|||
```{warning} MUD clients and semi-colon
|
||||
|
||||
Some MUD clients use the semi-colon `;` 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 `;`. If you still have
|
||||
trouble, use the Evennia web client.
|
||||
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 `;`. If you still have trouble, use the Evennia web client.
|
||||
```
|
||||
|
||||
What happened here was that we _assigned_ the string `"awesome sauce"` to a _variable_ we chose
|
||||
to name `a`. In the next statement, Python remembered what `a` was and we passed that into `format()`
|
||||
to get the output. If you replaced the value of `a` with something else in between, _that_ would be printed instead.
|
||||
What happened here was that we _assigned_ the string `"awesome sauce"` to a _variable_ we chose to name `a`. In the next statement, Python remembered what `a` was and we passed that into `format()` to get the output. If you replaced the value of `a` with something else in between, _that_ would be printed instead.
|
||||
|
||||
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):
|
||||
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):
|
||||
|
||||
> py stren, dext, intel = 13, 14, 8 ; print("STR: {}, DEX: {}, INT: {}".format(stren, dext, intel))
|
||||
STR: 13, DEX: 14, INT: 8
|
||||
|
|
@ -137,8 +115,7 @@ the `key=value` pairs we add are called _keyword arguments_ for the `format()` m
|
|||
|
||||
### f-strings
|
||||
|
||||
Using `.format()` is convenient (and there is a [lot more](https://www.w3schools.com/python/ref_string_format.asp) you can do with it). But the _f-string_ can be even more convenient. An
|
||||
f-string looks like a normal string ... except there is an `f` front of it, like this:
|
||||
Using `.format()` is powerful (and there is a [lot more](https://www.w3schools.com/python/ref_string_format.asp) you can do with it). But the _f-string_ can be even more convenient. An f-string looks like a normal string ... except there is an `f` front of it, like this:
|
||||
|
||||
f"this is now an f-string."
|
||||
|
||||
|
|
@ -148,18 +125,18 @@ An f-string on its own is just like any other string. But let's redo the example
|
|||
This is awesome sauce!
|
||||
|
||||
We insert that `a` variable directly into the f-string using `{a}`. Fewer parentheses to
|
||||
remember and arguable easier to read as well.
|
||||
remember and arguable easier to read as well!
|
||||
|
||||
> py stren, dext, intel = 13, 14, 8 ; print(f"STR: {stren}, DEX: {dext}, INT: {intel}")
|
||||
STR: 13, DEX: 14, INT: 8
|
||||
|
||||
We will be exploring more complex string concepts when we get to creating Commands and need to
|
||||
parse and understand player input.
|
||||
In modern Python code, f-strings are more often used than `.format()` but to read code you need to be aware of both.
|
||||
|
||||
We will be exploring more complex string concepts when we get to creating Commands and need to parse and understand player input.
|
||||
|
||||
### Colored text
|
||||
|
||||
Python itself knows nothing about colored text, this is an Evennia thing. Evennia supports the
|
||||
standard color schemes of traditional MUDs.
|
||||
Python itself knows nothing about colored text, this is an Evennia thing. Evennia supports the standard color schemes of traditional MUDs.
|
||||
|
||||
> py print("|rThis is red text!|n This is normal color.")
|
||||
|
||||
|
|
@ -175,9 +152,7 @@ Use the commands `color ansi` or `color xterm` to see which colors are available
|
|||
|
||||
## Importing code from other modules
|
||||
|
||||
As we saw in the previous sections, we used `.format` to format strings and `me.msg` to access
|
||||
the `msg` method on `me`. This use of the full-stop character is used to access all sorts of resources,
|
||||
including that in other Python modules.
|
||||
As we saw in the previous sections, we used `.format` to format strings and `me.msg` to access the `msg` method on `me`. This use of the full-stop character is used to access all sorts of resources, including that in other Python modules.
|
||||
|
||||
Keep your game running, then open a text editor of your choice. If your game folder is called
|
||||
`mygame`, create a new text file `test.py` in the subfolder `mygame/world`. This is how the file
|
||||
|
|
@ -196,7 +171,6 @@ print("Hello World!")
|
|||
```
|
||||
|
||||
```{sidebar} Python module
|
||||
|
||||
This is a text file with the `.py` file ending. A module
|
||||
contains Python source code and from within Python one can
|
||||
access its contents by importing it via its python-path.
|
||||
|
|
@ -208,11 +182,9 @@ To use this in-game we have to *import* it. Try this:
|
|||
> py import world.test
|
||||
Hello World
|
||||
|
||||
If you make some error (we'll cover how to handle errors below), fix the error in the module and
|
||||
run the `reload` command in-game for your changes to take effect.
|
||||
If you make some error (we'll cover how to handle errors below), make sure the text looks exactly like above and then run the `reload` command in-game for your changes to take effect.
|
||||
|
||||
So importing `world.test` actually means importing `world/test.py`. Think of the period `.` as
|
||||
replacing `/` (or `\` for Windows) in your path.
|
||||
... So as you can see, importing `world.test` actually means importing `world/test.py`. Think of the period `.` as replacing `/` (or `\` for Windows) in your path.
|
||||
|
||||
The `.py` ending of `test.py` is never included in this "Python-path", but _only_ files with that ending can be imported this way. Where is `mygame` in that Python-path? The answer is that Evennia has already told Python that your `mygame` folder is a good place to look for imports. So we should not include `mygame` in the path - Evennia handles this for us.
|
||||
|
||||
|
|
@ -234,9 +206,7 @@ And then
|
|||
> py import world.test
|
||||
Hello World!
|
||||
|
||||
Now we see it again. The `reload` 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.
|
||||
Now we see it again. The `reload` 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 hello-world to show, which is not very useful.
|
||||
|
||||
> We'll get back to more advanced ways to import code in [a later lesson](./Beginner-Tutorial-Python-classes-and-objects.md#importing-things) - this is an important topic. But for now, let's press on and resolve this particular problem.
|
||||
|
||||
|
|
@ -251,50 +221,39 @@ def hello_world():
|
|||
print("Hello World!")
|
||||
```
|
||||
|
||||
```{sidebar}
|
||||
If you are coming from some other language like Javascript or C you may be familiar with variables and functions mixing cases in names, like `helloWorld()`. While you _could_ choose to name things this way, it will clash with other Python code - Python standard is to use lower-case and underscores `_` for all variables and methods.
|
||||
```
|
||||
As we are moving to multi-line Python code, there are some important things to remember:
|
||||
|
||||
- Capitalization matters in Python. It must be `def` and not `DEF`, `who` is not the same as `Who`.
|
||||
- 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 *strongly* recommend that you, for your own sanity's sake,
|
||||
set up your editor to always indent *4 spaces* (**not** a single tab-character) when you press the TAB key.
|
||||
- Capitalization matters in Python. It must be `def` and not `DEF`, `hello_world()` is not the same as `Hello_World()`.
|
||||
- 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 *strongly* recommend that you, for your own sanity's sake, set up your editor to always indent *4 spaces* (**not** a single tab-character) when you press the TAB key.
|
||||
|
||||
So about that function. Line 1:
|
||||
|
||||
- `def` is short for "define" and defines a *function* (or a *method*, if sitting on an object).
|
||||
This is a [reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html); try not to use
|
||||
these words anywhere else.
|
||||
- A function name can not have spaces but otherwise we could have called it almost anything. We call it `hello_world`. Evennia follows [Python's standard naming style](iEvennia-Code-Style) with lowercase letters and underscores. We recommend you do the same.
|
||||
- `def` is short for "define" and defines a *function* (or a *method*, if sitting on an object). This is a [reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html); try not to use these words anywhere else.
|
||||
- A function name can not have spaces but otherwise we could have called it almost anything. We call it `hello_world`. Evennia follows [Python's standard naming style](../../../Coding/Evennia-Code-Style.md) with lowercase letters and underscores. We recommend you do the same.
|
||||
- The colon (`:`) at the end of line 1 indicates that the header of the function is complete.
|
||||
|
||||
Line 2:
|
||||
|
||||
- The indentation marks the beginning of the actual operating code of the function (the function's
|
||||
*body*). If we wanted more lines to belong to this function those lines would all have to
|
||||
start at least at this indentation level.
|
||||
- The indentation marks the beginning of the actual operating code of the function (the function's *body*). If we wanted more lines to belong to this function those lines would all have to start at least at this indentation level.
|
||||
|
||||
Now let's try this out. First `reload` your game to have it pick up
|
||||
our updated Python module, then import it.
|
||||
Now let's try this out. First `reload` your game to have it pick up our updated Python module, then import it.
|
||||
|
||||
> reload
|
||||
> py import world.test
|
||||
|
||||
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 *call* it. So we need to first import the module and then access the
|
||||
function within:
|
||||
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 *call* it. So we need to first import the module and then access the function within:
|
||||
|
||||
> py import world.test ; world.test.hello_world()
|
||||
Hello world!
|
||||
|
||||
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 `;` to their
|
||||
own ends.
|
||||
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 `;` to their own ends.
|
||||
|
||||
So what happened there? First we imported `world.test` as usual. But this time we continued and
|
||||
accessed the `hello_world` function _inside_ the newly imported module.
|
||||
|
||||
By adding `()` to the `hello_world` function we _call_ 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 `reload` in between:
|
||||
So what happened there? First we imported `world.test` as usual. But this time the 'top level' of the module only defined a function. It didn't actually execute the body of that function.
|
||||
|
||||
By adding `()` to the `hello_world` function we _call_ it. That is, we execute the body of the function and print our text. We can now redo this as many times as we want without having to `reload` in between:
|
||||
|
||||
> py import world.test ; world.test.hello_world()
|
||||
Hello world!
|
||||
|
|
@ -303,25 +262,17 @@ print our text. We can now redo this as many times as we want without having to
|
|||
|
||||
## Sending text to others
|
||||
|
||||
The `print` command is a standard Python structure. We can use that here in the `py` 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, `print` won't do, because it doesn't know _who_ to send to. Try this:
|
||||
The `print` command is a standard Python structure. We can use that here in the `py` 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, `print` won't do, because it doesn't know _who_ to send to. Try this:
|
||||
|
||||
> py me.msg("Hello world!")
|
||||
Hello world!
|
||||
|
||||
This looks the same as the `print` result, but we are now actually messaging a specific *object*,
|
||||
`me`. The `me` is a shortcut to 'us', the one running the `py` command. It is not some special
|
||||
Python thing, but something Evennia just makes available in the `py` command for convenience
|
||||
(`self` is an alias).
|
||||
This looks the same as the `print` result, but we are now actually messaging a specific *object*, `me`. The `me` is a shortcut to 'us', the one running the `py` command. It is not some special Python thing, but something Evennia just makes available in the `py` command for convenience (`self` is an alias).
|
||||
|
||||
The `me` is an example of an *Object instance*. Objects are fundamental in Python and Evennia.
|
||||
The `me` object also contains a lot of useful resources for doing
|
||||
things with that object. We access those resources with '`.`'.
|
||||
The `me` is an example of an *Object instance*. Objects are fundamental in Python and Evennia. The `me` object also contains a lot of useful resources for doing things with that object. We access those resources with '`.`'.
|
||||
|
||||
One such resource is `msg`, which works like `print` except it sends the text to the object it
|
||||
is attached to. So if we, for example, had an object `you`, doing `you.msg(...)` would send a message
|
||||
to the object `you`.
|
||||
is attached to. So if we, for example, had an object `you`, doing `you.msg(...)` would send a message to the object `you`.
|
||||
|
||||
For now, `print` and `me.msg` behaves the same, just remember that `print` is mainly used for
|
||||
debugging and `.msg()` will be more useful for you in the future.
|
||||
|
|
@ -342,7 +293,7 @@ then run it like before:
|
|||
|
||||
> py import world.test ; world.test.hello_world()
|
||||
|
||||
No go - this time you get an error!
|
||||
No go - this time you get an _error_!
|
||||
|
||||
```python
|
||||
File "./world/test.py", line 2, in hello_world
|
||||
|
|
@ -356,12 +307,9 @@ In regular use, tracebacks will often appear in the log rather than
|
|||
in the game. Use `evennia --log` to view the log in the terminal. Make
|
||||
sure to scroll back if you expect an error and don't see it. Use
|
||||
`Ctrl-C` (or `Cmd-C` on Mac) to exit the log-view.
|
||||
|
||||
```
|
||||
|
||||
This is called a *traceback*. 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.
|
||||
This is called a *traceback*. 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.
|
||||
|
||||
A traceback is to be read from the _bottom up_:
|
||||
|
||||
|
|
@ -374,42 +322,29 @@ In our case the traceback is short. There may be many more lines above it, track
|
|||
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.
|
||||
|
||||
The `NameError` 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 `print` is because that is a special
|
||||
[reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html). But `me` is *not* such a
|
||||
reserved word (as mentioned, it's just something Evennia came up with for convenience in the `py`
|
||||
command). As far as the module is concerned `me` is an unfamiliar name, appearing out of nowhere.
|
||||
Hence the `NameError`.
|
||||
The `NameError` 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 `print` is because that is a special [reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html). But `me` is *not* such a reserved word (as mentioned, it's just something Evennia came up with for convenience in the `py` command). As far as the module is concerned `me` is an unfamiliar name, appearing out of nowhere. Hence the `NameError`.
|
||||
|
||||
## Passing arguments to functions
|
||||
|
||||
We know that `me` exists at the point when we run the `py` command, because we can do `py me.msg("Hello World!")`
|
||||
with no problem. So let's _pass_ that me along to the function so it knows what it should be.
|
||||
Go back to your `test.py` and change it to this:
|
||||
We know that `me` exists at the point when we run the `py` command, because we can do `py me.msg("Hello World!")` with no problem. So let's _pass_ that me along to the function so it knows what it should be. Go back to your `test.py` and change it to this:
|
||||
|
||||
```python
|
||||
def hello_world(who):
|
||||
who.msg("Hello World!")
|
||||
```
|
||||
We now added an _argument_ to the function. We could have named it anything. Whatever `who` is,
|
||||
we will call a method `.msg()` on it.
|
||||
We now added an _argument_ to the function. We could have named it anything. Whatever `who` is, we will call a method `.msg()` on it.
|
||||
|
||||
As usual, `reload` the server to make sure the new code is available.
|
||||
|
||||
> py import world.test ; world.test.hello_world(me)
|
||||
Hello World!
|
||||
|
||||
Now it worked. We _passed_ `me` to our function. It will appear inside the function renamed as `who` and
|
||||
now the function works and prints as expected. Note how the `hello_world` function doesn't care _what_ you
|
||||
pass into it as long as it has a `.msg()` method on it. So you could reuse this function over and over for other
|
||||
suitable targets.
|
||||
Now it worked. We _passed_ `me` to our function. It will appear inside the function renamed as `who` and now the function works and prints as expected. Note how the `hello_world` function doesn't care _what_ you pass into it as long as it has a `.msg()` method on it. So you could reuse this function over and over for other suitable targets.
|
||||
|
||||
> **Extra Credit:** As an exercise, try to pass something else into `hello_world`. Try for example
|
||||
>to pass the number `5` or the string `"foo"`. You'll get errors telling you that they don't have
|
||||
> to pass the number `5` or the string `"foo"`. You'll get errors telling you that they don't have
|
||||
>the attribute `msg`. They don't care about `me` 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 *validating*
|
||||
>`who` to make sure it's of the right type before you send it. This is usually not recommended in Python.
|
||||
>Python philosophy is to [handle](https://docs.python.org/2/tutorial/errors.html) the error if it happens
|
||||
>familiar with other programming languages (especially C/Java) you may be tempted to start *validating* `who` to make sure it's of the right type before you send it. This is usually not recommended in Python. Python philosophy is to [handle](https://docs.python.org/2/tutorial/errors.html) the error if it happens
|
||||
>rather than to add a lot of code to prevent it from happening. See [duck typing](https://en.wikipedia.org/wiki/Duck_typing)
|
||||
>and the concept of _Leap before you Look_.
|
||||
|
||||
|
|
@ -426,7 +361,6 @@ On the game command-line, let's create a mirror:
|
|||
> create/drop mirror:contrib.tutorials.mirror.TutorialMirror
|
||||
|
||||
```{sidebar} Creating objects
|
||||
|
||||
The `create` command was first used to create boxes in the
|
||||
[Building Stuff](./Beginner-Tutorial-Building-Quickstart.md) tutorial. You should now recognize
|
||||
that it uses a "python-path" to tell Evennia where to load the mirror's code from.
|
||||
|
|
|
|||
|
|
@ -47,16 +47,13 @@ face you stand where the moor meets the sea along a high, rocky coast ...*
|
|||
### Gameplay hints
|
||||
|
||||
- Use the command `tutorial` to get code insight behind the scenes of every room.
|
||||
- Look at everything. While a demo, the Tutorial World is not necessarily trivial to solve - it depends
|
||||
on your experience with text-based adventure games. Just remember that everything can be solved or bypassed.
|
||||
- Some objects are interactive in more than one way. Use the normal `help` command to get a feel for
|
||||
which commands are available at any given time.
|
||||
- Look at everything. While a demo, the Tutorial World is not necessarily trivial to solve - it depends on your experience with text-based adventure games. Just remember that everything can be solved or bypassed.
|
||||
- Some objects are interactive in more than one way. Use the normal `help` command to get a feel for which commands are available at any given time.
|
||||
- In order to fight, you need to first find some type of weapon.
|
||||
- *slash* is a normal attack
|
||||
- *stab* launches an attack that makes more damage but has a lower chance to hit.
|
||||
- *defend* will lower the chance to taking damage on your enemy's next attack.
|
||||
- Some things _cannot_ be hurt by mundane weapons. In that case it's OK to run away. Expect
|
||||
to be chased though.
|
||||
- Some things _cannot_ be hurt by mundane weapons. In that case it's OK to run away. Expect to be chased ...
|
||||
- Being defeated is a part of the experience. You can't actually die, but getting knocked out
|
||||
means being left in the dark ...
|
||||
|
||||
|
|
@ -84,41 +81,26 @@ Some features exemplified by the tutorial world:
|
|||
|
||||
```{sidebar} Extra Credit
|
||||
|
||||
If you have previous programming experience (or after you have gone
|
||||
through this Starter tutorial) it may be instructive to dig a little deeper into the Tutorial-world
|
||||
code to learn how it achieves what it does. The code is heavily documented.
|
||||
You can find all the code in [evennia/contrib/tutorials/tutorial_world](../../../api/evennia.contrib.tutorials.tutorial_world.md).
|
||||
If you are already familiar with Python and want an early taste, it can be constructive to dig a little deeper into the Tutorial-world to learn how it achieves what it does. The code is heavily documented. You can find all the code in [evennia/contrib/tutorials/tutorial_world](../../../api/evennia.contrib.tutorials.tutorial_world.md).
|
||||
The build-script is [here](github:evennia/contrib/tutorials/tutorial_world/build.ev).
|
||||
|
||||
|
||||
When reading the code, remember that the Tutorial World was designed to install easily and to not permanently modify
|
||||
the rest of the game. It therefore makes sure to only use temporary solutions and to clean up after itself. This is
|
||||
not something you will often need to worry about when making your own game.
|
||||
When reading the tutorial-world code, note that the Tutorial World was designed to install easily and to not permanently modify the rest of the game. It therefore makes sure to only use temporary solutions and to clean up after itself. This is not something you will often need to worry about when making your own game.
|
||||
```
|
||||
|
||||
Quite a lot of stuff crammed in such a small area!
|
||||
|
||||
## Uninstall the tutorial world
|
||||
|
||||
Once are done playing with the tutorial world, let's uninstall it.
|
||||
Uninstalling the tutorial world basically means deleting all the rooms and objects it consists of.
|
||||
Make sure you are back in Limbo, then
|
||||
Once you are done playing with the tutorial world, let's uninstall it. Uninstalling the tutorial world basically means deleting all the rooms and objects it consists of. Make sure you are back in Limbo, then
|
||||
|
||||
find tut#01
|
||||
find tut#16
|
||||
|
||||
This should locate the first and last rooms created by `build.ev` - *Intro* and *Outro*. If you
|
||||
installed normally, everything created between these two numbers should be part of the tutorial.
|
||||
Note their #dbref numbers, for example 5 and 80. Next we just delete all objects in that range:
|
||||
This should locate the first and last rooms created by `build.ev` - *Intro* and *Outro*. If you installed normally, everything created between these two numbers should be part of the tutorial. Note their #dbref numbers, for example 5 and 80. Next we just delete all objects in that range:
|
||||
|
||||
del 5-80
|
||||
|
||||
You will see some errors since some objects are auto-deleted and so cannot be found when the delete
|
||||
mechanism gets to them. That's fine. You should have removed the tutorial completely once the
|
||||
command finishes.
|
||||
|
||||
Even if the game-style of the Tutorial-world was not similar to the one you are interested in, it
|
||||
should hopefully have given you a little taste of some of the possibilities of Evennia. Now we'll
|
||||
move on with how to access this power through code.
|
||||
|
||||
You will see some errors since some objects are auto-deleted and so cannot be found when the delete mechanism gets to them. That's fine. You should have removed the tutorial completely once the command finishes.
|
||||
|
||||
Even if the game-style of the Tutorial-world was not similar to the one you are interested in, it should hopefully have given you a little taste of some of the possibilities of Evennia. Now we'll move on with how to access this power through code.
|
||||
Loading…
Add table
Add a link
Reference in a new issue