User:Banana gun/Making Games In DWAINE

From Space Station 13 Wiki
Jump to navigation Jump to search

Making Games In DWAINE

Here's a handy finite state machine that can be used as a choose-your-own-adventure game, a quiz, or whatever your creativity allows it to be.

I'll also describe how it works and some of the tips and tricks I've learned for DWAINE.

The code

The code below is formatted in a specific way: there are double backslashes on places where a normal backslash is intended. This is for the purpose of correct copy-pasting into paper; they serve no purpose in the actual code.

File: ./game

#!
if $argc 1 lt | echo Valid arguments: start, help, scene | break
eval $arg0 to argument
if $argument help eq | echo {How to play: Actions are performed by commands starting with "act", and then the action you wish to perform. Potential actions are generally all lowercase, and designated by quotations in the scene dialogue. } | break
if $argument start eq | rm ./bin/scene | echo {Tutorial: Actions in this game are performed by first typing "act", and then the action you wish to perform. To start the game, perform the action "play", by typing "act play".} 0:play ^ ./bin/scene
grep -o \\{.*?\\} ./bin/scene

File: ./act

#! 
if $argc 1 lt | echo An action is required. | else | eval (\d+)\\: to regex | eval regex $arg0 + to regex | eval $(grep -o $regex ./bin/scene) to currentsave | eval (.\*?)\\( to regex | eval regex $currentsave + to regex | eval regex \\) + to regex | rm ./bin/scene | grep -o $regex ./bin/source ^ ./bin/scene 
grep -o \\{.\*?\\} ./bin/scene

How to use it

There are 3 files that are required to get this engine working:

  1. game
  2. act
  3. bin/source

First, locate a suitable DWAINE console, and the nearest scanner. The easiest way to load all files in reasonable time is to play as a silicon, since they have access to an integrated typewriter, and can access the DWAINE console from right next to the scanner. Copy and paste each code above into 2 separate papers, then locate your scanner's path with ls /mnt, and call this function for each of the papers:

mv /mnt/sc-location/document ./filename

Replace filename with the aforementioned names, and sc-location with your actual scanner's location.

The names of the commands aren't super important, so you can rename them for your preferred theme.

Source

The last file, bin/source, is up to you to create. The format for it is simple enough, it follows a pattern of

{scenedisplay} sceneindex:word (sceneindex)

An example of this format in action:

{This is scene 0, which is the starting point. Call act with arg0 "one" to go to scene 1, or "two" to go to scene two} 1:one 2:two (0)
{This is scene 1. Call act with arg0 "zero" to go to scene 0, or "two" to go to scene two} 0:zero 2:two (1) 
{This is scene 2. Scene two has multiple lines!} (2)
{Type act zero to go to scene 0, or act one to go to scene one.} 0:zero 1:one (2)

At this point, you can just call mkdir bin , scan the file, and put it in your new directory. To start the game, call game start which should automatically create the scene file with the format specified within the game file.

Code explanation (AKA the NERD ZONE)

DWAINE is difficult to use for advanced projects. However, there is a saving grace that can ease the pain a bit.

The grep command has two specific features that allow for a lot more freedom in development.

  1. It allows for a variable to be used in the regex format argument: ie grep -o $regex ./bin/scene , where $regex is the format that you can construct yourself.
  2. It can pipe to a file: ie grep -o $regex ./bin/source ^ ./bin/scene , where the result of the grep is put into bin/scene.

Those two features allow for a lot of freedom, and if you know regex, you can do a whole lot with it. Let's walk through the act file, and see where the aforementioned concepts come in handy.

eval (\d+)\: to regex
eval regex $arg0 + to regex
eval $(grep -o $regex ./bin/scene) to currentsave

This code constructs a regex format like this: (\d+)\:$arg0. Let's assume that $arg0 is "play", so this becomes (\d+)\:play.

That regex extracts any format like number:play from the given file, bin/scene, and stores it in the currentsave variable. The :play portion is excluded, because DWAINE is wacky. Let's assume that $currentsave is 1 in this case.

This is used in this segment:

eval (.*?)\( to regex
eval regex $currentsave + to regex
eval regex \) + to regex 

This creates a regex like (.*?)\(1\), which gets all the characters in the line behind (1). When applied from bin/source in grep -o $regex ./bin/source ^ ./bin/scene , it applies the scene that was extracted from the option in $arg0 to bin/scene.

After all that, it's relatively simple to print the current scene. Just calling grep -o \{.*?\} ./bin/scene shows all lines enclosed in {}.

To recap: bin/scene acts as a buffer for the current scene, holding the display and the options. bin/source acts as a database for all options from which bin/scene pulls from using the scene index, which was extracted from the last bin/scene.

Closing notes

Using the concepts above, it should not be impossible to expand the capabilities of this "engine" to include some more features.

I've also noted that the date command gets the current time in the round, and can be redirected to a file with a ^. This can be used for a psuedo random number generator, probably by ($(date) * 12345) % $range or something along those lines.

If you're having trouble with performance in your DWAINE scripts, try batching calls together. You can do that by putting them in an if/else statement. If your program doesn't need one, then you can format your code like if 1 | code | morecode | evenmorecode .

My act command used to take 3-5 seconds to run with all commands seperated, but when I batched them all into the initial if/else statement, it worked perfectly, running in roughly a second, give or take. Just keep in mind that DWAINE stream redirection is weird: I found that putting the grep -o \{.*?\} ./bin/scene inside the if statement would not output it to the console.