Many map objects have special programs that define their behavior. You can describe these programs in their init.lua files, in the programs table.

Map objects that can have programs are:

Critters all run the same built-in program, so you don’t need to define any programs for them.


Map object programs are put in a Lua table, like this:

programs = {
   main = {
      "action1=parameter1:value1 parameter2:value2",
   program_name2 = {
      "action4=value1 value2 value3",
   program_name3 = {
      "action5=value1 value2 parameter:value3",

For productionsites, there is a nested actions table, so that we can give them a descname for the tooltips:

programs = {
   main = {
      -- TRANSLATORS: Completed/Skipped/Did not start doing something because ...
      descname = _("doing something"),
      actions = {
  • Named parameters of the form parameter:value can be given in any order, but we recommend using the order from the documentation for consistency. It will make your code easier to read.

  • Values without parameter name need to be given in the correct order.

  • Some actions combine both named and unnamed values, see action5 in our example.

If there is a program called "main", this is the default program. For productionsites, having a main program is mandatory. For immovables, having a main program is optional, because their programs can also be triggered by a productionsite or by a worker. Workers have no default program, because their individual programs are always called from their production site.

Data Types

Some numerical action parameters use units of measure to clarify their meaning.


Temporal duration is specified with an accompanying unit. Valid units are:

  • m (minutes)

  • s (seconds)

  • ms (milliseconds)

You can combine these units in descending order as you please. Examples:

  • 4m

  • 12s

  • 500ms

  • 4m12s

  • 12s500ms

  • 4m500ms

  • 4m12s500ms

  • 1m500s100000ms will work too, but is not recommended (unreadable)


A percent value. Valid unit is:

  • % (percent)

Maximum value is 100%. Examples:

  • 25%

  • 25.1%

  • 25.13%


The actions documented in this section are available to all map object types.


animate=\<name\> [duration:\<duration\>]

Switch to new animation and pause program execution for the given duration.

  • name (string) – The name of the animation to be played.

  • duration (duration) – The time Duration for which the program will wait before continuing on to the next action. If omitted, the program will continue to the next step immediately.

Example for a worker:

plantvine = {
   "findspace=size:any radius:1",
   "animate=dig duration:2s500ms", -- Play a digging animation for 2.5 seconds.
   "animate=planting duration:3s", -- Play a planting animation for 3 seconds.

The animate action will trigger a new animation, then wait for the specified duration before moving on to the next action in the program. The animation will continue playing and loop around until the program ends or another animate= action is called. The given duration does not have to equal the length of the animation.

When the program ends, the map object will switch back to the default idle animation. Some actions also have an animation associated with them that will be played instead, e.g. "walk=coords" will play the walking animation for the direction the worker is walking in.


playsound=\<sound_dir/sound_name\> priority:<\percent\> \[allow_multiple\]
  • sound_dir/sound_name (string) – The directory (folder) that the sound files are in, relative to the data directory, followed by the name of the particular sound to play. There can be multiple sound files to select from at random, e.g. for sound/farm/scythe, we can have sound/farm/scythe_00.ogg, sound/farm/scythe_01.ogg

  • priority (percent) – The priority to give this sound, in Percent. Maximum priority is 100%.

  • allow_multiple – When this parameter is given, the sound can be played by different map objects at the same time.

Trigger a sound effect. Whether the sound effect is actually played is determined by the sound handler.


 -- Worker
 harvest = {
    "findobject=attrib:ripe_wheat radius:2",
    -- Almost certainly play a swishy harvesting sound
    "playsound=sound/farm/scythe priority:95%",
    "animate=harvesting duration:10s",
    "animate=gathering duration:4s",

 -- Production site
produce_ax = {
    -- TRANSLATORS: Completed/Skipped/Did not start forging an ax because ...
    descname = _("forging an ax"),
    actions = {
       "return=skipped unless economy needs ax",
       "consume=coal iron",
       -- Play a banging sound 50% of the time.
       -- Other buildings can also play this sound at the same time.
       "playsound=sound/smiths/smith priority:50% allow_multiple",
       "animate=working duration:22s",
       -- Play a sharpening sound 50% of the time,
       -- but not if another building is already playing it right now.
       "playsound=sound/smiths/sharpening priority:90%",