Popover Menu get started
Popover Menu Tools
client discord
Menu
supported games setup guides f.a.q. generate game host game user content clients discord
Starcraft 2 Guide

Custom Mission Orders for Starcraft 2

Table of Contents

What is this?

This is usage documentation for the custom_mission_order YAML option for Starcraft 2. You can enable Custom Mission Orders by setting mission_order: custom in your YAML.

You will need to know how to write a YAML before engaging with this feature, and should read the Archipelago YAML documentation before continuing here.

Every example in this document should be valid to generate.

Basic structure

Custom Mission Orders consist of three kinds of structures:

As a note, layouts are also called questlines in the UI. Layouts and questlines refer to the same thing, though this document will only use layouts.

To illustrate, the following is what the default custom mission order currently looks like. If you're not sure what some options mean, they will be explained in more depth later.

  custom_mission_order:
    # This is a campaign, defined by its name
    Default Campaign:
      # The campaign's name as displayed in the client
      display_name: "null"
      # Whether this campaign must have a unique name in the client
      unique_name: false
      # Conditions that must be fulfilled to access this campaign
      entry_rules: []
      # Whether beating this campaign is part of the world's goal
      goal: true
      # The lowest difficulty of missions in this campaign
      min_difficulty: relative
      # The highest difficulty of missions in this campaign
      max_difficulty: relative
      # This is a special layout that defines defaults
      # for other layouts in the campaign
      global:
        # The layout's name as displayed in the client
        display_name: "null"
        # Whether this layout must have a unique name in the client
        unique_name: false
        # Whether beating this layout is part of the world's goal
        goal: false
        # Whether this layout must be beaten to beat the campaign
        exit: false
        # Conditions that must be fulfilled to access this layout
        entry_rules: []
        # Which missions are allowed to appear in this layout
        mission_pool:
          - all missions
        # The lowest difficulty of missions in this layout
        min_difficulty: relative
        # The highest difficulty of missions in this layout
        max_difficulty: relative
        # Used for overwriting default options of mission slots,
        # which are set by the layout type (see Default Layout)
        missions: []
      # This is a regular layout, defined by its name
      Default Layout:
        # This defines how missions in the layout are organized,
        # as well as how they connect to one another
        type: grid
        # How many total missions should appear in this layout
        size: 9

