Making Maps Switch Randomly

I set up a race server that fetures map that change randomly every few rounds. Many people asked me how to set up their own, so before i answer each one of them, I will post it in here.

What You Need

  • You should have read and undestood the map making tutorial and already created a few maps. I won't explain how to create maps, just how to integrate them
  • You should know a scripting language like PHP, Perl or Python. You can use any language you want. Also, you should know a bit about shellscripts
  • You should know a bit about your armagetron installation and how to run a server. Better install a server and play around with it first for a bit. Also try integrating a few maps you created by hand onto your server and make sure they work fine. You need to know where the server stores its log files and its settings
  • The server needs to have access to a public webserver, either on the same machine or reachable per ftp or scp

As you can see, this tutorial is not intended for people who are new to armagetron, so try something easier first.

Setting up The Script

Ok, now fire up a text editor and use the programming language you like most to program a script that outputs random mazes to the console. Here is a very simple script in PHP, just to show you how it works:

#!/usr/bin/php
<?='<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>'?>

<!DOCTYPE Resource SYSTEM "map-0.2.8_beta3.dtd">

<Resource type="aamap" name="Fancy maze" version="0.2" author="wrtlprnft" category="random">

<Map version="0.2.8">
    <Settings>
        <Setting name="ARENA_AXES" value="4" />
    </Settings>
<World>
    <Field>
        <Axes number="4" />
        <Wall>
            <Point x="0"   y="0"   />
            <Point x="100" y="0"   />
            <Point x="100" y="100" />
            <Point x="0"   y="100" />
            <Point x="0"   y="0"   />
        </Wall>
        <Spawn x="1" y="1" angle="90" />
        <?php
            $x1 = rand(10,90);
            $x2 = rand(10,90);
            $y1 = rand(10,90);
            $y2 = rand(10,90);
            print('<Wall><Point x="'.$x1.'" y="'.$y1.'" /><Point x="'.$x2.'" y="'.$y2.'" /></Wall>');
        ?>
    </Field>
</World>
</Map>
</Resource>

This example script just outputs a 100x100 box with a random line through it, so there is definitely room for improvements.

Once you're done programming, call your script from the command- line (after making it executable) and redirect the output into a file:

$ ./fancymazegenerator.php >output.xml

Play with the maze like you would normally do to see if the script outputted the maze you wanted.

Tip: If you want to clear the worst bugs before setting up the server (it is easiest before), directly redirect the output to ~/.armagetronad/resource/automatic/test.xml, fire up armagetron, start a single player game and type map_file test.xml on the console. now your map loads and you can see your bugs. Then debug your script and run it again, redirecting the output to the same file, while keeping arma still running. On the next round it will use the new version, saving you a lot of trouble you'd have if you were testing on a dedicated server.

Bonus Tip: If your map won't load in the client, be sure to check if the output of the script doesn't contain any warnings or errors from PHP or whatever language you use. The output may only contain a valid map file or the client will refuse to load it.

Once you are done with all the debugging copy the script to the server.

Server Configuration

The only important part in the server configuation is the settings_custom.cfg. Here you need to set where the client and server can find the maps:

#don't use map_uri anymore... it could get removed in future versions
map_uri 0
#set the address of your web server here. Don't forget the slash at the end, it's important
resource_repository_server http://example.com/arma/

In the path you gave in the config create a directory named by your nickname. This is important to ensure maps from different administrators won't interfere with each other.

Now test your configuration by putting one of your maps in the directory you just creating, starting the server and entering this on the console:

MAP_FILE yournickname/filename.xml

the map_file and resource_repository_server given in this configuration will cause the client and server to search for the file on the url http://example.com/arma/yournickname/filename.xml, so make sure it's available there.

If that's working fine, you're almost done! You just have to get the server to automatically run your script to generate a new maze, to put it on your webserver and update the MAP_FILE server setting when it's done.

Creating And Using The Mazes Automatically

The best way I found to get a new maze every round is to use the server log files and an external shellscript.

In the log directory (the directory that also contains the ladder, won matches/rounds and highscores) is a file named scorelog.txt in which the server prints various messages. The interesting part for this is that it prints the line "New Round" in it whenever a new round starts and "New Match" whenever a new match is beginning, so this is the ideal file for us.

Ok, now we know how to know how to get the info when a new round or match starts. But how do we get the server to change the MAP_FILE setting? There's two ways: We could either pipe the output of the script we're going to program through the armagetron server, but this will mean we can't use the console anymore to change settings by hand.

The better way is the everytime.cfg which lies in the server config. The server reads it at the beginning of every round and executes all commands in it.

Ok, now we have everything, so let's hack together a shellscript:

#!/bin/sh

# temporary file to store the filenumber of the maze.
# the filename needs to change to make the server and
# client fetch the newest version
NUM_FILE=$HOME/armanumfile

# local path to the web server
WEBSRV_PATH=/var/www/htdocs/arma/
# URL for the webserver. Needs to point to the same
# directory as above.
REMOTE_URI=http://example.com/arma/
# name for the map files. The number and the extension
# .xml get attached to it.
MAP_FILE_NAME=yourusername/fancymaze
# name of your everytime.cfg
EVERYTIME_CFG=$HOME/tronsrv/etc/games/armagetronad-dedicated/everytime.cfg
# path to the map generator script
GENERATOR_SCRIPT=$HOME/fancymazegenerator.php

# test if the number file exist, if not, create it
test -e $NUM_FILE || echo 1 >$NUM_FILE
# read the file number
num=`cat $NUM_FILE`
while true
do
    # read the next line from STDIN
    read line
    # if it isn't the message we're hoping for wait for
    # the next one
    test "$line" == "New Round" || continue
    # increment our counter variable and store it
    num=`expr $num + 1`
    echo $num >$NUM_FILE
    # Output a status message
    echo new map number $num
    # run the script and put it on the webserver
    "$GENERATOR_SCRIPT" >"$WEBSRV_PATH$MAP_FILE_NAME$num".xml
    # inform the arma server to load the script
    echo "MAP_FILE ""$MAP_FILE_NAME$num.xml ($REMOTE_URI$MAP_FILE_NAME$num.xml)" > "$EVERYTIME_CFG"
done

Change all variables to the right values and you're set. If you need to push the maps onto another server, you have to create temporary files and use a method like ftp or scp to put them onto the server, but I'm sure you can figure out how. Another thing you might wish to do is to delete old map files.

Now start the server, then on another console start your shellscript with the following command:

$ tail -f $HOME/tronsrv/var/scorelog.txt | $HOME/tronsrv/arma-update.sh

Of course, your paths to the script and logfiles may differ, so make sure you use the right ones.

If you did everything right, you should now have a tronserver with randomly changing maps!