It’s highly recommended that you jump in on the Starting Tutorial. Even if
+
It’s highly recommended that you jump in on the Starting Tutorial. Even if
you only the beginning or some part of it, it covers much of the things needed to get started, including giving you are first introduction to Python.
diff --git a/docs/1.0-dev/Coding/Coding-Overview.html b/docs/1.0-dev/Coding/Coding-Overview.html
index 860aa4f9d1..76de7a7938 100644
--- a/docs/1.0-dev/Coding/Coding-Overview.html
+++ b/docs/1.0-dev/Coding/Coding-Overview.html
@@ -111,7 +111,7 @@
make your game, also if you never coded before. If you are an experienced coder, much of this will be familiar to you, but some things may still be useful.
diff --git a/docs/1.0-dev/Components/TickerHandler.html b/docs/1.0-dev/Components/TickerHandler.html
index 03175fe94d..3c596be46a 100644
--- a/docs/1.0-dev/Components/TickerHandler.html
+++ b/docs/1.0-dev/Components/TickerHandler.html
@@ -191,7 +191,7 @@ may store.
When testing, you can stop all tickers in the entire game with tickerhandler.clear(). You can also
view the currently subscribed objects with tickerhandler.all().
-
See the Weather Tutorial for an example of using the TickerHandler.
+
See the Weather Tutorial for an example of using the TickerHandler.
Using the TickerHandler may sound very useful but it is important to consider when not to use it.
diff --git a/docs/1.0-dev/Concepts/Web-Features.html b/docs/1.0-dev/Concepts/Web-Features.html
index d7666364d2..cb03b37239 100644
--- a/docs/1.0-dev/Concepts/Web-Features.html
+++ b/docs/1.0-dev/Concepts/Web-Features.html
@@ -148,7 +148,7 @@ change from the web
Example: To override or modify evennia/web/website/template/website/index.html you need to
add/modify mygame/web/template_overrides/website/index.html.
The detailed description on how to customize the website is best described in tutorial form. See the
-Web Tutorial for more information.
This tutorial describes the creation of an in-game map display based on a pre-drawn map. It also
-details how to use the Batch code processor for advanced building. There is
-also the Dynamic in-game map tutorial that works in the opposite direction,
-by generating a map from an existing grid of rooms.
This tutorial describes the creation of an in-game map display based on a pre-drawn map. It goes with the Mapbuilder contrib. It also details how to use the Batch code processor for advanced building.
Evennia does not require its rooms to be positioned in a “logical” way. Your exits could be named
anything. You could make an exit “west” that leads to a room described to be in the far north. You
could have rooms inside one another, exits leading back to the same room or describing spatial
@@ -148,9 +143,8 @@ Exits: north(#8), east(#9), south(#10), west(#11)
We will henceforth assume your game folder is name named mygame and that you haven’t modified the
-default commands. We will also not be using Colors for our map since they
+dkefault commands. We will also not be using Colors for our map since they
don’t show in the documentation wiki.
Let’s begin with the fun part! Maps in MUDs come in many different [shapes and
@@ -187,7 +181,7 @@ planning at this stage can solve many problems before they happen.
In this section we will try to create an actual “map” object that an account can pick up and look
at.
Evennia offers a range of default commands for
-creating objects and rooms in-game. While readily accessible, these commands are made to do very
+creating objects and rooms in-game. While readily accessible, these commands are made to do very
specific, restricted things and will thus not offer as much flexibility to experiment (for an
advanced exception see the FuncParser). Additionally, entering long
descriptions and properties over and over in the game client can become tedious; especially when
@@ -494,8 +488,8 @@ Prompt use evennia<
easily new game defining features can be added to Evennia.
You can easily build from this tutorial by expanding the map and creating more rooms to explore. Why
not add more features to your game by trying other tutorials: [Add weather to your world](Weather-
-Tutorial), fill your world with NPC’s or
-implement a combat system.
@@ -159,6 +159,7 @@ be used on the second iteration. The iteration number and a dictionary of
references to rooms previously created is passed to the build commands.
You then call the command in-game using the path to the MAP and MAP_LEGEND vars
The path you provide is relative to the evennia or mygame folder.
Use by importing and including the command in your default_cmdsets module.
@@ -383,6 +384,8 @@ convenience The below example code should be in
+
+
This document page is generated from evennia/contrib/grid/mapbuilder/README.md. Changes to this
file will be overwritten, so edit that file rather than this one.
@@ -406,7 +409,7 @@ file will be overwritten, so edit that file rather than this one.
modules |
Contribs are optional code snippets and systems contributed by
the Evennia community. They vary in size and complexity and
may be more specific about game types and styles than ‘core’ Evennia.
-This page is auto-generated and summarizes all contribs currently included.
+This page is auto-generated and summarizes all 46 contribs currently included
+with the Evennia distribution.
All contrib categories are imported from evennia.contrib, such as
from evennia.contrib.base_systems import building_menu
@@ -185,15 +192,108 @@ This page is auto-generated and summarizes all contribs currently included.
Each contrib contains installation instructions for how to integrate it
with your other code. If you want to tweak the code of a contrib, just
copy its entire folder to your game directory and modify/use it from there.
-
-
Hint: Additional (potentially un-maintained) code snippets from the community can be found
-in our discussion forum’s Community Contribs & Snippets category.
This category contains systems that are not necessarily tied to a specific
-in-game mechanic but is useful for the game as a whole. Examples include
+
Systems that are not necessarily tied to a specific
+in-game mechanic but which are useful for the game as a whole. Examples include
login systems, new command syntaxes, and build helpers.
@@ -214,16 +314,16 @@ login systems, new command syntaxes, and build helpers.
Contrib by The Right Honourable Reverend (trhr), 2020
This plugin migrates the Web-based portion of Evennia, namely images,
javascript, and other items located inside staticfiles into Amazon AWS (S3)
cloud hosting. Great for those serving media with the game.
Building menus are in-game menus, not unlike EvMenu though using a
different approach. Building menus have been specifically designed to edit
@@ -233,16 +333,16 @@ steps to add the contrib, you will have access to an Read the documentation - Browse the Code
Additional color markup styles for Evennia (extending or replacing the default
|r, |234). Adds support for MUSH-style (%cr, %c123) and/or legacy-Evennia
({r, {123).
Contrib by vlgeoff, 2017 - based on Griatch’s core original
This reimplements the evennia.utils.gametime module but with a custom
calendar (unusual number of days per week/month/year etc) for your game world.
@@ -259,16 +359,16 @@ Like the original, it allows for scheduling events to happen at given
in-game times, but now taking this custom calendar into account.
This is a variant of the login system that asks for an email-address
instead of a username to login. Note that it does not verify the email,
it just uses it as the identifier rather than a username.
This contrib adds the ability to script with Python in-game. It allows trusted
staff/builders to dynamically add features and triggers to individual objects
@@ -280,16 +380,16 @@ security concerns (you must trust your builders deeply), so read the warnings in
this module carefully before continuing.
Contribution by Vincent-lg 2016. Reworked for modern EvMenu by Griatch, 2019.
This changes the Evennia login to ask for the account name and password as a series
of questions instead of requiring you to enter both at once. It uses Evennia’s
menu system EvMenu under the hood.
In Evennia 1.0+, the old Channel commands (originally inspired by MUX) were
replaced by the single channel command that performs all these functions.
@@ -298,8 +398,8 @@ separate Commands more familiar to MU* users. This is just for show though, the
main channel command is still called under the hood.
This module contains a command class with an alternate syntax parser implementing
Unix-style command syntax in-game. This means --options, positional arguments
@@ -311,15 +411,15 @@ library under the hood.
A full engine for creating multiplayer escape-rooms in Evennia. Allows players to
spawn and join puzzle rooms that track their state independently. Any number of players
@@ -331,10 +431,10 @@ content but contains the utilities and base classes and an empty example room.
This category holds code implementing in-game gameplay systems like
-crafting, mail, combat and more. Each system is meant to be adopted
-piecemeal and adopted for your game. This does not include
-roleplaying-specific systems, those are found in the rpg folder.
+
In-game gameplay systems like crafting, mail, combat and more.
+Each system is meant to be adopted piecemeal and adopted for your game.
+This does not include roleplaying-specific systems, those are found in
+the rpg category.
This implements a full barter system - a way for players to safely
trade items between each other in code rather than simple give/get
@@ -360,15 +460,15 @@ be moved automatically). By just replacing one side with coin objects,
transactions.
Cooldowns are used to model rate-limited actions, like how often a
character can perform a given action; until a certain time has passed their
@@ -377,8 +477,8 @@ handler that can be attached to any typeclass. A cooldown is a lightweight persi
asynchronous timer that you can query to see if a certain time has yet passed.
This implements a full crafting system. The principle is that of a ‘recipe’,
where you combine items (tagged as ingredients) create something new. The recipe can also
@@ -386,8 +486,8 @@ require certain (non-consumed) tools. An example would be to use the ‘bread re
combine ‘flour’, ‘water’ and ‘yeast’ with an ‘oven’ to bake a ‘loaf of bread’.
This is a simple gender-aware Character class for allowing users to
insert custom markers in their text to indicate gender-aware
@@ -395,8 +495,8 @@ messaging. It relies on a modified msg() and is meant as an
inspiration and starting point to how to do stuff like this.
A simple Brandymail style mail system that uses the Msg class from Evennia
Core. It has two Commands for either sending mails between Accounts (out of game)
@@ -404,8 +504,8 @@ or between Characters (in-game). The two types of mails can be used together or
on their own.
A “multidescer” is a concept from the MUSH world. It allows for
creating, managing and switching between multiple character
@@ -414,8 +514,8 @@ changing clothes) in more free-form roleplaying systems. This will also
work well together with the rpsystem contrib.
Intended for adventure-game style combination puzzles, such as combining fruits
and a blender to create a smoothie. Provides a typeclass and commands for objects
@@ -424,8 +524,8 @@ puzzle is built from unique objects rather than using tags and a builder can cre
the puzzle entirely from in-game.
This is a framework for a simple turn-based combat system, similar
to those used in D&D-style tabletop role playing games. It allows
@@ -439,8 +539,8 @@ the participants until the fight ends.
This extends the normal Room typeclass to allow its description to change
with time-of-day and/or season. It also adds ‘details’ for the player to look at
@@ -461,8 +561,8 @@ in the room (without having to create a new in-game object for each). The room i
supported by new look and desc commands.
This adds an ascii map to a given room which can be viewed with the map command.
You can easily alter it to add special characters, room colors etc. The map shown is
@@ -470,22 +570,22 @@ dynamically generated on use, and supports all compass directions and up/down. O
directions are ignored.
A simple two-way exit that represents a door that can be opened and
closed from both sides. Can easily be expanded to make it lockable,
destroyable etc.
An example of an Exit-type that delays its traversal. This simulates
slow movement, common in many games. The contrib also
@@ -493,8 +593,8 @@ contains two commands, Read the documentation - Browse the Code
This contrib provides a wilderness map without actually creating a large number
of rooms - as you move, you instead end up back in the same room but its description
@@ -502,8 +602,8 @@ changes. This means you can make huge areas with little database use as
long as the rooms are relatively similar (name/desc changing).
Places Evennia’s game world on an xy (z being different maps) coordinate grid.
Grid is created and maintained externally by drawing and parsing 2D ASCII maps,
@@ -516,7 +616,7 @@ current location (useful for displaying the grid as an in-game, updating map).
A buff is a timed object, attached to a game entity. It is capable of modifying values, triggering code, or both.
It is a common design pattern in RPGs, particularly action games.
A dice roller for any number and side of dice. Adds in-game dice rolling
(roll2d10+1) as well as conditionals (roll under/over/equal to a target)
@@ -550,8 +650,8 @@ and functions for rolling dice in code. Command also supports hidden or secret
rolls for use by a human game master.
The function provided in this module lets you easily display visual
bars or meters as a colorful bar instead of just a number. A “health bar”
@@ -559,8 +659,8 @@ is merely the most obvious use for this, but the bar is highly customizable
and can be used for any sort of appropriate data besides player health.
A full roleplaying emote system. Short-descriptions and recognition (only
know people by their looks until you assign a name to them). Room poses. Masks/disguises
@@ -571,8 +671,8 @@ very powerful in-emote reference system, for referencing and differentiate targe
(including objects).
Contribution by Griatch 2020, based on code by Whitenoise and Ainneve contribs, 2014
A Trait represents a modifiable property on (usually) a Character. They can
be used to represent everything from attributes (str, agi etc) to skills
@@ -588,7 +688,8 @@ healed).
Helper resources specifically meant to teach a development concept or
to exemplify an Evennia system. Any extra resources tied to documentation
-tutorials are found here. Also the home of the Tutorial World demo adventure.
+tutorials are found here. Also the home of the Tutorial-World and Evadventure
+demo codes.
Simple examples for the batch-processor. The batch processor is used for generating
in-game content from one or more static files. Files can be stored with version
control and then ‘applied’ to the game to create content.
A stand-alone tutorial area for an unmodified Evennia install.
Think of it as a sort of single-player adventure rather than a
@@ -661,8 +762,7 @@ is a great way to start learning the system.
Utility that taps and intercepts all data sent to/from clients and the
server and passes it to a callback of your choosing. This is intended for
quality assurance, post-incident investigations and debugging.
This module contains a function that generates an EvMenu for you - this
menu presents the player with a form of fields that can be filled
@@ -693,14 +793,14 @@ function. Once the form is submitted, the form’s data is submitted as a dictio
to any callable of your choice.
A module to integrate a stripped-down version of git within the game, allowing developers to view their git status, change branches, and pull updated code of both their local mygame repo and Evennia core. After a successful pull or checkout, the git command will reload the game: Manual restarts may be required to to apply certain changes that would impact persistent scripts etc.
A module for generating random names, both real-world and fantasy. Real-world
names can be generated either as first (personal) names, family (last) names, or
@@ -708,8 +808,8 @@ full names (first, optional middles, and last). The name data is from CC BY-SA 4.0 license.
This utility can be used to generate pseudo-random strings of information
with specific criteria. You could, for instance, use it to generate
@@ -717,8 +817,8 @@ phone numbers, license plate numbers, validation codes, in-game security
passwords and so on. The strings generated will be stored and won’t be repeated.
This utility allows you to create and initialize an entire branching EvMenu
instance from a multi-line string passed to one function.
diff --git a/docs/1.0-dev/Evennia-Introduction.html b/docs/1.0-dev/Evennia-Introduction.html
index ef43c33691..f33e2a9c45 100644
--- a/docs/1.0-dev/Evennia-Introduction.html
+++ b/docs/1.0-dev/Evennia-Introduction.html
@@ -157,7 +157,7 @@ you need to know depending on your skills and needs.
Evennia’s source code is extensively documented. But while Python is considered a very easy programming language to get into, you do have a learning curve to climb if you are new to programming. Evennia’s Starting-tutorial has a basic introduction to Python but you should probably also sit down with a full Python beginner’s tutorial at some point (there are plenty of them on the web if you look around). See also our link page for some reading suggestions.
+
Evennia’s source code is extensively documented. But while Python is considered a very easy programming language to get into, you do have a learning curve to climb if you are new to programming. Evennia’s Starting-tutorial has a basic introduction to Python but you should probably also sit down with a full Python beginner’s tutorial at some point (there are plenty of them on the web if you look around). See also our link page for some reading suggestions.
To code your dream game in Evennia you don’t need to be a Python guru, but you do need to be able to read example code containing at least these basic Python features:
It’s recommended you jump into the Beginner Tutorial. You can either follow it or jump around to lessons that seem interesting. You can also read the lead developer’s dev blog for many tidbits and snippets about Evennia’s development and structure.
+
It’s recommended you jump into the Beginner Tutorial. You can either follow it or jump around to lessons that seem interesting. You can also read the lead developer’s dev blog for many tidbits and snippets about Evennia’s development and structure.
Sometimes it’s easier to ask for help. Get engaged in the Evennia community by joining our Discord for direct support. Make an introductory post to our Discussion forum and say hi!.
diff --git a/docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Intro.html b/docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Overview.html
similarity index 88%
rename from docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Intro.html
rename to docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Overview.html
index 7fab6fc409..c41825a4d1 100644
--- a/docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Intro.html
+++ b/docs/1.0-dev/Howtos/Beginner-Tutorial/Beginner-Tutorial-Overview.html
@@ -17,7 +17,7 @@
-
+
Part 5: Showing the world Taking our new game online and let players try it out
-
Welcome to Evennia! This multi-part Beginner Tutorial will help you get off the ground. It consists
-of five parts, each with several lessons. You can pick what seems interesting, but if you
-follow through to the end you will have created a little online game of your own to play
-and share with others!
-
Use the menu on the right to get the index of each tutorial-part. Use the next
-and previous links to step from lesson to lesson.
+
Welcome to Evennia! This multi-part Beginner Tutorial will help you get off the ground.
+
You can pick what seems interesting, but if you follow through to the end you will have created a little online game of your own to play and share with others!
+
Use the menu on the right to get the index of each tutorial-part. Use the next and previous links at the top/bottom right of the page to step between lessons.
You need to know how to find your Terminal/Console in your OS. The Evennia server can be controlled
-from in-game, but you will need to use the command-line to get anywhere. Here are some starters:
+
You need to know how to find your Terminal/Console in your OS. The Evennia server can be controlled from in-game, but you will need to use the command-line to get anywhere. Here are some starters:
You might already have a MUD-client you prefer. Check out the grid of supported clients.
If telnet’s not your thing, you can also just use Evennia’s web client in your browser.
-
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.
+
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.
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 - 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.
+
Here’s a blog post summing up some of the alternatives - 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
+
-
Hint: When setting up your editor, make sure 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.
Next you should make sure you have installed Evennia. If you followed the instructions
-you will already have created a game-dir. You could use that for this tutorial or you may want to do the
-tutorial in its own, isolated game dir; it’s up to you.
-
-
If you want a new gamedir for the tutorial game and already have Evennia running with another gamedir,
-first enter that gamedir and run
-
evennia stop
-
-
-
-
-
-
If you want to run two parallel servers, that’d be fine too, but one would have to use
-different ports from the defaults, or there’d be a clash. We will go into changing settings later.
-
-
-
Now go to where you want to create your tutorial-game. We will always refer to it as mygame so
-it may be convenient if you do too:
Add your superuser name and password at the prompt (email is optional). Make sure you can
-go to localhost:4000 in your MUD client or to http://localhost:4001
-in your web browser (Mac users: Try 127.0.0.1 instead of localhost if you have trouble).
-
The above --log flag will have Evennia output all its logs to the terminal. This will block
-the terminal from other input. To leave the log-view, press Ctrl-C (Cmd-C on Mac). To see
-the log again just run
You should make sure you have installed Evennia. 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 evenniastop to halt the running server and then Initialize a new game dir 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
Click here to expand a list of all Beginner-Tutorial sections (all parts).
@@ -116,17 +116,17 @@ from it at this time.
@@ -245,7 +245,7 @@ of experience using Evennia and be really helpful for doing your own thing later
>previous |
We now have the code underpinnings of everything we need. We have also tested the various components
-and has a simple tech-demo to show it all works together. But there is no real coherence to it at this
-point - we need to actually make a world.
-In part four we will expand our tech demo into a more full-fledged (if small) game by use of batchcommand
-and batchcode processors.
+
We now have the code underpinnings of everything we need. We have also tested the various components and has a simple tech-demo to show it all works together. But there is no real coherence to it at this point - we need to actually make a world. In part four we will expand our tech demo into a more full-fledged (if small) game by use of batchcommand and batchcode processors.
A lot of games use a separate time system we refer to as game time. This runs in parallel to what
-we usually think of as real time. The game time might run at a different speed, use different
-names for its time units or might even use a completely custom calendar. You don’t need to rely on a
-game time system at all. But if you do, Evennia offers basic tools to handle these various
-situations. This tutorial will walk you through these features.
A lot of games use a separate time system we refer to as game time. This runs in parallel to what we usually think of as real time. The game time might run at a different speed, use different
+names for its time units or might even use a completely custom calendar. You don’t need to rely on a game time system at all. But if you do, Evennia offers basic tools to handle these various situations. This tutorial will walk you through these features.
All is done through the settings. Here are the settings you should use if you want a game time with
@@ -150,11 +146,7 @@ a standard calendar:
TIME_GAME_EPOCH=None
-
By default, the game time runs twice as fast as the real time. You can set the time factor to be 1
-(the game time would run exactly at the same speed than the real time) or lower (the game time will
-be slower than the real time). Most games choose to have the game time spinning faster (you will
-find some games that have a time factor of 60, meaning the game time runs sixty times as fast as the
-real time, a minute in real time would be an hour in game time).
+
By default, the game time runs twice as fast as the real time. You can set the time factor to be 1 (the game time would run exactly at the same speed than the real time) or lower (the game time will be slower than the real time). Most games choose to have the game time spinning faster (you will find some games that have a time factor of 60, meaning the game time runs sixty times as fast as the real time, a minute in real time would be an hour in game time).
The epoch is a slightly more complex setting. It should contain a number of seconds that would
indicate the time your game started. As indicated, an epoch of 0 would mean January 1st, 1970. If
you want to set your time in the future, you just need to find the starting point in seconds. There
@@ -167,8 +159,7 @@ are several ways to do this in Python, this method will show you how to do it in
time.mktime(start.timetuple())
-
This should return a huge number - the number of seconds since Jan 1 1970. Copy that directly into
-your settings (editing server/conf/settings.py):
+
This should return a huge number - the number of seconds since Jan 1 1970. Copy that directly into your settings (editing server/conf/settings.py):
# in a file settings.py in mygame/server/confTIME_GAME_EPOCH=1577865600
@@ -197,20 +188,13 @@ time updated correctly… and going (by default) twice as fast as the real time.
The gametime utility also has a way to schedule game-related events, taking into account your game
-time, and assuming a standard calendar (see below for the same feature with a custom calendar). For
-instance, it can be used to have a specific message every (in-game) day at 6:00 AM showing how the
-sun rises.
-
The function schedule() should be used here. It will create a script with some
-additional features to make sure the script is always executed when the game time matches the given
-parameters.
+
The gametime utility also has a way to schedule game-related events, taking into account your game time, and assuming a standard calendar (see below for the same feature with a custom calendar). For instance, it can be used to have a specific message every (in-game) day at 6:00 AM showing how the sun rises.
+
The function schedule() should be used here. It will create a script with some additional features to make sure the script is always executed when the game time matches the given parameters.
The schedule function takes the following arguments:
The callback, a function to be called when time is up.
-
The keyword repeat (False by default) to indicate whether this function should be called
-repeatedly.
-
Additional keyword arguments sec, min, hour, day, month and year to describe the time
-to schedule. If the parameter isn’t given, it assumes the current time value of this specific unit.
+
The keyword repeat (False by default) to indicate whether this function should be called repeatedly.
+
Additional keyword arguments sec, min, hour, day, month and year to describe the time to schedule. If the parameter isn’t given, it assumes the current time value of this specific unit.
Here is a short example for making the sun rise every day:
# in a file ingame_time.py in mygame/world/
@@ -237,9 +221,7 @@ to schedule. If the parameter isn’t given, it assumes the current time value
The script will be created silently. The at_sunrise function will now be called every in-game day
at 6 AM. You can use the @scripts command to see it. You could stop it using @scripts/stop. If
we hadn’t set repeat the sun would only have risen once and then never again.
-
We used the @py command here: nothing prevents you from adding the system into your game code.
-Remember to be careful not to add each event at startup, however, otherwise there will be a lot of
-overlapping events scheduled when the sun rises.
+
We used the @py command here: nothing prevents you from adding the system into your game code. Remember to be careful not to add each event at startup, however, otherwise there will be a lot of overlapping events scheduled when the sun rises.
The schedule function when using repeat set to True works with the higher, non-specified unit.
In our example, we have specified hour, minute and second. The higher unit we haven’t specified is
day: schedule assumes we mean “run the callback every day at the specified time”. Therefore, you
@@ -253,24 +235,14 @@ such day in February, April etc. Similarly, leap years may change the number of
Using a custom calendar to handle game time is sometimes needed if you want to place your game in a
-fictional universe. For instance you may want to create the Shire calendar which Tolkien described
-having 12 months, each which 30 days. That would give only 360 days per year (presumably hobbits
-weren’t really fond of the hassle of following the astronomical calendar). Another example would be
-creating a planet in a different solar system with, say, days 29 hours long and months of only 18
-days.
+
Using a custom calendar to handle game time is sometimes needed if you want to place your game in a fictional universe. For instance you may want to create the Shire calendar which Tolkien described having 12 months, each which 30 days. That would give only 360 days per year (presumably hobbits weren’t really fond of the hassle of following the astronomical calendar). Another example would be creating a planet in a different solar system with, say, days 29 hours long and months of only 18 days.
Evennia handles custom calendars through an optional contrib module, called custom_gametime.
Contrary to the normal gametime module described above it is not active by default.
In our first example of the Shire calendar, used by hobbits in books by Tolkien, we don’t really
-need the notion of weeks… but we need the notion of months having 30 days, not 28.
-
The custom calendar is defined by adding the TIME_UNITS setting to your settings file. It’s a
-dictionary containing as keys the name of the units, and as value the number of seconds (the
-smallest unit for us) in this unit. Its keys must be picked among the following: “sec”, “min”,
-“hour”, “day”, “week”, “month” and “year” but you don’t have to include them all. Here is the
-configuration for the Shire calendar:
+
In our first example of the Shire calendar, used by hobbits in books by Tolkien, we don’t really need the notion of weeks… but we need the notion of months having 30 days, not 28.
+
The custom calendar is defined by adding the TIME_UNITS setting to your settings file. It’s a dictionary containing as keys the name of the units, and as value the number of seconds (the smallest unit for us) in this unit. Its keys must be picked among the following: “sec”, “min”, “hour”, “day”, “week”, “month” and “year” but you don’t have to include them all. Here is the configuration for the Shire calendar:
# in a file settings.py in mygame/server/confTIME_UNITS={"sec":1,"min":60,
@@ -280,11 +252,8 @@ configuration for the Shire calendar:
"year":60*60*24*30*12}
-
We give each unit we want as keys. Values represent the number of seconds in that unit. Hour is
-set to 60 * 60 (that is, 3600 seconds per hour). Notice that we don’t specify the week unit in this
-configuration: instead, we skip from days to months directly.
-
In order for this setting to work properly, remember all units have to be multiples of the previous
-units. If you create “day”, it needs to be multiple of hours, for instance.
+
We give each unit we want as keys. Values represent the number of seconds in that unit. Hour is set to 60 * 60 (that is, 3600 seconds per hour). Notice that we don’t specify the week unit in this configuration: instead, we skip from days to months directly.
+
In order for this setting to work properly, remember all units have to be multiples of the previous units. If you create “day”, it needs to be multiple of hours, for instance.
So for our example, our settings may look like this:
# in a file settings.py in mygame/server/conf# Time factor
@@ -304,19 +273,16 @@ units. If you create “day”, it needs to be multiple of hours, for instance.
}
-
Notice we have set a time epoch of 0. Using a custom calendar, we will come up with a nice display
-of time on our own. In our case the game time starts at year 0, month 1, day 1, and at midnight.
+
Notice we have set a time epoch of 0. Using a custom calendar, we will come up with a nice display of time on our own. In our case the game time starts at year 0, month 1, day 1, and at midnight.
Year, hour, minute and sec starts from 0, month, week and day starts from 1, this makes them
behave consistently with the standard time.
-
Note that while we use “month”, “week” etc in the settings, your game may not use those terms in-
-game, instead referring to them as “cycles”, “moons”, “sand falls” etc. This is just a matter of you
+
Note that while we use “month”, “week” etc in the settings, your game may not use those terms in- game, instead referring to them as “cycles”, “moons”, “sand falls” etc. This is just a matter of you
displaying them differently. See next section.
As pointed out earlier, the @time command is meant to be used with a standard calendar, not a
-custom one. We can easily create a new command though. We’ll call it time, as is often the case
+
As pointed out earlier, the @time command is meant to be used with a standard calendar, not a custom one. We can easily create a new command though. We’ll call it time, as is often the case
on other MU*. Here’s an example of how we could write it (for the example, you can create a file
gametime.py in your commands directory and paste this code in it):
# in a file mygame/commands/gametime.py
@@ -371,8 +337,7 @@ on other MU*. Here’s an example of how we could write it (for the example, yo
self.add(CmdTime())# <- Add
-
Reload your game with the @reload command. You should now see the time command. If you enter
-it, you might see something like:
+
Reload your game with the @reload command. You should now see the time command. If you enter it, you might see something like:
We are in year 0, day 0, month 0.
It's 00:52:17.
@@ -384,10 +349,7 @@ And if “months” are called “moons” in your game, this is where you’d a
The custom_gametime module also has a way to schedule game-related events, taking into account
-your game time (and your custom calendar). It can be used to have a specific message every day at
-6:00 AM, to show the sun rises, for instance. The custom_gametime.schedule function works in the
-same way as described for the default one above.
+
The custom_gametime module also has a way to schedule game-related events, taking into account your game time (and your custom calendar). It can be used to have a specific message every day at 6:00 AM, to show the sun rises, for instance. The custom_gametime.schedule function works in the same way as described for the default one above.
@@ -407,14 +369,14 @@ same way as described for the default one above.
modules |
Recommended starting point! This will take you from absolute beginner to making
@@ -123,18 +124,18 @@ a small but full game with Evennia. Other tutorials and howto’s tend to assume
This page was adapted from the article “Building a Giant Mech in Evennia” by Griatch, published in
-Imaginary Realities Volume 6, issue 1, 2014. The original article is no longer available online,
-this is a version adopted to be compatible with the latest Evennia.
Let us create a functioning giant mech using the Python MUD-creation system Evennia. Everyone likes
-a giant mech, right? Start in-game as a character with build privileges (or the superuser).
Let us create a functioning giant mech in Evennia. Everyone likes a giant mech, right? Start in-game as a character with build privileges (or the superuser).
+
create/drop Giant Mech ; mech
Boom. We created a Giant Mech Object and dropped it in the room. We also gave it an alias mech.
Let’s describe it.
-
@desc mech = This is a huge mech. It has missiles and stuff.
+
desc mech = This is a huge mech. It has missiles and stuff.
Next we define who can “puppet” the mech object.
-
@lock mech = puppet:all()
+
lock mech = puppet:all()
-
This makes it so that everyone can control the mech. More mechs to the people! (Note that whereas
-Evennia’s default commands may look vaguely MUX-like, you can change the syntax to look like
-whatever interface style you prefer.)
-
Before we continue, let’s make a brief detour. Evennia is very flexible about its objects and even
-more flexible about using and adding commands to those objects. Here are some ground rules well
-worth remembering for the remainder of this article:
+
This makes it so that everyone can control the mech. More mechs to the people! (Note that whereas Evennia’s default commands may look vaguely MUX-like, you can change the syntax to look like whatever interface style you prefer.)
+
Before we continue, let’s make a brief detour. Evennia is very flexible about its objects and even more flexible about using and adding commands to those objects. Here are some ground rules well worth remembering for the remainder of this article:
The Account represents the real person logging in and has no game-world existence.
Any Object can be puppeted by an Account (with proper permissions).
Any Object can be inside another (except if it creates a loop).
Any Object can store custom sets of commands on it. Those commands can:
be made available to the puppeteer (Account),
be made available to anyone in the same location as the Object, and
be made available to anyone “inside” the Object
-
Also Accounts can store commands on themselves. Account commands are always available unless
-commands on a puppeted Object explicitly override them.
+
Also Accounts can store commands on themselves. Account commands are always available unless commands on a puppeted Object explicitly override them.
-
In Evennia, using the @ic command will allow you to puppet a given Object (assuming you have
-puppet-access to do so). As mentioned above, the bog-standard Character class is in fact like any
-Object: it is auto-puppeted when logging in and just has a command set on it containing the normal
-in-game commands, like look, inventory, get and so on.
-
@ic mech
+
In Evennia, using the ic command will allow you to puppet a given Object (assuming you have puppet-access to do so). As mentioned above, the bog-standard Character class is in fact like any Object: it is auto-puppeted when logging in and just has a command set on it containing the normal in-game commands, like look, inventory, get and so on.
+
ic mech
You just jumped out of your Character and are now the mech! If people look at you in-game, they
will look at a mech. The problem at this point is that the mech Object has no commands of its own.
The usual things like look, inventory and get sat on the Character object, remember? So at the
moment the mech is not quite as cool as it could be.
-
@ic <Your old Character>
+
ic <Your old Character>
You just jumped back to puppeting your normal, mundane Character again. All is well.
-
(But, you ask, where did that @ic command come from, if the mech had no commands on it? The
-answer is that it came from the Account’s command set. This is important. Without the Account being
-the one with the @ic command, we would not have been able to get back out of our mech again.)
+
Where did that ic command come from, if the mech had no commands on it? The
+answer is that it came from the Account’s command set. This is important. Without the Account being the one with the ic command, we would not have been able to get back out of our mech again.
Let us make the mech a little more interesting. In our favorite text editor, we will create some new
mech-suitable commands. In Evennia, commands are defined as Python classes.
# in a new file mygame/commands/mechcommands.py
@@ -220,18 +201,10 @@ mech-suitable commands. In Evennia, commands are defined as Python classes.
-
This is saved as a normal Python module (let’s call it mechcommands.py), in a place Evennia looks
-for such modules (mygame/commands/). This command will trigger when the player gives the command
-“shoot”, “fire,” or even “fire!” with an exclamation mark. The mech can shoot in the air or at a
-target if you give one. In a real game the gun would probably be given a chance to hit and give
+
This is saved as a normal Python module (let’s call it mechcommands.py), in a place Evennia looks for such modules (mygame/commands/). This command will trigger when the player gives the command “shoot”, “fire,” or even “fire!” with an exclamation mark. The mech can shoot in the air or at a target if you give one. In a real game the gun would probably be given a chance to hit and give
damage to the target, but this is enough for now.
-
We also make a second command for launching missiles (CmdLaunch). To save
-space we won’t describe it here; it looks the same except it returns a text
-about the missiles being fired and has different key and aliases. We leave
-that up to you to create as an exercise. You could have it print “WOOSH! The
-mech launches missiles against !”, for example.
-
Now we shove our commands into a command set. A Command Set (CmdSet) is a container
-holding any number of commands. The command set is what we will store on the mech.
+
We also make a second command for launching missiles (CmdLaunch). To save space we won’t describe it here; it looks the same except it returns a text about the missiles being fired and has different key and aliases. We leave that up to you to create as an exercise. You could have it print "WOOSH!Themechlaunchesmissilesagainst<target>!, for example.
+
Now we shove our commands into a command set. A Command Set (CmdSet) is a container holding any number of commands. The command set is what we will store on the mech.
# in the same file mygame/commands/mechcommands.pyfromevenniaimportCmdSet
@@ -249,15 +222,12 @@ holding any number of commands. The command set is what we will store on the mec
self.add(CmdLaunch())
-
This simply groups all the commands we want. We add our new shoot/launch commands. Let’s head back
-into the game. For testing we will manually attach our new CmdSet to the mech.
This simply groups all the commands we want. We add our new shoot/launch commands. Let’s head back into the game. For testing we will manually attach our new CmdSet to the mech.
This is a little Python snippet (run from the command line as an admin) that searches for the mech
-in our current location and attaches our new MechCmdSet to it. What we add is actually the Python
-path to our cmdset class. Evennia will import and initialize it behind the scenes.
-
@ic mech
+
This is a little Python snippet that searches for the mech in our current location and attaches our new MechCmdSet to it. What we add is actually the Python path to our cmdset class. Evennia will import and initialize it behind the scenes.
+
ic mech
We are back as the mech! Let’s do some shooting!
@@ -265,23 +235,17 @@ path to our cmdset class. Evennia will import and initialize it behind the scene
BOOM! The mech fires its gun in the air!
-
There we go, one functioning mech. Try your own launch command and see that it works too. We can
-not only walk around as the mech — since the CharacterCmdSet is included in our MechCmdSet, the mech
-can also do everything a Character could do, like look around, pick up stuff, and have an inventory.
-We could now shoot the gun at a target or try the missile launch command. Once you have your own
-mech, what else do you need?
+
There we go, one functioning mech. Try your own launch command and see that it works too. We can not only walk around as the mech — since the CharacterCmdSet is included in our MechCmdSet, the mech can also do everything a Character could do, like look around, pick up stuff, and have an inventory. We could now shoot the gun at a target or try the missile launch command. Once you have your own mech, what else do you need?
-
Note: You’ll find that the mech’s commands are available to you by just standing in the same
+
You’ll find that the mech’s commands are available to you by just standing in the same
location (not just by puppeting it). We’ll solve this with a lock in the next section.
What we’ve done so far is just to make a normal Object, describe it and put some commands on it.
This is great for testing. The way we added it, the MechCmdSet will even go away if we reload the
-server. Now we want to make the mech an actual object “type” so we can create mechs without those
-extra steps. For this we need to create a new Typeclass.
+server. Now we want to make the mech an actual object “type” so we can create mechs without those extra steps. For this we need to create a new Typeclass.
A Typeclass is a near-normal Python class that stores its existence to the database
behind the scenes. A Typeclass is created in a normal Python source file:
# in the new file mygame/typeclasses/mech.py
@@ -302,41 +266,29 @@ behind the scenes. A Typeclass is created in a normal Python source file:
self.db.desc="This is a huge mech. It has missiles and stuff."
-
For convenience we include the full contents of the default CharacterCmdSet in there. This will
-make a Character’s normal commands available to the mech. We also add the mech-commands from before,
-making sure they are stored persistently in the database. The locks specify that anyone can puppet
-the meck and no-one can “call” the mech’s Commands from ‘outside’ it - you have to puppet it to be
-able to shoot.
-
That’s it. When Objects of this type are created, they will always start out with the mech’s command
-set and the correct lock. We set a default description, but you would probably change this with
-@desc to individualize your mechs as you build them.
+
For convenience we include the full contents of the default CharacterCmdSet in there. This will make a Character’s normal commands available to the mech. We also add the mech-commands from before, making sure they are stored persistently in the database. The locks specify that anyone can puppet the meck and no-one can “call” the mech’s Commands from ‘outside’ it - you have to puppet it to be able to shoot.
+
That’s it. When Objects of this type are created, they will always start out with the mech’s command set and the correct lock. We set a default description, but you would probably change this with desc to individualize your mechs as you build them.
Back in the game, just exit the old mech (@ic back to your old character) then do
-
@create/drop The Bigger Mech ; bigmech : mech.Mech
+
create/drop The Bigger Mech ; bigmech : mech.Mech
We create a new, bigger mech with an alias bigmech. Note how we give the python-path to our
Typeclass at the end — this tells Evennia to create the new object based on that class (we don’t
-have to give the full path in our game dir typeclasses.mech.Mech because Evennia knows to look in
-the typeclasses folder already). A shining new mech will appear in the room! Just use
-
@ic bigmech
+have to give the full path in our game dir typeclasses.mech.Mech because Evennia knows to look in the typeclasses folder already). A shining new mech will appear in the room! Just use
+
To expand on this you could add more commands to the mech and remove others. Maybe the mech
-shouldn’t work just like a Character after all. Maybe it makes loud noises every time it passes from
-room to room. Maybe it cannot pick up things without crushing them. Maybe it needs fuel, ammo and
-repairs. Maybe you’ll lock it down so it can only be puppeted by emo teenagers.
-
Having you puppet the mech-object directly is also just one way to implement a giant mech in
-Evennia.
Having you puppet the mech-object directly is just one way to implement a giant mech in Evennia.
For example, you could instead picture a mech as a “vehicle” that you “enter” as your normal
-Character (since any Object can move inside another). In that case the “insides” of the mech Object
-could be the “cockpit”. The cockpit would have the MechCommandSet stored on itself and all the
-shooting goodness would be made available to you only when you enter it.
+Character (since any Object can move inside another). In that case the “insides” of the mech Object could be the “cockpit”. The cockpit would have the MechCommandSet stored on itself and all the shooting goodness would be made available to you only when you enter it.
+
To expand on this you could add more commands to the mech and remove others. Maybe the mech shouldn’t work just like a Character after all.
+
Maybe it makes loud noises every time it passes from room to room. Maybe it cannot pick up things without crushing them. Maybe it needs fuel, ammo and repairs. Maybe you’ll lock it down so it can only be puppeted by emo teenagers.
And of course you could put more guns on it. And make it fly.
+
@@ -355,14 +307,14 @@ shooting goodness would be made available to you only when you enter it.
modules |
This tutorial explains how you can create vehicles that can move around in your world. The tutorial
-will explain how to create a train, but this can be equally applied to create other kind of vehicles
+
+
TODO: This should be updated for latest Evennia use.
+
+
Vehicles are things that you can enter and then move around in your game world. Here we’ll explain how to create a train, but this can be equally applied to create other kind of vehicles
(cars, planes, boats, spaceships, submarines, …).
Objects in Evennia have an interesting property: you can put any object inside another object. This
-is most obvious in rooms: a room in Evennia is just like any other game object (except rooms tend to
-not themselves be inside anything else).
+
Objects in Evennia have an interesting property: you can put any object inside another object. This is most obvious in rooms: a room in Evennia is just like any other game object (except rooms tend to not themselves be inside anything else).
Our train will be similar: it will be an object that other objects can get inside. We then simply
move the Train, which brings along everyone inside it.
The first step we need to do is create our train object, including a new typeclass. To do this,
create a new file, for instance in mygame/typeclasses/train.py with the following content:
-
# file mygame/typeclasses/train.py
+
# in mygame/typeclasses/train.pyfromevenniaimportDefaultObject
@@ -140,27 +136,21 @@ create a new file, for instance in
Now we can create our train in our game:
-
@create/droptrain:train.TrainObject
+
create/droptrain:train.TrainObject
Now this is just an object that doesn’t do much yet… but we can already force our way inside it
and back (assuming we created it in limbo).
Using the @telcommand like shown above is obviously not what we want. @tel is an admin command
-and normal players will thus never be able to enter the train! It is also not really a good idea to
-use Exits to get in and out of the train - Exits are (at least by default) objects
-too. They point to a specific destination. If we put an Exit in this room leading inside the train
-it would stay here when the train moved away (still leading into the train like a magic portal!). In
-the same way, if we put an Exit object inside the train, it would always point back to this room,
-regardless of where the Train has moved. Now, one could define custom Exit types that move with
-the train or change their destination in the right way - but this seems to be a pretty cumbersome
-solution.
+
Using the telcommand like shown above is obviously not what we want. @tel is an admin command and normal players will thus never be able to enter the train!
+
It is also not really a good idea to use Exits to get in and out of the train - Exits are (at least by default) objects too. They point to a specific destination. If we put an Exit in this room leading inside the train it would stay here when the train moved away (still leading into the train like a magic portal!). In the same way, if we put an Exit object inside the train, it would always point back to this room, regardless of where the Train has moved.
+
Now, one could define custom Exit types that move with the train or change their destination in the right way - but this seems to be a pretty cumbersome solution.
What we will do instead is to create some new commands: one for entering the train and
another for leaving it again. These will be stored on the train object and will thus be made
available to whomever is either inside it or in the same room as the train.
@@ -181,7 +171,6 @@ available to whomever is either inside it or in the same room as the train.
"""key="enter train"
- locks="cmd:all()"deffunc(self):train=self.obj
@@ -202,7 +191,6 @@ available to whomever is either inside it or in the same room as the train.
"""key="leave train"
- locks="cmd:all()"deffunc(self):train=self.obj
@@ -219,34 +207,29 @@ available to whomever is either inside it or in the same room as the train.
Note that while this seems like a lot of text, the majority of lines here are taken up by
documentation.
-
These commands are work in a pretty straightforward way: CmdEnterTrain moves the location of the
-player to inside the train and CmdLeaveTrain does the opposite: it moves the player back to the
-current location of the train (back outside to its current location). We stacked them in a
-cmdsetCmdSetTrain so they can be used.
+
These commands are work in a pretty straightforward way: CmdEnterTrain moves the location of the player to inside the train and CmdLeaveTrain does the opposite: it moves the player back to the
+current location of the train (back outside to its current location). We stacked them in a cmdsetCmdSetTrain so they can be used.
To make the commands work we need to add this cmdset to our train typeclass:
Note the switches used with the @typeclass command: The /force switch is necessary to assign our
-object the same typeclass we already have. The /reset re-triggers the typeclass’
-at_object_creation() hook (which is otherwise only called the very first an instance is created).
+
Note the switches used with the typeclass command: The /force switch is necessary to assign our object the same typeclass we already have. The /reset re-triggers the typeclass’ at_object_creation() hook (which is otherwise only called the very first an instance is created).
As seen above, when this hook is called on our train, our new cmdset will be loaded.
@@ -254,15 +237,10 @@ As seen above, when this hook is called on our train, our new cmdset will be loa
If you have played around a bit, you’ve probably figured out that you can use leavetrain when
outside the train and entertrain when inside. This doesn’t make any sense … so let’s go ahead
and fix that. We need to tell Evennia that you can not enter the train when you’re already inside
-or leave the train when you’re outside. One solution to this is locks: we will lock down
-the commands so that they can only be called if the player is at the correct location.
-
Right now commands defaults to the lock cmd:all(). The cmd lock type in combination with the
-all() lock function means that everyone can run those commands as long as they are in the same
-room as the train or inside the train. We’re going to change this to check the location of the
-player and only allow access if they are inside the train.
+or leave the train when you’re outside. One solution to this is locks: we will lock down the commands so that they can only be called if the player is at the correct location.
+
Since we didn’t set a lock property on the Command, it defaults to cmd:all(). This means that everyone can use the command as long as they are in the same room or inside the train.
First of all we need to create a new lock function. Evennia comes with many lock functions built-in
-already, but none that we can use for locking a command in this particular case. Create a new entry
-in mygame/server/conf/lockfuncs.py:
+already, but none that we can use for locking a command in this particular case. Create a new entry in mygame/server/conf/lockfuncs.py:
# file mygame/server/conf/lockfuncs.py
@@ -278,12 +256,7 @@ in mygame/server/co
If you didn’t know, Evennia is by default set up to use all functions in this module as lock
functions (there is a setting variable that points to it).
-
Our new lock function, cmdinside, is to be used by Commands. The accessed_obj is the Command
-object (in our case this will be CmdEnterTrain and CmdLeaveTrain) — Every command has an obj
-property: this is the the object on which the command “sits”. Since we added those commands to our
-train object, the .obj property will be set to the train object. Conversely, accessing_obj is
-the object that called the command: in our case it’s the Character trying to enter or leave the
-train.
+
Our new lock function, cmdinside, is to be used by Commands. The accessed_obj is the Command object (in our case this will be CmdEnterTrain and CmdLeaveTrain) — Every command has an obj property: this is the the object on which the command “sits”. Since we added those commands to our train object, the .obj property will be set to the train object. Conversely, accessing_obj is the object that called the command: in our case it’s the Character trying to enter or leave the train.
What this function does is to check that the player’s location is the same as the train object. If
it is, it means the player is inside the train. Otherwise it means the player is somewhere else and
the check will fail.
@@ -314,28 +287,23 @@ user ignores lock functions. In order to use this functionality you need to Now that we can enter and leave the train correctly, it’s time to make it move. There are different
things we need to consider for this:
-
Who can control your vehicle? The first player to enter it, only players that have a certain
-“drive” skill, automatically?
-
Where should it go? Can the player steer the vehicle to go somewhere else or will it always follow
-the same route?
+
Who can control your vehicle? The first player to enter it, only players that have a certain “drive” skill, automatically?
+
Where should it go? Can the player steer the vehicle to go somewhere else or will it always follow the same route?
-
For our example train we’re going to go with automatic movement through a predefined route (its
-track). The train will stop for a bit at the start and end of the route to allow players to enter
-and leave it.
-
Go ahead and create some rooms for our train. Make a list of the room ids along the route (using the
-@ex command).
-
@dig/telSouthstation
-@ex# note the id of the station
-@tunnel/teln=Followingarailroad
-@ex# note the id of the track
-@tunnel/teln=Followingarailroad
-...
-@tunnel/teln=NorthStation
+
For our example train we’re going to go with automatic movement through a predefined route (its track). The train will stop for a bit at the start and end of the route to allow players to enter and leave it.
+
Go ahead and create some rooms for our train. Make a list of the room ids along the route (using the xe command).
+
>dig/telSouthstation
+>ex# note the id of the station
+>tunnel/teln=Followingarailroad
+>ex# note the id of the track
+>tunnel/teln=Followingarailroad
+>...
+>tunnel/teln=NorthStation
Put the train onto the tracks:
-
@telsouthstation
-@teltrain=here
+
telsouthstation
+teltrain=here
Next we will tell the train how to move and which route to take.
@@ -377,26 +345,22 @@ and leave it.
self.msg_contents(f"The train is moving forward to {room.name}.")
-
We added a lot of code here. Since we changed the at_object_creation to add in variables we will
-have to reset our train object like earlier (using the @typeclass/force/reset command).
+
We added a lot of code here. Since we changed the at_object_creation to add in variables we will have to reset our train object like earlier (using the @typeclass/force/reset command).
We are keeping track of a few different things now: whether the train is moving or standing still,
which direction the train is heading to and what rooms the train will pass through.
-
We also added some methods: one to start moving the train, another to stop and a third that actually
-moves the train to the next room in the list. Or makes it stop driving if it reaches the last stop.
-
Let’s try it out, using @py to call the new train functionality:
We also added some methods: one to start moving the train, another to stop and a third that actually moves the train to the next room in the list. Or makes it stop driving if it reaches the last stop.
+
Let’s try it out, using py to call the new train functionality:
If we wanted full control of the train we could now just add a command to step it along the track
-when desired. We want the train to move on its own though, without us having to force it by manually
-calling the goto_next_room method.
+
If we wanted full control of the train we could now just add a command to step it along the track when desired. We want the train to move on its own though, without us having to force it by manually calling the goto_next_room method.
To do this we will create two scripts: one script that runs when the train has stopped at
a station and is responsible for starting the train again after a while. The other script will take
care of the driving.
@@ -457,9 +421,9 @@ train again., and we’re ready to ride it around!
self.scripts.add(TrainStoppedScript)
>reload
+>typeclass/force/resettrain=train.TrainObject
+>entertrain# output:<ThetrainismovingforwardtoFollowingarailroad.
@@ -479,14 +443,10 @@ train again., and we’re ready to ride it around!
This train is very basic and still has some flaws. Some more things to do:
Make it look like a train.
-
Make it impossible to exit and enter the train mid-ride. This could be made by having the
-enter/exit commands check so the train is not moving before allowing the caller to proceed.
+
Make it impossible to exit and enter the train mid-ride. This could be made by having the enter/exit commands check so the train is not moving before allowing the caller to proceed.
Have train conductor commands that can override the automatic start/stop.
Allow for in-between stops between the start- and end station
-
Have a rail road track instead of hard-coding the rooms in the train object. This could for
-example be a custom Exit only traversable by trains. The train will follow the
-track. Some track segments can split to lead to two different rooms and a player can switch the
-direction to which room it goes.
+
Have a rail road track instead of hard-coding the rooms in the train object. This could for example be a custom Exit only traversable by trains. The train will follow the track. Some track segments can split to lead to two different rooms and a player can switch the direction to which room it goes.
Create another kind of vehicle!
@@ -511,11 +471,11 @@ direction to which room it goes.
next |
This tutorial is moderately difficult in content. You might want to be familiar and at ease with
-some Python concepts (like properties) and possibly Django concepts (like queries), although this
-tutorial will try to walk you through the process and give enough explanations each time. If you
-don’t feel very confident with math, don’t hesitate to pause, go to the example section, which shows
-a tiny map, and try to walk around the code or read the explanation.
-
Evennia doesn’t have a coordinate system by default. Rooms and other objects are linked by location
-and content:
This tutorial is moderately difficult in content. You might want to be familiar and at ease with some Python concepts (like properties) and possibly Django concepts (like queries), although this tutorial will try to walk you through the process and give enough explanations each time. If you don’t feel very confident with math, don’t hesitate to pause, go to the example section, which shows a tiny map, and try to walk around the code or read the explanation.
+
Evennia doesn’t have a coordinate system by default. Rooms and other objects are linked by location and content:
An object can be in a location, that is, another object. Like an exit in a room.
An object can access its content. A room can see what objects uses it as location (that would
@@ -137,14 +132,8 @@ instance.
The first concept might be the most surprising at first glance: we will create coordinates as
tags.
-
-
Why not attributes, wouldn’t that be easier?
-
-
It would. We could just do something like room.db.x=3. The advantage of using tags is that it
-will be easy and effective to search. Although this might not seem like a huge advantage right now,
-with a database of thousands of rooms, it might make a difference, particularly if you have a lot of
-things based on coordinates.
-
Rather than giving you a step-by-step process, I’ll show you the code. Notice that we use
+
So, why not attributes, wouldn’t that be easier? It would. We could just do something like room.db.x=3. The advantage of using tags is that it will be easy and effective to search. Although this might not seem like a huge advantage right now, with a database of thousands of rooms, it might make a difference, particularly if you have a lot of things based on coordinates.
+
Rather than giving you a step-by-step process, We’ll show you the code. Notice that we use
properties to easily access and update coordinates. This is a Pythonic approach. Here’s our first
Room class, that you can modify in typeclasses/rooms.py:
# in typeclasses/rooms.py
@@ -227,12 +216,7 @@ The tags.get
We convert the value to an integer, if it’s a str. Remember that tags can only contain str,
so we’ll need to convert it.
-
-
I thought tags couldn’t contain values?
-
-
Well, technically, they can’t: they’re either here or not. But using tag categories, as we have
-done, we get a tag, knowing only its category. That’s the basic approach to coordinates in this
-tutorial.
+
So can Tags contain values? Well, technically, they can’t: they’re either here or not. But using tag categories, as we have done, we get a tag, knowing only its category. That’s the basic approach to coordinates in this tutorial.
Now, let’s look at the method that will be called when we wish to set x in our room:
@x.setterdefx(self,x):
@@ -249,19 +233,15 @@ tutorial.
room with “coordx” as their category, which wouldn’t do at all.
Then we add the new tag, giving it the proper category.
-
-
Now what?
-
If you add this code and reload your game, once you’re logged in with a character in a room as its
location, you can play around:
This solution includes a bit of Django
-queries.
-Basically, what we do is reach for the object manager and search for objects with the matching tags.
-Again, don’t spend too much time worrying about the mechanism, the method is quite easy to use:
+
This solution includes some Django queries. Basically, what we do is reach for the object manager and search for objects with the matching tags. Again, don’t spend too much time worrying about the mechanism, the method is quite easy to use:
Room.get_room_at(5,2,-3)
-
Notice that this is a class method: you will call it from Room (the class), not an instance.
-Though you still can:
-
@py here.get_room_at(3, 8, 0)
+
Notice that this is a class method: you will call it from Room (the class), not an instance. Though you still can:
Here’s another useful method that allows us to look for rooms around a given coordinate. This is
-more advanced search and doing some calculation, beware! Look at the following section if you’re
+
Here’s another useful method that allows us to look for rooms around a given coordinate. This is more advanced search and doing some calculation, beware! Look at the following section if you’re
lost.
frommathimportsqrt
@@ -385,9 +360,7 @@ lost.
We have specified coordinates as parameters. We determine a broad range using the distance.
That is, for each coordinate, we create a list of possible matches. See the example below.
-
We then search for the rooms within this broader range. It gives us a square
-around our location. Some rooms are definitely outside the range. Again, see the example below
-to follow the logic.
+
We then search for the rooms within this broader range. It gives us a square around our location. Some rooms are definitely outside the range. Again, see the example below to follow the logic.
We filter down the list and sort it by distance from the specified coordinates.
Notice that we only search starting at step 2. Thus, the Django search doesn’t look and cache all
@@ -406,24 +379,16 @@ optimized to be quick and efficient.
1234
-
The X coordinates are given below. The Y coordinates are given on the left. This is a simple
-square with 16 rooms: 4 on each line, 4 lines of them. All the rooms are identified by letters in
-this example: the first line at the top has rooms A to D, the second E to H, the third I to L and
-the fourth M to P. The bottom-left room, X=1 and Y=1, is M. The upper-right room X=4 and Y=4 is D.
-
So let’s say we want to find all the neighbors, distance 1, from the room J. J is at X=2, Y=2.
+
The X coordinates are given below. The Y coordinates are given on the left. This is a simple square with 16 rooms: 4 on each line, 4 lines of them. All the rooms are identified by letters in this example: the first line at the top has rooms A to D, the second E to H, the third I to L and the fourth M to P. The bottom-left room, X=1 and Y=1, is M. The upper-right room X=4 and Y=4 is D.
+So let’s say we want to find all the neighbors, distance 1, from the room J. J is at X=2, Y=2.
So we use:
Room.get_rooms_around(x=2, y=2, z=0, distance=1)
# we'll assume a z coordinate of 0 for simplicity
-
First, this method gets all the rooms in a square around J. So it gets E F G, I J K, M N O. If
-you want, draw the square around these coordinates to see what’s happening.
-
Next, we browse over this list and check the real distance between J (X=2, Y=2) and the room.
-The four corners of the square are not in this circle. For instance, the distance between J and M
-is not 1. If you draw a circle of center J and radius 1, you’ll notice that the four corners of our
-square (E, G, M and O) are not in this circle. So we remove them.
-
We sort by distance from J.
+
First, this method gets all the rooms in a square around J. So it gets E F G, I J K, M N O. If you want, draw the square around these coordinates to see what’s happening.
+
Next, we browse over this list and check the real distance between J (X=2, Y=2) and the room. The four corners of the square are not in this circle. For instance, the distance between J and M is not 1. If you draw a circle of center J and radius 1, you’ll notice that the four corners of our square (E, G, M and O) are not in this circle. So we remove them. 3. We sort by distance from J.
So in the end we might obtain something like this:
[
@@ -437,11 +402,11 @@ square (E, G, M and O) are not in this circle. So we remove them.
You can try with more examples if you want to see this in action.
An often desired feature in a MUD is to show an in-game map to help navigation. The Static in-game
-map tutorial solves this by creating a static map, meaning the map is pre-
-drawn once and for all - the rooms are then created to match that map. When walking around, parts of
-the static map is then cut out and displayed next to the room description.
-
In this tutorial we’ll instead do it the other way around; We will dynamically draw the map based on
-the relationships we find between already existing rooms.
There are at least two requirements needed for this tutorial to work.
-
The structure of your mud has to follow a logical layout. Evennia supports the layout of your
-world to be ‘logically’ impossible with rooms looping to themselves or exits leading to the other
-side of the map. Exits can also be named anything, from “jumping out the window” to “into the fifth
-dimension”. This tutorial assumes you can only move in the cardinal directions (N, E, S and W).
-
Rooms must be connected and linked together for the map to be generated correctly. Vanilla
-Evennia comes with a admin command tunnel that allows a
-user to create rooms in the cardinal directions, but additional work is needed to assure that rooms
-are connected. For example, if you tunneleast and then immediately do tunnelwest you’ll find
-that you have created two completely stand-alone rooms. So care is needed if you want to create a
-“logical” layout. In this tutorial we assume you have such a grid of rooms that we can generate the
-map from.
+
The structure of your mud has to follow a logical layout. Evennia supports the layout of your world to be ‘logically’ impossible with rooms looping to themselves or exits leading to the other side of the map. Exits can also be named anything, from “jumping out the window” to “into the fifth dimension”. This tutorial assumes you can only move in the cardinal directions (N, E, S and W).
+
Rooms must be connected and linked together for the map to be generated correctly. Vanilla Evennia comes with a admin command tunnel that allows a user to create rooms in the cardinal directions, but additional work is needed to assure that rooms are connected. For example, if you tunneleast and then immediately do tunnelwest you’ll find that you have created two completely stand-alone rooms. So care is needed if you want to create a “logical” layout. In this tutorial we assume you have such a grid of rooms that we can generate the map from.
Before getting into the code, it is beneficial to understand and conceptualize how this is going to
-work. The idea is analogous to a worm that starts at your current position. It chooses a direction
-and ‘walks’ outward from it, mapping its route as it goes. Once it has traveled a pre-set distance
-it stops and starts over in another direction. An important note is that we want a system which is
-easily callable and not too complicated. Therefore we will wrap this entire code into a custom
-Python class (not a typeclass as this doesn’t use any core objects from evennia itself).
-
We are going to create something that displays like this when you type ‘look’:
-
Hallway
+
Before getting into the code, it is beneficial to understand and conceptualize how this is going to work. The idea is analogous to a worm that starts at your current position. It chooses a direction and ‘walks’ outward from it, mapping its route as it goes. Once it has traveled a pre-set distance it stops and starts over in another direction. An important note is that we want a system which is easily callable and not too complicated. Therefore we will wrap this entire code into a custom Python class (not a typeclass as this doesn’t use any core objects from evennia itself). We are going to create something that displays like this when you type ‘look’:
Your current location is defined by [@] while the [.]s are other rooms that the “worm” has seen
@@ -164,12 +154,7 @@ since departing from your location.
First we must define the components for displaying the map. For the “worm” to know what symbol to
-draw on the map we will have it check an Attribute on the room it visits called sector_type. For
-this tutorial we understand two symbols - a normal room and the room with us in it. We also define a
-fallback symbol for rooms without said Attribute - that way the map will still work even if we
-didn’t prepare the room correctly. Assuming your game folder is named mygame, we create this code
-in mygame/world/map.py.
+
First we must define the components for displaying the map. For the “worm” to know what symbol to draw on the map we will have it check an Attribute on the room it visits called sector_type. For this tutorial we understand two symbols - a normal room and the room with us in it. We also define a fallback symbol for rooms without said Attribute - that way the map will still work even if we didn’t prepare the room correctly. Assuming your game folder is named mygame, we create this code in mygame/world/map.py.
# in mygame/world/map.py# the symbol is identified with a key "sector_type" on the
@@ -197,17 +182,11 @@ methods we need.
self.caller is normally your Character object, the one using the map.
-
self.max_width/length determine the max width and length of the map that will be generated. Note
-that it’s important that these variables are set to odd numbers to make sure the display area has
-a center point.
-
self.worm_has_mapped is building off the worm analogy above. This dictionary will store all
-rooms the “worm” has mapped as well as its relative position within the grid. This is the most
-important variable as it acts as a ‘checker’ and ‘address book’ that is able to tell us where the
-worm has been and what it has mapped so far.
+
self.max_width/length determine the max width and length of the map that will be generated. Note that it’s important that these variables are set to odd numbers to make sure the display area has a center point.
+
self.worm_has_mapped is building off the worm analogy above. This dictionary will store all rooms the “worm” has mapped as well as its relative position within the grid. This is the most important variable as it acts as a ‘checker’ and ‘address book’ that is able to tell us where the worm has been and what it has mapped so far.
self.curX/Y are coordinates representing the worm’s current location on the grid.
-
Before any sort of mapping can actually be done we need to create an empty display area and do some
-sanity checks on it by using the following methods.
+
Before any sort of mapping can actually be done we need to create an empty display area and do some sanity checks on it by using the following methods.
# in mygame/world/map.pyclassMap(object):
@@ -230,8 +209,7 @@ sanity checks on it by using the following methods.
elseFalse
-
Before we can set our worm on its way, we need to know some of the computer science behind all this
-called ‘Graph Traversing’. In Pseudo code what we are trying to accomplish is this:
+
Before we can set our worm on its way, we need to know some of the computer science behind all this called ‘Graph Traversing’. In Pseudo code what we are trying to accomplish is this:
# pseudo codedefdraw_room_on_map(room,max_distance):
@@ -252,35 +230,25 @@ called ‘Graph Traversing’. In Pseudo code what we are trying to accomplish i
The beauty of Python is that our actual code of doing this doesn’t differ much if at all from this
Pseudo code example.
-
max_distance is a variable indicating to our Worm how many rooms AWAY from your current location
-will it map. Obviously the larger the number the more time it will take if your current location has
-many many rooms around you.
+
max_distance is a variable indicating to our Worm how many rooms AWAY from your current location will it map. Obviously the larger the number the more time it will take if your current location has many many rooms around you.
-
The first hurdle here is what value to use for ‘max_distance’. There is no reason for the worm to
-travel further than what is actually displayed to you. For example, if your current location is
-placed in the center of a display area of size max_length=max_width=9, then the worm need only
+
The first hurdle here is what value to use for ‘max_distance’. There is no reason for the worm to travel further than what is actually displayed to you. For example, if your current location is placed in the center of a display area of size max_length=max_width=9, then the worm need only
go 4 spaces in either direction:
[.][.][.][.][@][.][.][.][.]432101234
-
The max_distance can be set dynamically based on the size of the display area. As your width/length
-changes it becomes a simple algebraic linear relationship which is simply max_distance=(min(max_width,max_length)-1)/2.
+
The max_distance can be set dynamically based on the size of the display area. As your width/length changes it becomes a simple algebraic linear relationship which is simply max_distance=(min(max_width,max_length)-1)/2.
Now we can start to fill our Map object with some methods. We are still missing a few methods that
-are very important:
+
Now we can start to fill our Map object with some methods. We are still missing a few methods that are very important:
self.draw(self,room) - responsible for actually drawing room to grid.
-
self.has_drawn(self,room) - checks to see if the room has been mapped and worm has already been
-here.
-
self.median(self,number) - a simple utility method that finds the median (middle point) from 0,
-n
-
self.update_pos(self,room,exit_name) - updates the worm’s physical position by reassigning
-self.curX/Y. .accordingly
-
self.start_loc_on_grid(self) - the very first initial draw on the grid representing your
-location in the middle of the grid
+
self.has_drawn(self,room) - checks to see if the room has been mapped and worm has already been here.
+
self.median(self,number) - a simple utility method that finds the median (middle point) from 0,n
+
self.update_pos(self,room,exit_name) - updates the worm’s physical position by reassigning self.curX/Y accordingly.
+
self.start_loc_on_grid(self) - the very first initial draw on the grid representing your location in the middle of the grid.
self.show_map - after everything is done convert the map into a readable string
self.draw_room_on_map(self,room,max_distance) - the main method that ties it all together.
@@ -307,10 +275,8 @@ conditional statements and set it up to start building the display.
-
Here we check to see if the parameters for the grid are okay, then we create an empty canvas and map
-our initial location as the first room!
-
As mentioned above, the code for the self.draw_room_on_map() is not much different than the Pseudo
-code. The method is shown below:
+
Here we check to see if the parameters for the grid are okay, then we create an empty canvas and map our initial location as the first room!
+
As mentioned above, the code for the self.draw_room_on_map() is not much different than the Pseudo code. The method is shown below:
# in mygame/world/map.py, in the Map classdefdraw_room_on_map(self,room,max_distance):
@@ -431,22 +397,9 @@ presentational string out of it using the return string
-
Obviously this method of generating maps doesn’t take into account of any doors or exits that are
-hidden… etc… but hopefully it serves as a good base to start with. Like previously mentioned, it
-is very important to have a solid foundation on rooms before implementing this. You can try this on
-vanilla evennia by using @tunnel and essentially you can just create a long straight/edgy non-
-looping rooms that will show on your in-game map.
-
The above example will display the map above the room description. You could also use an
-EvTable to place description and map next to each other. Some other
-things you can do is to have a Command that displays with a larger radius, maybe with a
-legend and other features.
-
Below is the whole map.py for your reference. You need to update your Room typeclass (see above)
-to actually call it. Remember that to see different symbols for a location you also need to set the
-sector_type Attribute on the room to one of the keys in the SYMBOLS dictionary. So in this
-example, to make a room be mapped as [.] you would set the room’s sector_type to
-"SECT_INSIDE". Try it out with @sethere/sector_type="SECT_INSIDE". If you wanted all new
-rooms to have a given sector symbol, you could change the default in the SYMBOLS dictionary below,
-or you could add the Attribute in the Room’s at_object_creation method.
+
Obviously this method of generating maps doesn’t take into account of any doors or exits that are hidden… etc… but hopefully it serves as a good base to start with. Like previously mentioned, it is very important to have a solid foundation on rooms before implementing this. You can try this on vanilla evennia by using @tunnel and essentially you can just create a long straight/edgy non- looping rooms that will show on your in-game map.
+
The above example will display the map above the room description. You could also use an EvTable to place description and map next to each other. Some other things you can do is to have a Command that displays with a larger radius, maybe with a legend and other features.
+
Below is the whole map.py for your reference. You need to update your Room typeclass (see above) to actually call it. Remember that to see different symbols for a location you also need to set the sector_type Attribute on the room to one of the keys in the SYMBOLS dictionary. So in this example, to make a room be mapped as [.] you would set the room’s sector_type to "SECT_INSIDE". Try it out with @sethere/sector_type="SECT_INSIDE". If you wanted all new rooms to have a given sector symbol, you could change the default in the SYMBOLS dictionary below, or you could add the Attribute in the Room’s at_object_creation method.
# mygame/world/map.py# These are keys set with the Attribute sector_type on the room.
@@ -587,14 +540,14 @@ also look into up/down directions and figure out how to display that in a good w
modules |
@@ -158,8 +158,7 @@ you would have trouble communicating with others in the game. One would need to
command for every kind of word or sentence, which is, of course, not practical.
Last thing: what is parsing?
-
In our case, parsing is the process by which we convert command arguments into something we can
-work with.
+
In our case, parsing is the process by which we convert command arguments into something we can work with.
We don’t usually use the command argument as is (which is just text, of type str in Python). We
need to extract useful information. We might want to ask the user for a number, or the name of
@@ -838,7 +837,7 @@ code.
This tutorial will have us create a simple weather system for our MUD. The way we want to use this
-is to have all outdoor rooms echo weather-related messages to the room at regular and semi-random
-intervals. Things like “Clouds gather above”, “It starts to rain” and so on.
-
One could imagine every outdoor room in the game having a script running on themselves that fires
-regularly. For this particular example it is however more efficient to do it another way, namely by
-using a “ticker-subscription” model. The principle is simple: Instead of having each Object
-individually track the time, they instead subscribe to be called by a global ticker who handles time
-keeping. Not only does this centralize and organize much of the code in one place, it also has less
-computing overhead.
-
Evennia offers the TickerHandler specifically for using the subscription model. We
-will use it for our weather system.
-
We will assume you know how to make your own Typeclasses. If not see one of the beginning tutorials.
-We will create a new WeatherRoom typeclass that is aware of the day-night cycle.
This tutorial will have us create a simple weather system for our MUD. The way we want to use this is to have all outdoor rooms echo weather-related messages to the room at regular and semi-random intervals. Things like “Clouds gather above”, “It starts to rain” and so on.
+
One could imagine every outdoor room in the game having a script running on themselves that fires regularly. For this particular example it is however more efficient to do it another way, namely by using a “ticker-subscription” model.
+
The principle is simple: Instead of having each Object individually track the time, they instead subscribe to be called by a global ticker who handles time keeping. Not only does this centralize and organize much of the code in one place, it also has less computing overhead.
+
Evennia’s TickerHandler specifically offers such a subscription model. We will use it for our weather system.
+
We will create a new WeatherRoom typeclass that is aware of the day-night cycle.
importrandomfromevenniaimportDefaultRoom,TICKER_HANDLERECHOES=["The sky is clear.",
@@ -132,7 +142,7 @@ We will create a new WeatherRoom typeclass that is aware of the day-night cycle.
"ticked at regular intervals"echo=random.choice(ECHOES)self.msg_contents(echo)
-
+
In the at_object_creation method, we simply added ourselves to the TickerHandler and tell it to
call at_weather_update every hour (60*60 seconds). During testing you might want to play with a
@@ -160,14 +170,14 @@ weather came before it. Expanding it to be more realistic is a useful exercise.<
modules |
diff --git a/docs/1.0-dev/Howtos/Tutorial-for-basic-MUSH-like-game.html b/docs/1.0-dev/Howtos/Tutorial-for-basic-MUSH-like-game.html
index 8bff0e8fe6..83254b491c 100644
--- a/docs/1.0-dev/Howtos/Tutorial-for-basic-MUSH-like-game.html
+++ b/docs/1.0-dev/Howtos/Tutorial-for-basic-MUSH-like-game.html
@@ -130,7 +130,7 @@
focused on free form storytelling. Even if you are not interested in MUSH:es, this is still a good
first game-type to try since it’s not so code heavy. You will be able to use the same principles for
building other types of games.
-
The tutorial starts from scratch. If you did the First Steps Coding tutorial
+
The tutorial starts from scratch. If you did the First Steps Coding tutorial
already you should have some ideas about how to do some of the steps already.
The following are the (very simplistic and cut-down) features we will implement (this was taken from
a feature request from a MUSH user new to Evennia). A Character in this system should:
Before doing this tutorial you will probably want to read the intro in
-Basic Web tutorial. Reading the three first parts of the
+Basic Web tutorial. Reading the three first parts of the
Django tutorial might help as well.
This tutorial will provide a step-by-step process to installing a wiki on your website.
Fortunately, you don’t have to create the features manually, since it has been done by others, and
@@ -331,7 +331,7 @@ solution for connecting the Evennia permission levels to wiki access, this is th
next |