This default option also defines default values (though you won't get the Default Campaign and Default Layout), so you can omit the options you don't want to change in your own YAML.

Notably however, layouts are required to have both a type and a size, but neither have defaults. You must define both of them for every layout, either through your own global layout, or in the options of every individual layout.

If you want multiple campaigns or layouts, it would look like this:

  custom_mission_order:
    My first campaign!:
        # Campaign options here
        global: # Can be omitted if the above defaults work for you
          # Makes all the other layouts only have Terran missions
          mission_pool:
            - terran missions
          # Other layout options here
        My first layout:
          # Defining at least type and size of a layout is mandatory
          type: column
          size: 3
          # Other layout options here
        my second layout:
          type: grid
          size: 4
        layout number 3:
          type: column
          size: 3
        # etc.
    Second campaign:
      the other first layout:
        type: grid
        size: 10
    # etc.

If you don't want to have a campaign container for your layouts, you can also forego the campaign layer like this:

  custom_mission_order:
    Example campaign-level layout:
      # Make sure to always declare these two, like with regular layouts
      type: column
      size: 3
    
    # Regular campaigns and campaign-less layouts
    # can be mixed however you want
    Some Campaign:
      Some Layout:
        type: column
        size: 3

It is also possible to access mission slots by their index, which is defined by the type of the layout they are in. The below shows an example of how to access a mission slot, as well as the defaults for their options.

However, keep in mind that layout types will set their own options for specific slots, overwriting the below defaults, and using this option in turn overwrites the values set by layout types. As before, the options are explained in more depth later.

  custom_mission_order:
    My Campaign:
      My Layout:
        type: column
        size: 5
        missions:
          # 0 is often the layout's starting mission
          # Any index between 0 and (size - 1) is accessible
          - index: 0
            # Whether this mission is part of the world's goal
            goal: false
            # Whether this mission is accessible as soon as the
            # layout is accessible
            entrance: false
            # Whether this mission is required to beat the layout
            exit: false
            # Whether this slot contains a mission at all
            empty: false
            # Conditions that must be fulfilled to access this mission
            entry_rules: []
            # Which missions in the layout are unlocked by this mission
            # This is normally set by the layout's type
            next: []
            # Which missions are allowed to appear in this slot
            # If not defined, the slot inherits the layout's pool
            mission_pool:
              - all missions
            # Which specific difficulty this mission should have
            difficulty: relative

Interactions with other YAML options

Custom Mission Orders respect all the options that change which missions can appear as if the options' relevant missions had been excluded. For example, selected_races: protoss is equivalent to excluding all Zerg and Terran missions, and enabled_campaigns: ["Wings of Liberty"] is equivalent to excluding all but WoL missions.

This means that if you want total control over available missions in your mission order via mission_pools, you should enable all races and campaigns and leave your excluded_missions list empty, but you can also use these options to get rid of particular missions you never want and can then ignore those missions in your mission_pools.

There are, however, several options that are ignored by Custom Mission Orders:

Instructions for building a mission order

Normally when you play a Starcraft 2 world, you have a table of missions in the Archipelago SC2 Client, and hovering over a mission tells you what missions are required to access it. This is still true for custom mission orders, but you now have control over the way missions are visually organized, as well as their access requirements.

This section is meant to offer some guidance when making your own mission order for the first time.

To begin making your own mission order, think about how you visually want your missions laid out. This should inform the layout types you want to use, and give you some idea about the overall structure of your mission order.

For example, if you want to make a custom campaign like the vanilla ones, you will want a lot of layouts of type: column. If you want a Hopscotch layout with certain missions or races, a single layout with type: hopscotch will suffice. If you want to play through a funny shape, you will want to draw with a type: canvas. If you just want to make a minor change to a vanilla campaign, you will want to start with a preset campaign.

The natural flow of a mission order is defined by the types of its layouts. It makes sense for a mission to unlock its neighbors, it makes sense for a Hopscotch layout to wrap around the sides, and it makes sense for a Column's final mission to be at the bottom. Layout types create their flow by setting next, entrance, exit, and entry_rules on missions. More on these in a little bit.

Layout types dictate their own visual structure, and will only rarely make mission slots with empty: true. If you want a certain shape that's not exactly like an existing type, you can pick a type with more slots than you want and remove the extras by setting empty: true on them.

With the basic setup in place, you should decide on what the goal of your mission order is. By default every campaign has goal: true, meaning all campaigns must be beaten to complete the world. You can additionally set goal: true on layouts and mission slots to require them to be beaten as well. If you set goal: false on everything, the mission order will default to setting the last campaign (lowest in your YAML) as the goal.

After deciding on a goal, you can complicate your way towards it. At the start of a world, the only accessible missions in the mission order are all the missions marked entrance: true. When you beat one of these missions, it unlocks all the missions in the beaten mission's next list. This process repeats until all the missions are accessible.

If this behavior isn't enough for your planned mission order, you can interrupt the natural flow of layout types using entry_rules in combination with exit.

When this document refers to "beating" something, it means the following:

Note victory checks may be claimed by someone else running !collect in a multiworld and receiving an item on a victory check. Collecting victory cache checks do not count, only victory checks.

Layouts will have their default exit missions set by the layout type. If you don't want to use this default, you will have to manually set exit: false on the default exits. Campaigns default to using the last layout in them (the lowest in your YAML) as their exit, but only if you don't manually set exit: true on a layout.

Using entry_rules, you can make a mission require beating things other than those missions whose next points to it, and you can make layouts and campaigns not available from the start.

Note that entry_rules are an addition to the next behavior. If you want a mission to completely ignore the natural flow and only use your entry_rules, simply set entrance: true on it.

Please see the entry_rules section below for available rules and examples.

With your playthrough sufficiently complicated, it only remains to add flavor to your mission order by changing mission_pool and difficulty options as you like them. These options are also explained below.

To summarize:

Shared options

These are the options that are shared between at least two of campaigns, layouts and missions. All the options below are listed with their defaults.


Display Name

# For campaigns and layouts
display_name: "null"

As shown in the examples, every campaign and layout is defined with a name in your YAML. This name is used to find campaigns and layouts within the mission order (see entry_rules section), and by default (meaning with display_name: "null") it is also shown in the client.

This option changes the name shown in the client without affecting the definition name.

There are two special use cases for this option:

# This means the campaign or layout
# will not have a title in the client
display_name: ""
# This will randomly pick a name from the given list of options
display_name:
  - My First Choice
  - My Second Choice
  - My Third Choice

Unique name

# For campaigns and layouts
unique_name: false

This option prevents names from showing up multiple times in the client. It is recommended to be used in combination with lists of display_names to prevent the generator from picking duplicate names.


Goal

# For campaigns
goal: true
# For layouts and missions
goal: false

This determines whether the campaign, layout or mission is required to beat the world. If you turn this off for everything, the last defined campaign (meaning the lowest one in your YAML) is chosen by default.


Exit

# For layouts and missions
exit: false

This determines whether beating the mission is required to beat its parent layout, and whether beating the layout is required to beat its parent campaign.


Entry rules

# For campaigns, layouts, and missions
entry_rules: []

This defines access restrictions for parts of the mission order.

These are the available rules:

entry_rules:
  # Beat these things ("Beat rule")
  - scope: []
  # Beat X amount of missions from these things ("Count rule")
  - scope: []
    amount: -1
  # Find these items ("Item rule")
  - items: {}
  # Fulfill X amount of other conditions ("Subrule rule")
  - rules: []
    amount: -1

Note that Item rules take both a name and amount for each item (see the example below). In general this rule treats items like the locked_items option, including that it will override excluded_items, but as a notable difference all items required for Item rules are marked as progression. If multiple Item rules require the same item, the largest required amount will be locked, not the sum of all amounts.

Additionally, Item rules accept a special item:

entry_rules:
  - items:
      Key: 1

This is a generic item that is converted to a key item for the specific scope it is under. Missions get Mission Keys, layouts get Questline Keys, and campaigns get Campaign Keys. If you want to know which specific key is created (for example to tie multiple unlocks to the same key), you can generate a test game and check in the client.

You can also use one of the following key items for this purpose:

Custom keys
  • Terran Key
  • Zerg Key
  • Protoss Key
  • Raynor Key
  • Tychus Key
  • Swann Key
  • Stetmann Key
  • Hanson Key
  • Nova Key
  • Tosh Key
  • Valerian Key
  • Warfield Key
  • Mengsk Key
  • Han Key
  • Horner Key
  • Kerrigan Key
  • Zagara Key
  • Abathur Key
  • Yagdra Key
  • Kraith Key
  • Slivan Key
  • Zurvan Key
  • Brakk Key
  • Stukov Key
  • Dehaka Key
  • Niadra Key
  • Izsha Key
  • Artanis Key
  • Zeratul Key
  • Tassadar Key
  • Karax Key
  • Vorazun Key
  • Alarak Key
  • Fenix Key
  • Urun Key
  • Mohandar Key
  • Selendis Key
  • Rohana Key
  • Reigel Key
  • Davis Key
  • Ji'nara Key

These keys will never be used by the generator unless you specify them yourself.

There is also a special type of key:

entry_rules:
  - items:
      # These two forms are equivalent
      Progressive Key: 5
      Progressive Key 5: 1

Progressive keys come in two forms: Progressive Key: <track> and Progressive Key <track>: 1. In the latter form the item amount is ignored. Their track is used to group them, so all progressive keys with track 1 belong together, as do all with track 2, and so on. Item rules using progressive keys are sorted by how far into the mission order they appear and have their required amounts set automatically so that deeper rules require more keys, with each track of progressive keys performing its own sorting.

Note that if any Item rule within a track belongs to a mission, the generator will accept ties, in which case the affected rules will require the same number of progressive keys. If a track only contains Item rules belonging to layouts and campaigns, the track will be sorted in definition order (top to bottom in your YAML), so there will be no ties.

If you prefer not to manually specify the track, use the unique_progression_track option.

The Beat and Count rules both require a list of scopes. This list accepts addresses towards other parts of the mission order.

The basic form of an address is <Campaign>/<Layout>/<Mission>, where <Campaign> and <Layout> are the definition names (not display_names!) of a campaign and a layout within that campaign, and <Mission> is the index of a mission slot in that layout or an index function for the layout's type. See the section on your layout's type to find valid indices and functions.

If you don't want to point all the way down to a mission slot, you can omit the later parts. <Campaign> and <Campaign>/<Layout> are valid addresses, and will point to the entire specified campaign or layout.

Futhermore, you can generically refer to the parent of an object using .., so if you are creating entry rules for a given layout and want to point at a different <Layout> in the same <Campaign>, the following are identical:

You can also chain these, so for a given mission ../.. will point to its parent campaign.

Lastly, you can point to the whole mission order via <Campaign>/.. (or the equivalent number of ..s from a given layer), but this is only supported for Count rules and not Beat rules.

Note that if you have a campaign-less layout, you will not require a <Campaign> part to find it, and .. will skip the campaign layer.

Below are examples of the available entry rules:

  custom_mission_order:
    Some Missions:
      type: grid
      size: 9
      entry_rules:
        # Item rule:
        # To access the Some Missions layout,
        # you have to find or receive your Marine
        - items:
            Marine: 1
    
    Wings of Liberty:
      Mar Sara:
        type: column
        size: 3
      Artifact:
        type: column
        size: 3
        entry_rules:
          # Beat rule:
          # To access the Artifact layout,
          # you have to first beat Mar Sara
          - scope: ../Mar Sara
      Prophecy:
        type: column
        size: 3
        entry_rules:
          # Beat rule:
          # Beat the mission at index 1 in the Artifact layout
          - scope: ../Artifact/1
          # This is identical to the above
          # because this layout is already in Wings of Liberty
          - scope: Wings of Liberty/Artifact/1
      Covert:
        type: column
        size: 3
        entry_rules:
          # Count rule:
          # Beat any 7 missions from Wings of Liberty
          - scope: Wings of Liberty
            amount: 7
    
    Complicated Access:
      type: column
      size: 3
      entry_rules:
        # Subrule rule:
        # To access this layout,
        # fulfill any 1 of the nested rules
        # (See amount value at the bottom)
        - rules:
            # Nested Subrule rule:
            # Fulfill all of the nested rules
            # Amount can be at the top if you prefer
            - amount: -1 # -1 means "all of them"
              rules:
              # Count rule:
              # Beat any 5 missions from Wings of Liberty
              - scope: Wings of Liberty
                amount: 5
              # Count rule:
              # Beat any 5 missions from Some Missions
              - scope: Some Missions
                amount: 5
            # Count rule:
            # Beat any 10 combined missions from
            # Wings of Liberty or Some Missions
            - scope:
                - Wings of Liberty
                - Some Missions
              amount: 10
          amount: 1

As this last example shows, the Subrule rule is a powerful tool for making arbitrarily complex requirements. Put plainly, the example accomplishes the following: To unlock the Complicated Access layout, either beat 5 missions in both the Wings of Liberty campaign and the Some Missions layout, or beat 10 missions across both of them.


Unique progression track

# For campaigns and layouts
unique_progression_track: 0

This option specifically affects Item entry rules using progressive keys. Progressive keys used by children of this campaign/layout that are on the given track will automatically be put on a track that is unique to the container instead.

  custom_mission_order:
    First Column:
      type: column
      size: 3
      unique_progression_track: 0 # Default
      missions:
        - index: [1, 2]
          entry_rules:
          - items:
              Progressive Key: 0
    Second Column:
      type: column
      size: 3
      unique_progression_track: 0 # Default
      missions:
        - index: [1, 2]
          entry_rules:
          - items:
              Progressive Key: 0

In this example the two columns will use separate progressive keys for their missions.

In the case that a mission slot uses a progressive key whose track matches the unique_progression_track of both its containing layout and campaign, the key will use the layout's unique track and not the campaign's. To avoid this behavior simply use different unique_progression_track values for the layout and campaign.


Difficulty

# These two apply to campaigns and layouts
min_difficulty: relative
max_difficulty: relative
# This one applies to missions
difficulty: relative

Valid values are:

These determine the difficulty of missions within campaigns, layouts, or specific mission slots.

On relative, the difficulty of mission slots is dynamically scaled based on earliest possible access to that mission. By default, this scales the entire mission order to go from Starter missions at the start to Very Hard missions at the end.

Campaigns can override these limits, layouts can likewise override the limits set by their campaigns, and missions can simply define their desired difficulty.

In every case, if a mission's mission pool does not contain missions of an appropriate difficulty, it will attempt to find a mission of a nearby difficulty, preferring lower ones.

  custom_mission_order:
    Campaign:
      min_difficulty: easy
      max_difficulty: medium
      Layout 1:
        max_difficulty: hard
        type: column
        size: 3
      Layout 2:
        type: column
        size: 3
        missions:
          - index: 0
            difficulty: starter

In this example, Campaign is restricted to missions between Easy and Medium. Layout 1 overrides Medium to be Hard instead, so its 3 missions will go from Easy to Hard. Layout 2 keeps the campaign's limits, but its first mission is set to Starter. In this case, the first mission will be a Starter mission, but the other two missions will scale towards Medium as if the first had been an Easy one.


Mission Pool

# For layouts and missions
mission_pool:
  - all missions

Valid values are names of specific missions and names of mission groups. Group names can be looked up here: APSC2 Mission Groups

If a mission defines this, it ignores the pool of its containing layout. To define a pool for a full campaign, define it in the global layout.

This is a list of instructions for constructing a mission pool, executed from top to bottom, so the order of values is important.

There are three available instructions:

As a reminder, <Group Name> can also be the name of a specific mission.

The first instruction in a pool must always be an addition.

  custom_mission_order:
    Campaign:
      global:
        type: column
        size: 3
        mission_pool:
          - terran missions
          - ~ no-build missions
      Layout A-1:
        mission_pool:
          - zerg missions
          - ^ kerrigan missions
          - + Lab Rat
      Layout A-2:
        missions:
          - index: 0
            mission_pool:
              - For Aiur!
              - Liberation Day

The following pools are constructed in this example:

Campaign Options

These options can only be used in campaigns.


Preset

preset: none

This option loads a pre-built campaign into your mission order. Presets may accept additional options in addition to regular campaign options.

With all presets, you can override their layout options by defining the layouts like normal in your YAML.

  custom_mission_order:
    My Campaign:
      preset: wol + prophecy
      missions: random # Optional
      shuffle_raceswaps: false # Optional
      keys: none # Optional
      Prophecy:
        mission_pool:
          - zerg missions

This example loads the Wol + Prophecy preset and then changes Prophecy's missions to be Zerg instead of Protoss.

See the following section for available presets.

Campaign Presets

There are two kinds of presets: Static presets that are based on vanilla campaigns, and scripted presets that dynamically create a complex campaign based on extra required options.


Static Presets

Available static presets are the following:

For these presets, the layout names used to override settings match the names shown in the client, with some exceptions:

Preset Options

All static presets accept these options, as shown in the example above:

Missions

The missions option accepts these possible values:

Shuffle Raceswaps

The shuffle_raceswaps option accepts true and false (default). If enabled, the missions pools in the preset will contain raceswapped missions. This means missions: vanilla_shuffled will shuffle raceswaps alongside their regular variants, and missions: vanilla will allow a random variant of the mission in each slot. This option does nothing if missions is set to random.

Keys

The keys option accepts these possible values:


Golden Path

preset: golden path
size: # Required, no default, accepts positive numbers
two_start_positions: false
keys: none # Optional

Golden Path aims to create a dynamically-sized campaign with branching paths to create a similar experience to the Wings of Liberty campaign. It accomplishes this by having a main column that requires an increasing number of missions to be beaten to advance, and a number of side columns that require progressing the main column to advance. The exit of a Golden Path campaign is the last mission of the main column.

The size option defines the number of missions in the campaign.

If two_start_positions, the first mission will be skipped, and the first two branches will be available from the start instead.

The columns in a Golden Path get random names from a display_name list and have unique_name: true set on them. Their definition names for overriding options are "0", "1", "2", etc., with "0" always being the main column, "1" being the left-most side column, and so on.

Since the number of side columns depends on the number of missions, it is best to generate a test game for a given size to see how many columns are generated.

Golden Path also accepts a keys option, which works like the same option for static presets, and accepts the following values:

Layout Options

Layouts may have special options depending on their type. These are covered in the section on Layout Types. Below are the options that apply to every layout.


Type

type: # There is no default

Determines how missions are placed relative to one another within a layout, as well as how they connect to each other.

Currently, valid values are:

Details about specific layout types are covered at the end of this document.


Size

size: # There is no default

Determines how many missions a layout contains. Valid values are positive numbers.

Missions

missions: []

This is used to access mission slots and overwrite the options that the layout type set for them. Valid options for mission slots are covered below, but the index option used to find mission slots is explained here.

Note that this list is evaluated from top to bottom, meaning if you perform conflicting changes on the same mission slot, the last defined operation (lowest in your YAML) will be the one that takes effect.

The following example shows ways to access and modify missions:

  custom_mission_order:
    My Example:
      type: grid
      size: 4
      missions:
        # Indices can be a numerical value
        # This sets the mission at index 1 to be an exit
        - index: 1
          exit: true
        # Indices can be special index functions
        # Valid functions are 'exits', 'entrances', and 'all'
        # These are available for all types of layouts
        # This takes all exits, including the one set above,
        # and turns them into non-exits
        - index: exits
          exit: false
        # Indices can be index functions
        # Available functions depend on the layout's type
        # In this case the function will return the indices 1 and 3
        # and then mark those two slots as empty
        - index: rect(1, 0, 1, 2)
          empty: true
        # Indices can be a list of valid values
        # This takes all entrances as well as the mission at index 2
        # and marks all of them as both entrances and exits
        - index:
            - entrances
            - 2
          entrance: true
          exit: true

The result of this example will be a grid where the two missions on the right are empty, and the two missions on the left are both entrances and exits.

Mission Slot Options

For all options in mission slots, the layout type containing the mission slot choses the defaults, and any values you define override the type's defaults.


Entrance

entrance: false

Determines whether this mission is an entrance for its containing layout. An entrance mission becomes available its parent layout's and campaign's entry_rules are fulfilled, but may further be restricted by its own entry_rules.

If for any reason a mission cannot be unlocked by beating other missions, meaning that there is no mission whose next points at this mission, then this missions will be automatically marked as entrances. However, this cannot detect circular dependencies, for example if you cut off a section of a grid, so make sure to manually set entrances as appropriate in those cases.


Empty

empty: false

Determines whether this mission slot contains a mission at all. If set to true, the slot is empty and will show up as a blank space in the client.

Layout types have their own means of creating blank spaces in the client, and so rarely use this option. If you want complete control over a layout's slots, use a layout of type: grid.


Next

next: []

Valid values are indices of other missions within the same layout and index functions for the layout's type. Note that this does not accept addresses.

This is the mechanism layout types use to establish mission flow. Overriding this will break the intended order of missions within a type. If you wish to add on to the type's flow rather than replace it, you must manually include the indices intended by the type.

Mechanically, a mission is unlocked when any other mission that contains the former in its next list is beaten. If a mission is not present in any other mission's next list, it is automatically marked as an entrance.

  custom_mission_order:
    Wings of Liberty:
      Char:
        type: column
        size: 4
        missions:
          - index: 0
            next:
              - 1
              - 2
          - index: 1
            next:
              - 3
          # The below two are default for a column
          # and could be removed from this list
          - index: 2
            next:
              - 3
          - index: 3
            next: []

This example creates the branching path within Char in the Vanilla mission order.


Victory Cache

victory_cache: 0

Valid values are integers in the range 0 to 10. Sets the number of extra locations given for victory on a mission.

By default, when this value is not set, the option is set to 0 for goal missions and to the global victory_cache option for all other missions.

Layout Types

The below types are listed with their custom options and their defaults.


Column

type: column

This is a linear order going from top to bottom.

A size: 5 column has the following indices:

0 # This is the default entrance
1
2
3
4 # This is the default exit (size - 1)

Grid

type: grid
width: 0 # Accepts positive numbers
two_start_positions: false # Accepts true/false

This is a rectangular order. Beating a mission unlocks adjacent missions in cardinal directions.

width sets the width of the grid, and height is determined via size and width. If width is set to 0, the width and height are determined automatically.

If two_start_positions, the top left corner will be set to empty: true, and its two neighbors will be entrances instead.

If size is too small for the determined width and height, then slots in the bottom left and top right corners will be removed to fit the given size. These empty slots are still accessible by index.

A size: 25, width: 5 grid has the following indices:

 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

The top left corner (index 0) is the default entrance. The bottom right corner (index size - 1) is the default exit.

Grid Index Functions

Grid supports the following index functions:

point(x, y)

point(x, y) returns the index at the given zero-based X and Y coordinates. In the above example, point(2, 4) is index 22.

rect(x, y, width, height)

rect(x, y, width, height) returns the indices within the rectangle defined by the starting point at the X and Y coordinates and the width and height arguments. In the above example, rect(1, 2, 3, 2) returns the indices 11, 12, 13, 16, 17, 18.


Canvas

type: canvas
canvas: # No default
jump_distance_orthogonal: 1 # Accepts numbers >= 1
jump_distance_diagonal: 1 # Accepts numbers >= 0

This is a special type of grid that is created from a drawn canvas. For this type of layout canvas is required and size is ignored if specified.

canvas is a list of strings that form a rectangular grid, from which the layout's size is determined automatically. Every space in the canvas creates an empty slot, while every character that is not a space creates a filled mission slot. The resulting grid determines its indices like Grid.

type: canvas
canvas:
- '     ggg     ' # 0
- '    ggggg    ' # 1
- '    ggggg    ' # 2
- ' bbb ggg rrr ' # 3
- 'bbbbb g rrrrr' # 4
- 'bbbbb   rrrrr' # 5
- ' ggg     bbb ' # 6
- 'ggggg   bbbbb' # 7
- 'gggg     bbbb' # 8
- 'ggg  rrr  bbb' # 9
- ' gg rrrrr bb ' # 10
- '    rrrrr    ' # 11
- '    rrrrr    ' # 12
- '     rrr     ' # 13
jump_distance_orthogonal: 2
jump_distance_diagonal: 1
missions:
- index: group(g)
  mission_pool: Terran Missions
- index: group(b)
  mission_pool: Protoss Missions
- index: group(r)
  mission_pool: Zerg Missions

This example draws the Archipelago logo using missions of different races as its colors. Note that while this example fits into 13 lines, there is no set limit for how many lines you may use, and likewise lines may be as long as you need them to be. Short lines are padded with spaces to match the longest line in the canvas, so lines are left-aligned in this case.

You may have noticed that the above example has gaps between missions. Canvas layouts support jumping over gaps via jump_distance_orthogonal and jump_distance_diagonal, which determine the maximum distance over which two missions may be connected, in orthogonal and diagonal directions respectively. Missions at higher distances will only connect if there is no other mission in front of them.

type: canvas
canvas:
- 'A  A'
- 'B XB'
jump_distance_orthogonal: 3
jump_distance_diagonal: 0

In this example the two As will connect because they are less than 3 missions apart, but the two Bs will not connect because X is between them, and both Bs will connect to X instead. Both sets of ABs will also connect because they are neighbors.

Diagonal jumps function identically, with one exception:

type: canvas
canvas:
- 'A  '
- ' B '
- ' XC'
jump_distance_orthogonal: 1
jump_distance_diagonal: 1

Missions that are diagonal neighbors only connect if they do not already share an orthogonal neighbor. In this example A and B connect, but B and C don't because X already connects them. No such restriction exists for higher-distance diagonal jumps, so it is recommended to keep jump_distance_diagonal low.

Finally, the default entrance and exit on a canvas are dynamically set to be the non-empty slots that are closest to the top left and bottom right corner respectively, but only if you don't set any entrances or exits yourself. It is highly recommended to set your own entrance and exit.

Canvas Index Functions

Canvas supports all of Grid's index functions, as well as the following:

group(character)

group(character) returns the indices which match the given character on the canvas. In the Archipelago logo example, group(g) gives the indices of all the gs on the canvas. Note that there is no group for spaces, so group(" ") does not work.


Hopscotch

type: hopscotch
width: 7 # Accepts numbers >= 4
spacer: 2 # Accepts numbers >= 1
two_start_positions: false # Accepts true/false

This order alternates between one and two missions becoming available at a time.

width determines how many mini columns are allowed to be next to one another before they wrap around the sides. spacer determines the amount of empty slots between diagonals in the client.

If two_start_positions, the top left corner will be set to empty: true, and its two neighbors will be entrances instead.

A size: 23, width: 4, spacer: 1 Hopscotch layout has the following indices:

 0  2
 1  3  5
    4  6  8
11     7  9
12 14    10
13 15 17
   16 18 20
      19 21
         22

The top left corner (index 0) is the default entrance. The bottom-most mission of the lowest column (index size - 1) is the default exit.

Hopscotch Index Functions

Hopscotch supports the following index functions:

top

top() (or top) returns the indices of all the top-right corners. In the above example, it returns the indices 2, 5, 8, 11, 14, 17, 20.

bottom

bottom() (or bottom) returns the indices of all the bottom-left corners. In the above example, it returns the indices 1, 4, 7, 10, 13, 16, 19, 22.

middle

middle() (or middle) returns the indices of all the middle slots. In the above example, it returns the indices 0, 3, 6, 9, 12, 15, 18, 21.

corner(index)

corner(index) returns the indices within the given corner. A corner is a slot in the middle and the slots to the bottom and right of it. corner(0) would return 0, 1, 2, corner(1) would return 3, 4, 5, and so on. In the above example, corner(7) will only return 21, 22 because it does not have a right mission.


Gauntlet

type: gauntlet
width: 7 # Accepts positive numbers

This type works the same way as column, but it goes horizontally instead of vertically.

width is the maximum allowed missions on a row before it wraps around into a new row.

A size: 21, width: 7 gauntlet has the following indices:

 0  1  2  3  4  5  6

 7  8  9 10 11 12 13

14 15 16 17 18 19 20

The left-most mission on the top row (index 0) is the default entrance. The right-most mission on the bottom row (index size - 1) is the default exit.


Blitz

type: blitz
width: 0 # Accepts positive numbers

This type features rows of missions, where beating a mission in a row unlocks the entire next row.

width determines how many missions there are in a row. If set to 0, the width is determined automatically based on the total number of missions (the layout's size), but limited to be between 2 and 5.

A size: 20, width: 5 Blitz layout has the following indices:

 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19

The top left corner (index 0) is the default entrance. The right-most mission on the bottom row (index size - 1) is the default exit.

Blitz Index Functions

Blitz supports the following index function:

row(height)

row(height) returns the indices of the row at the given zero-based height. In the above example, row(1) would return 5, 6, 7, 8, 9.