Custom level creation/test.si

From Turing Complete
wip
wip

This page descibes the early access verion 2.1.197 alpha. It may not be completely correct for the the current stable version, nor the latest unstable version. Help us update it, and you get a cookie.

Each level folder contains a test.si file which has all the code for verifying level solutions. Written in Simplex.

A list of functions that can be used in test.si.

Functions[edit | edit source]

Component & Sequential[edit | edit source]

User defined functions for Component & Sequential type levels.

  • check_output(tick: Int, inputs: Input, outputs: Output) TestResult
  • get_input(tick: Int) Input
  • on_ui_update(input: Input, output: Output)
    • Optional: Called every time the UI is updated, approx 30 times a second while the sim is running.

Architecture[edit | edit source]

User defined functions for Architecture type levels.

  • arch_check_output(test: Int, input: Int, output: Int) TestResult
  • arch_get_input(test: Int) Int
  • on_manual_input(input: Int)
    • Optional: Hook provided for handling keyboard input while simulation is not running. See NIM or Tower of Hanoi for an example.
  • on_ui_update(input: Input, output: Output)
    • Optional: Called every time the UI is updated, approx 30 times a second while the sim is running.

Callable[edit | edit source]

The test framework defines these function which may be used in test.si for any type of level.

  • add_keyboard_value(key_down: Bool, value: U8)
    • Push a new keyboard event onto the keyboard event queue.
  • get_component_count() Int
    • Number of components, includes level IO pins.
  • get_component_count(component_type: ComponentType) Int
    • Number of a specific type of component.
  • get_delay_score() Int
  • get_gate_score() Int
  • get_last_time() Int
  • get_ram_value(label: String, address: Int, size: @Size) @Size
  • get_memory(label: String) Int
  • get_test() Int
  • get_tick() Int
  • set_error(input: String)
    • Displays a yellow error message, indicating the reason for the test failure
  • set_ram_value(label: String, offset: Int, value: @Type)
  • ui_set_address_color(id: String, value: Int)
  • ui_set_color(id: String, value: Int)
  • ui_set_column_header_color(id: String, value: Int)
  • ui_set_column_header_size(id: String, value: Int)
  • ui_set_description_color(id: String, value: Int)
  • ui_set_hidden(id: String, value: Bool)
  • ui_set_image_name(id: String, text: String
  • ui_set_instruction(index: Int, code: Int, pointer: Int)
  • ui_set_instruction_color(id: String, value: Int)
  • ui_set_position(id: String, x: Int, y: Int)
  • ui_set_row_header_color(id: String, value: Int)
  • ui_set_row_header_size(id: String, value: Int)
  • ui_set_size(id: String, size: Int)
  • ui_set_text(id: String, text: String
  • ui_set_width(id: String, value: Int)

Internal[edit | edit source]

These are used internally to communicate between the backend and frontend, they are not relevant for level creation.

  • get_command(idx: CommandIndex) U64
  • get_setting(idx: CommandIndex) U64
  • set_setting(idx: StateIndex, value: U64)

These are generated by the code generation code based on the circuit and implement the actual logic gates. You don't want to call these manually (nor do you want to define a conflicting function, which is why these are listed here):

  • reset_sim()
  • mode_refresh()
  • mode_run(target_tick: Int)

There are also various global and local variables. These should not be accessed directly; If access is desirable, they are exposed via one of the functions above

Types[edit | edit source]

TestResult[edit | edit source]

Returned by

  • check_output()
  • arch_check_output()

Possible values:

  • pass (the default): This test/tick is OK, proceed to the next test/tick.
  • fail: The circuit has failed validation.
  • win: The final test has passed, and the level is complete. This marks the win condition.

Input[edit | edit source]

Returned by get_input() and arch_get_input(), and passed into check_output(), arch_check_output(), and on_ui_update().

Should be a type with a field for each input pin, the type should be an unsigned integer with the same width as the pin.

The field names must be based on the pin label with the case folded to lower case and any non alphanumeric characters replaced with an underscore.

For example the byte_adder level has three input pins A, B, and Carry in with widths 8, 8, 1 respectively.

type Input {
    a:        U8,
    b:        U8,
    carry_in: U1
}

Output[edit | edit source]

Passed into check_output(), arch_check_output(), and on_ui_update().

This type as 2 fields for each output pin in the level. One field is based on the the pin label and holds the current output value. The other has the same name but with _is_z appended. Its value is true if and only if the output is currently disconnected or .

The field names must be based on the pin label with the case folded to lower case and any non alphanumeric characters replaced with an underscore.

For example the level byte_adder has two outputs, called Output and Carry out, with widths 8 and 1.

type Output {
    output:         U8,
    output_is_z:    Bool,
    carry_out:      U1,
    carry_out_is_z: Bool
}

ComponentType[edit | edit source]

Passed into get_component_count()

Possible values are the internal component names, of the form com_*. See the most recent kaitai structure definition for a full list.

Initialization[edit | edit source]

Any code outside a function will be run at every reset and can be used to initialize any state.