Main      Site Guide    
Smash Tutorial

Overview of Smash


Location Files

The basic idea behind Smash is this: each "location" you are permitted to travel to in the game has a separate file of Smash code associated with it, which defines what happens at that location.

Each game location is assigned a "tag" which is a keyword used to refer to that location. The filename of the Smash code that describes what the game should do at that location is the location's tag, plus a .sma extension. For example, if you have a location in the game that you choose to name "field," then the file named field.sma contains the information about what the game should do whenever the player is at that location.

Functions Files

If your game is complex enough, there may be sections of code that you want to have executed in more than one place. In such situations, it makes sense to put each block of repeated code into a function, and call that function wherever you need to execute that same block of code. Functions can be located within location files, or they can be placed in their own .sma files, alone or in groups. If you have a .sma file that does not correspond directly with a physical location within the game but rather contains functions called by other code, then this is a function file. The difference is largely academic: there is no syntactic difference between the code that goes into location files vs. functions files, but the distinction is sometimes helpful when talking about the code.

The "Start" File

The start.sma file is a special file containing Smash code that is executed only once at the very beginning of the game. Typically, the start file contains introductory text, what location the player begins the game in, and the initial settings for any variables you might need to set.

The Object Data Files

There are a few data files you need that are not written in Smash but simply contain raw data. One of them is the objects.txt file, which contains a list of the carryable objects in the game. If your game does not have carryable objects, then you don't need to have this file.

Similarly, there is an eobjects.txt file, which is basically the same thing but refers to objects you can carry more than one of. (The "e" in "eobjects" stands for "enumerated.") We will discuss this in more detail later.

The Object Actions Files

The objectactions.sma and eobjectactions.sma contain code that defines what happens when the player selects an object he is carrying. Typically, this code displays a short description of what the object looks like, but really there is no restriction on what you can have the game do when the user selects an object.

Commands

In Smash, actions are specified through commands, which consist of only a single character. This single character is usually followed by additional information. For example, the code to "move" a player to another location looks like this:

g house

The g command is the command to "go" to another location. In the above example, "house" is the location tag of the location you are moving to.

Here is another example of a Smash command:

p You stubbed your toe on a rock.

The p command is the command you use to specify what the action text -- that is, the text that describes what happened as a result of your last move -- should say. Here, the line of code is saying that the action text should be set to "You stubbed your toe on a rock."

Variables

Variables store information about the state of the game at any given time. They can keep track of what the player has accomplished so far, what's left to do, and so on.

