Skip to content

Pathfinder ‐ Module Properties

Andrew Clements edited this page Dec 23, 2024 · 1 revision

Module Properties

Module properties are various attributes that modules may have which can influence or alter the shortest path. A simple example of a property is color; if you assign modules different colors and the final state requires that modules of certain colors be in specific positions, then the program will find the shortest path that meets these new requirements. Properties also allow for the usage of move subroutines, which are series of functions to be called upon move execution or during move checks. Move subroutines allow for properties to be taken into consideration when determining if a move is possible, and also make it possible to modify a module's properties throughout the search based on the moves performed.

Usage - Initial and Desired property definitions

A module's properties are set in the initial state file like so:

"modules": [
  {
    "position": [1, 1],
    "static": false,
    "properties": {
      "colorProperty": {
        "color": "blue"
      }
    }
  }
]

This constructs the property associated with the identifier "colorProperty" using the provided JSON object:

{
  "color": "blue"
}

This process also allows setting the desired values for properties in the final state definition.

Usage - Move Subroutines

Move subroutines are divided into two classes of subroutine: Checks and updates.

Check subroutines are executed during a move check, and consist of calls to functions which all return boolean values. If any of these functions returns false, then the move check is considered to have failed. This allows for moves to have additional restrictions placed on them beyond the single-backbone condition and the free-space requirements.

Update subroutines are executed in-between a successful move check and a move occurring, and typically consist of calls to functions which alter the properties of the moving module or nearby modules. Update subroutines are intended to be used for adjusting module properties as the modules move, but could also be used to for example move multiple modules or alter the distance covered by a move.

Important Note: Update subroutines have a nasty tendency to break heuristic admissibility, and as such when using a move that performs these updates it is probably best to use bi-directional breadth-first search instead of A*.

Example

{
  "moves": [
    {
      "name": "Corner Slide (Blue to Red around Green)",
      "order": 2,
      "def": [[
        "?x",
        "#!"
      ]],
      "propertyChecks": [
        {
          "module": [0, 0],
          "property": "colorProperty",
          "function": "IsColor",
          "args": [255]
        },
        {
          "module": [0, 1],
          "property": "colorProperty",
          "function": "IsColor",
          "args": [65280]
        }
      ],
      "propertyUpdates": [
        {
          "module": [0, 0],
          "property": "colorProperty",
          "function": "SetColor",
          "args": [16711680]
        }
      ],
      "permGen": true,
      "animSeq": [
        ["x-slide", [1, 1, 0]]
      ]
    }
  ]
}

This example includes both a check move subroutine and an update move subroutine. The check subroutine calls two functions to ensure that the module at offset [0, 0] (Relative to the moving module ?) is blue, and that the module at offset [0, 1] (Keeping in mind that positive y is downwards) is green. The update subroutine calls a function which adjusts the module at offset [0, 0] to be red.

Implementation Details

A module property consists of a specification JSON file (.json) and an implementation shared object file (.so, .dll, or .lib). The specification file tells Pathfinder which shared library to link at runtime, and the names of various functions within the library. Property constructors take a JSON object as input and produce a property. The JSON values used to construct properties are specified in the initial and desired state JSON files, on a per-module basis. Move definitions can include move subroutines, which tell the program which functions to call when executing a move using the names provided in the specification.