Smash has three types of variables: state variables, which are readable from anywhere but only editable from the location in which they were defined; global variables, which are readable and editable from anywhere; and timers, which autoincrement or autodecrement after every turn (timers are useful for situations where it's important for the player to accomplish something within a set amount of turns).

Variables do not need to be declared ahead of their first use. All variables are initialized to zero. All variables are signed 64-bit integers. Smash cannot store strings or fractional numbers in variables.

The s command assigns a value to a state variable; the v command assigns a value to a global variable; and the t command assigns a value to a timer. Here is a sample snippet of Smash code that manipulates some variables:

s gate_is_open = 1 v tore_shirt = 1 t - timer = 50

The above snippet of code sets the state variable "gate_is_open" to 1, the global variable "tore_shirt" to 1, and sets a downward counting timer called "timer" to 50.

Don't worry if you're confused! This will all be explained in more detail later.

Objects

"Objects" in Smash refer to the items a player may carry around. A player's "inventory" refers to all the items the player is carrying at a given time. There are two types of objects -- regular and enumerated. Regular objects are unique. Enumerated objects allow you to specify how many of the objects you have at any given time. (The most common enumerated object is a unit of currency. Using an enumerated object such as "coin," you can allow the player to accumulate or spend any amount of money.)

Each object has a tag associated with it. For example, let's say your game has an object called a "Box of Chocolates." Though the object will be displayed to the user as a "Box of Chocolates," the Smash code that refers to it will use a shorter string, such as "box," which is the object's tag.

The Smash commands a and d add and drop regular objects from the player's inventory, respectively. Here is a sample snippet of Smash code that adds the "box" object to the player's inventory, while removing his "carrot" object:

a box d carrot

Enumerated objects are handled somewhat differently. The syntax actually resembles that of setting a variable, but with the e command, and instead of using a variable name, you use an object tag defined in the eobjects.txt file:

e coins = 5

When the enumerated object's value is 0, the player isn't carrying any of them, and it will not appear in the player's inventory. Otherwise, it will. This will also be discussed in greater depth later.

Control Flow

Control flow -- that is, determining what lines of code execute when -- is determined solely by indentation using the tab character. Unlike most modern languages, where tabs and spaces are ignored, spacing is very important in Smash. Let's look at the example below:

c s = 5 p A dragon came along and knocked you into the river. g river

The c command is a conditional, analogous to the "if" command in many other programming languages. The s = 5 is the condition. The above code says that if the variable s currently equals 5, then all the code indented beneath that line should be executed. If s does not equal five, nothing happens.

Note that the indentation must be precise: the indentation must be achieved with a tab character rather than multiple spaces, and only one tab character should be used.

This example illustrates the importance of correct indenting. Compare the above code with the following code:

c s = 5 p A dragon came along and knocked you into the river. g river

In the first example, if s = 5, then the action text would be set to the message about the dragon, and the player would be moved to the new location called "river." Otherwise, nothing would happen.

In the second example, the action text would be set only if s = 5, but the player would be moved to the "river" location no matter what. The conditional only affects code that is indented beneath it -- any code that appears on the same level of indentation signifies the end of the conditional code block.

Note that conditional code blocks may be nested inside of each other:

c s = 5 c a:shield p The dragon came along, but your shield protected you. c d:shield p The dragon came along and knocked you into the river. g river

In the above code, nothing will happen if s does not equal 5, but if it does, then two more conditionals will be tried. If the a:shield condition is true, the action text will be set to "The dragon came along, but your shield protected you," and if the d:shield condition is true, then the action text will be set to "The dragon came along and knocked you into the river," and the player will be moved to the "river" location.

The a:shield condition means "if the player has the 'shield' object," and the d:shield condition means "if the player does not have the 'shield' object." We will discuss all the various conditions a c command may have later.

Like many other languages with conditional statements (usually "if"), Smash has an "else" statement, which is a capital C. The above code snippet could be rewritten more efficiently as follows:

c s = 5 c a:shield p The dragon came along, but your shield protected you. C p The dragon came along and knocked you into the river. g river

Again, we will discuss this in more detail later, so don't worry if you're confused.

Multi-Line Commands

Indentation is also used in multi-line commands. The p command, which sets the action text, is an example of a command that may take more than one line:

p The dragon swoops down out of the sky, grasps you in its sharp talons, and carries you away to its lair.

In this example, the action text was too long to fit on one line, so it was broken up into two lines. However, the second line must be indented or the Smash engine will think "carries you away to its lair." is the next command it should execute rather than part of the previous one.

It is not uncommon for the action text to take three or four or five lines, and there is no hard limit on the number of lines you may use. As long as every line after the first is indented, it should work:

p As you extend your hand to pick up the bucket, the old woman glares at you evilly and swats you with a broom. "Lay off my stuff, you wily thief! Or I'll have the police all over you like bees over honey!" You shy away uncertainly.

Options

The heart of Smash is the options provided on the screen for the user. In Smash, there are three types of options: constant options, movement options, and action options.

The distinction between movement options and action options is more for the user's benefit than the programmer's, because they are handled in the code in exactly the same manner. By convention, movement options are options that involve the player trying to move to new locations, while action options are options that involve the player doing things within the current location. This is not enforced by the engine itself -- you can have action options that move the player to new locations, and movement options that do not -- but grouping all the "go somewhere" choices together in a separate place from the "do something" options makes the game more navigable for its players.

The command to add a movement option is the ^ command. The * command adds an action option. Each of these commands accepts a code block after it, which must be indented according to the same rules as conditionals. These code blocks contain what should be done only if and when the user selects that option. Here is an example:

^ n Go north. g house ^ e Go east. p On your way to the backyard, you trip over a garden hose. Oops. g backyard ^ s Go south. p You try to hoist yourself over the fence but can't. * dance Dance merrily. p You dance a quick jig. Suddenly, a leprechaun appears before you and laughs his head off. "Thanks for the laugh, buddy." He disappears again. * jump Jump up and down. p You jump up and down, stumble, and roll down the hill into the backyard. g backyard

In the above code, five options are provided to the user. No other code from this example is executed until after the user selects an option. At that point, only the code for the selected option is executed. So if the user chose to "go north," the g house command would be executed, and the player's new location would be set to the location named "house."

The syntax of the ^ and * commands is a little strange. Immediately after the ^ or * character, there is a keyword, followed by the text of the option which should be displayed to the user. It doesn't matter what this short keyword is, so long as there are no other options of that type with the same keyword presented to the user at the same time. This keyword is required by the engine so that, when the user selects an option, the engine knows where to find it in the code.

The "go south" option illustrates how, even though it is a movement option, there is no actual requirement that a move take place. Likewise, the "jump up and down" option illustrates how an action option can still move you somewhere else.

Sometimes you will want to make certain options available only under certain conditions. The following code illustrates how the "turn the switch on" option is available only when the switch is currently off. Assume the state variable "light_switch" is 0 when the switch is off and 1 when the switch is on.

c light_switch = 0 * on Turn the switch on. p Ok, you have turned the switch on. s light_switch = 1

This same technique could be used to provide a "turn the switch off" option.

Functions

If you find yourself repeating snippets of code a lot, you might want to move that code into a function, instead. A function looks like this:

~ examine_the_area * ex Examine the area. c earthquake_happened = 0 p The room looks neat and tidy. Everything is in its proper place. C p The room is in shambles. Dust chokes out the light.

This will allow you to add this same "Examine the area" function in multiple locations without having to repeat the code for it.

Let's say that this function block appears in a file called add_options.sma, which might contain other functions for supplying options to the user. Then, in each location you want to have this "Examine the area" option, you would include a line like this:

f add_options.examine_the_area

Basically, the f command calls a function, and the ~ command defines what a function does.

Comments

Comments can be included in .sma files by beginning a line with a # symbol. For example:

# This function is called when the user examines the area: ~ examine_the_area * ex Examine the area. # When an earthquake happens, the description of the area changes. c earthquake_happened = 0 p The room looks neat and tidy. Everything is in its proper place. C p The room is in shambles. Dust chokes out the light.

Note that comments can only be included in .sma files -- they can't go in the special files with .txt extensions.