0: Initial.

[?]
Aaw9nJhsNmfzFih9mKyNw9mV8CgERXJkRa1kK1Kx3LQH
Dec 20, 2021, 12:58 PM
6ZZOMSZRHZ67J5N64GYR4GO7JG3O45EJBRRNRDJS3T533VPVRCAAC

Dependencies

Change contents

  • add root
    [1.1]
    [0.1]
  • file addition: test.sprak (----------)
    [0.2]
    #############
    # Functions #
    #############
    void run_tests(string name, array tests)
    number count = 0
    loop test in tests
    if !equal(test[0], test[1])
    Print(name + " " + count + ": fail")
    Print("left: " + test[0])
    Print("right: " + test[1])
    end
    count += 1
    end
    Print(name + " tests done.")
    end
  • file addition: test.md (----------)
    [0.2]
    # test.sprak
    Library for testing functions/programs.
    ## Usage
    * TODO.
    ## Functions
    ### `run_tests`
    Runs unit tests that test for equality of outputs
    #### Type
    `string -> [[A, A]] -> void`
    #### Arguments
    * `name`: Name of the curent test.
    * `tests`: Array of output pairs to compare.
    #### Examples
    ```sprak
    # TODO
    ```
    #### Imports
    * equality.sprak
  • file addition: supply.sprak (----------)
    [0.2]
    ###############
    # serde.sprak #
    ###############
    string deserialise_string(string input)
    string output = ""
    bool escaped = false
    loop character in input
    if character != "\"
    if character != '"'
    output += character
    end
    else if escaped
    output += character
    escaped = false
    else if character == '\'
    escaped = true
    end
    end
    return output
    end
    bool is_digit(string input)
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    var deserialise_array(string input)
    array accumulator = []
    bool in_string = false
    bool escaped = false
    bool in_value = false
    string buffer = ""
    number key_type = 0
    bool key_bool = false
    number key_number = 0
    string key_string = ""
    number value_type = 0
    bool value_bool = false
    number value_number = 0
    string value_string = ""
    array contexts = []
    loop character in input
    bool is_numeric = false
    if character == ":"
    if !in_string
    in_value = true
    if key_type == 2
    key_number = buffer
    buffer = ""
    end
    else if in_value
    value_string += ":"
    else
    key_string += ":"
    end
    else if character == ","
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    in_value = false
    buffer = ""
    key_string = ""
    value_string = ""
    else if in_value
    value_string += ","
    else
    key_string += ","
    end
    else if is_digit(character)
    is_numeric = true
    else if character == "."
    is_numeric = true
    else if character == "-"
    is_numeric = true
    else if character == '"'
    if !in_string
    in_string = true
    if in_value
    value_type = 3
    else
    key_type = 3
    end
    else if !escaped
    in_string = false
    else if in_value
    value_string += '"'
    else
    key_string += '"'
    end
    else if character == "t"
    if !in_string
    if in_value
    value_bool = true
    value_type = 1
    else
    key_bool = true
    key_type = 1
    end
    else if in_value
    value_string += "t"
    else
    key_string += "t"
    end
    else if character == "f"
    if !in_string
    if in_value
    value_bool = false
    value_type = 1
    else
    key_bool = false
    key_type = 1
    end
    else if in_value
    value_string += "f"
    else
    key_string += "f"
    end
    else if character == "{"
    if !in_string
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    else
    value_string += "{"
    end
    else if character == "}"
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    array last_context = contexts[Count(contexts) - 1]
    array last_accumulator = last_context[0]
    number last_key_type = last_context[1]
    if last_key_type != 0
    last_accumulator[last_context[2]] = accumulator
    else
    return accumulator
    end
    accumulator = last_accumulator
    value_type = 4
    Remove(contexts, Count(contexts) - 1)
    else
    value_string += "}"
    end
    else if character == "\"
    if !escaped
    escaped = true
    else
    escaped = false
    if in_value
    value_string += "\"
    else
    key_string += "\"
    end
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    if is_numeric
    if !in_string
    buffer += character
    if in_value
    value_type = 2
    else
    key_type = 2
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    end
    end
    end
    var deserialise(string input)
    if input[0] == "{"
    return deserialise_array(input)
    else if is_digit(input[0])
    number output = input
    return output
    else if input[0] == "-"
    number output = input
    return output
    else if input[0] == '"'
    return deserialise_string(input)
    else if input == "t"
    return true
    else if input == "f"
    return false
    end
    end
    ##################
    # equality.sprak #
    ##################
    bool equal_array(array first, array second)
    if Count(first) == Count(second)
    if "" + first == "" + second
    loop key in GetIndexes(first)
    if !HasIndex(second, key)
    return false
    else if !equal(first[key], second[key])
    return false
    end
    end
    return true
    end
    end
    return false
    end
    bool equal(var first, var second)
    string type_first = Type(first)
    if type_first == Type(second)
    if type_first != "array"
    return first == second
    end
    return equal_array(first, second)
    end
    return false
    end
    ###############
    # array.sprak #
    ###############
    bool has(var test_element, array input)
    loop element in input
    if equal(element, test_element)
    return true
    end
    end
    return false
    end
    #############
    # Functions #
    #############
    array supply(array overrides, string function)
    string MemoryAPI_thing = "FinanceComputer"
    string TingrunnerAPI_thing = "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1"
    string name = Name()
    if HasIndex(overrides, "MemoryAPI")
    MemoryAPI_thing = overrides["MemoryAPI"]
    end
    if HasIndex(overrides, "TingrunnerAPI")
    TingrunnerAPI_thing = overrides["TingrunnerAPI"]
    end
    var MemoryAPI
    if MemoryAPI_thing != name
    MemoryAPI = Connect(MemoryAPI_thing)
    else
    return [false, "MemoryAPI unavailable."]
    end
    var TingrunnerAPI
    if TingrunnerAPI_thing != name
    TingrunnerAPI = Connect(TingrunnerAPI_thing)
    else
    return [false, "TingrunnerAPI unavailable."]
    end
    array skip_types = ["floppy", "navnode", "bed", "point", "seat", "locker", "memory", "portal", "character", "map", "suitcase", "goods"]
    array skip_things = ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]
    var load_buffer
    if !HasIndex(overrides, "skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    if load_buffer != 0
    skip_types = deserialise(load_buffer)
    end
    else
    skip_types = overrides["skip_types"]
    end
    if !HasIndex(overrides, "skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    if load_buffer != 0
    skip_things = deserialise(load_buffer)
    end
    else
    skip_things = overrides["skip_things"]
    end
    if HasIndex(overrides, "more_skip_types")
    loop type in overrides["more_skip_types"]
    if !has(type, skip_types)
    Append(skip_types, type)
    end
    end
    end
    if HasIndex(overrides, "more_skip_things")
    loop thing in overrides["more_skip_things"]
    if !has(thing, skip_things)
    Append(skip_things, thing)
    end
    end
    end
    load_buffer = MemoryAPI.LoadMemory(function)
    if load_buffer != 0
    if load_buffer != name
    if !has(load_buffer, skip_things)
    if !has(TingrunnerAPI.GetTypeOfThing(load_buffer), skip_types)
    var connection = Connect(load_buffer)
    if connection.HasFunction(function)
    return [true, connection]
    end
    end
    end
    end
    end
    load_buffer = 0
    loop room in TingrunnerAPI.GetAllRooms()
    loop thing in TingrunnerAPI.GetThingsInRoom(room)
    if thing != name
    if !has(thing, skip_things)
    if !has(TingrunnerAPI.GetTypeOfThing(thing), skip_types)
    var connection = Connect(thing)
    if connection.HasFunction(function)
    MemoryAPI.SaveMemory(function, thing)
    return [true, connection]
    end
    end
    end
    end
    end
    end
    return [false, "`" + function + "` not found."]
    end
  • file addition: supply.md (----------)
    [0.2]
    # supply.sprak
    Library for supplying connections.
    ## Usage
    * Once in a while, keep re-runnning the "skip.sprak" script until completion to update the list of types and things to skip.
    * Don't use on "FinanceComputer" or "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1".
    ## Functions
    ### `supply`
    Returns `[true, connection]` where `connection` is a connection to a thing that supplies the input function if anything in the game world is able to supply the function, otherwise `[false, error_message]` where `error_message` is a `string` about what caused the failure. If it hasn't yet been cached, the thing that supplies the function is then saved in the memory of "FinanceComputer" (or the thing overriding it) using the name of the function as key to speed up later access to the same function.
    #### Type
    `["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> [true, connection] | [false, string]`
    #### Arguments
    * `overrides`: `array` that may contain data to replace or supplement variables used by the function.
    * `function`: Function to find a connection for.
    #### Examples
    ```sprak
    var connection = supply([], "IsNight")
    Say("" + connection[1].IsNight())
    ```
    #### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
  • file addition: skip.sprak (----------)
    [0.2]
    DisconnectAll()
    ###############
    # serde.sprak #
    ###############
    string serialise_string(string input)
    string output = ""
    loop character in input
    if character == '"'
    output += "\"
    else if character == "\"
    output += "\"
    end
    output += character
    end
    return '"' + output + '"'
    end
    string serialise_array(array input)
    string output = ""
    bool not_start = false
    loop key in GetIndexes(input)
    string key_type = Type(key)
    if key_type != "array"
    if not_start
    output += ","
    else
    not_start = true
    end
    output += serialise(key) + ":" + serialise(input[key])
    end
    end
    return "{" + output + "}"
    end
    string serialise(var input)
    string input_type = Type(input)
    if input_type == "unknown"
    string output = ""
    loop character in "" + input
    if character != "i"
    output += character
    end
    end
    return output
    else if input_type == "string"
    return serialise_string(input)
    else if input_type == "number"
    return "" + input
    else if input_type == "bool"
    if input
    return "t"
    end
    return "f"
    else if input_type == "array"
    return serialise_array(input)
    end
    end
    string deserialise_string(string input)
    string output = ""
    bool escaped = false
    loop character in input
    if character != "\"
    if character != '"'
    output += character
    end
    else if escaped
    output += character
    escaped = false
    else if character == '\'
    escaped = true
    end
    end
    return output
    end
    bool is_digit(string input)
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    var deserialise_array(string input)
    array accumulator = []
    bool in_string = false
    bool escaped = false
    bool in_value = false
    string buffer = ""
    number key_type = 0
    bool key_bool = false
    number key_number = 0
    string key_string = ""
    number value_type = 0
    bool value_bool = false
    number value_number = 0
    string value_string = ""
    array contexts = []
    loop character in input
    bool is_numeric = false
    if character == ":"
    if !in_string
    in_value = true
    if key_type == 2
    key_number = buffer
    buffer = ""
    end
    else if in_value
    value_string += ":"
    else
    key_string += ":"
    end
    else if character == ","
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    in_value = false
    buffer = ""
    key_string = ""
    value_string = ""
    else if in_value
    value_string += ","
    else
    key_string += ","
    end
    else if is_digit(character)
    is_numeric = true
    else if character == "."
    is_numeric = true
    else if character == "-"
    is_numeric = true
    else if character == '"'
    if !in_string
    in_string = true
    if in_value
    value_type = 3
    else
    key_type = 3
    end
    else if !escaped
    in_string = false
    else if in_value
    value_string += '"'
    else
    key_string += '"'
    end
    else if character == "t"
    if !in_string
    if in_value
    value_bool = true
    value_type = 1
    else
    key_bool = true
    key_type = 1
    end
    else if in_value
    value_string += "t"
    else
    key_string += "t"
    end
    else if character == "f"
    if !in_string
    if in_value
    value_bool = false
    value_type = 1
    else
    key_bool = false
    key_type = 1
    end
    else if in_value
    value_string += "f"
    else
    key_string += "f"
    end
    else if character == "{"
    if !in_string
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    else
    value_string += "{"
    end
    else if character == "}"
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    array last_context = contexts[Count(contexts) - 1]
    array last_accumulator = last_context[0]
    number last_key_type = last_context[1]
    if last_key_type != 0
    last_accumulator[last_context[2]] = accumulator
    else
    return accumulator
    end
    accumulator = last_accumulator
    value_type = 4
    Remove(contexts, Count(contexts) - 1)
    else
    value_string += "}"
    end
    else if character == "\"
    if !escaped
    escaped = true
    else
    escaped = false
    if in_value
    value_string += "\"
    else
    key_string += "\"
    end
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    if is_numeric
    if !in_string
    buffer += character
    if in_value
    value_type = 2
    else
    key_type = 2
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    end
    end
    end
    var deserialise(string input)
    if input[0] == "{"
    return deserialise_array(input)
    else if is_digit(input[0])
    number output = input
    return output
    else if input[0] == "-"
    number output = input
    return output
    else if input[0] == '"'
    return deserialise_string(input)
    else if input == "t"
    return true
    else if input == "f"
    return false
    end
    end
    ##################
    # equality.sprak #
    ##################
    bool equal_array(array first, array second)
    if Count(first) == Count(second)
    if "" + first == "" + second
    loop key in GetIndexes(first)
    if !HasIndex(second, key)
    return false
    else if !equal(first[key], second[key])
    return false
    end
    end
    return true
    end
    end
    return false
    end
    bool equal(var first, var second)
    string type_first = Type(first)
    if type_first == Type(second)
    if type_first != "array"
    return first == second
    end
    return equal_array(first, second)
    end
    return false
    end
    ###############
    # array.sprak #
    ###############
    bool has(array input, var test_element)
    loop element in input
    if equal(element, test_element)
    return true
    end
    end
    return false
    end
    #############
    # Functions #
    #############
    bool no_SprakAPI(string thing)
    return Connect(thing).HasFunction("") == 0
    end
    ########
    # Main #
    ########
    ClearText()
    string name = Name()
    string MemoryAPI = Connect("FinanceComputer")
    string TingrunnerAPI = Connect("PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1")
    array skip_types = []
    skip_types[0] = "floppy"
    array skip_things = []
    var load_buffer = MemoryAPI.LoadMemory("skip_types")
    if load_buffer != 0
    skip_types = deserialise(load_buffer)
    end
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    if load_buffer != 0
    skip_things = deserialise(load_buffer)
    end
    load_buffer = 0
    bool seen_last_thing = false
    string last_thing = ""
    number number_buffer = Count(skip_things)
    if number_buffer > 0
    last_thing = skip_things[number_buffer - 1]
    else
    seen_last_thing = true
    end
    loop room in TingrunnerAPI.GetAllRooms()
    loop thing in TingrunnerAPI.GetThingsInRoom(room)
    if seen_last_thing
    string thing_type = TingrunnerAPI.GetTypeOfThing(thing)
    if thing != name
    if !has(skip_types, thing_type)
    if !has(skip_things, thing)
    Append(skip_things, thing)
    MemoryAPI.SaveMemory("skip_things", serialise(skip_things))
    if no_SprakAPI(thing)
    Append(skip_types, thing_type)
    MemoryAPI.SaveMemory("skip_types", serialise(skip_types))
    end
    Remove(skip_things, Count(skip_things) - 1)
    end
    end
    end
    else if thing == last_thing
    seen_last_thing = true
    end
    end
    end
    MemoryAPI.SaveMemory("skip_things", serialise(skip_things))
    Say("Done.")
    DisconnectAll()
  • file addition: skip.md (----------)
    [0.2]
    # skip.sprak
    Finds and saves the names of things with broken code and types with no SprakAPI (no `HasFunction` function). Saves the serialised results to the memory of "FinanceComputer" using the keys "skip_types" for the types "skip_things" for the names.
    ## Usage
    * Don't run the code on "FinanceComputer" or "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1".
    * Save the code onto a thing that has the `Say` and `Connect` functions. A drink would work, but a computer would be more ideal, as the latter's code execution speed can be increased using screwdrivers.
    * Run the code until it causes an error or until completion. I recommend pausing the game whilst the code is running and periodically checking if it's done as pausing allows code to run faster. It is critical that the code is not interrupted whilst it's running (i.e., don't re-hack the thing/re-run the code) as this will cause incorrect outputs.
    * Repeat the previous step until a notification appears with the "Done." message. I recommend saving after each time the code errors/finishes in case of accidents.
    ## Functions
    ### `no_SprakAPI`
    Determines if the thing has SprakAPI.
    #### Type
    `string -> bool`
    #### Arguments
    * `thing`: Thing to test.
    #### Examples
    ```sprak
    # TODO
    ```
    ## Imports
    * supply.sprak
    * `hardcoded_supply`
    * serde.sprak
    * equality.sprak
    * array.sprak
    * `has`
  • file addition: serde.tests.sprak (----------)
    [0.2]
    ##################
    # equality.sprak #
    ##################
    bool equal_array(array first, array second)
    if Count(first) == Count(second) && "" + first == "" + second
    loop key in GetIndexes(first)
    if !HasIndex(second, key)
    return false
    else if !equal(first[key], second[key])
    return false
    end
    end
    return true
    end
    return false
    end
    bool equal(var first, var second)
    string type_first = Type(first)
    if type_first == Type(second)
    if type_first != "array"
    return first == second
    end
    return equal_array(first, second)
    end
    return false
    end
    ##############
    # test.sprak #
    ##############
    void run_tests(string name, array tests)
    number count = 0
    loop test in tests
    if !equal(test[0], test[1])
    Print(name + " " + count + ": fail")
    Print("left: " + test[0])
    Print("right: " + test[1])
    end
    count += 1
    end
    Print(name + " tests done.")
    end
    #############
    # Functions #
    #############
    void test_serialise_string()
    string name = "serialise_string"
    array tests = []
    Append(tests, [serialise_string('a'), '"a"'])
    Append(tests, [serialise_string(''), '""'])
    Append(tests, [serialise_string('\'), '"\\"'])
    Append(tests, [serialise_string('"'), '"\""'])
    Append(tests, [serialise_string('\\'), '"\\\\"'])
    run_tests(name, tests)
    end
    void test_serialise_array()
    string name = "serialise_array"
    array tests = []
    Append(tests, [serialise_array([false]), '{0:f}'])
    Append(tests, [serialise_array([-273.15]), '{0:-273.15}'])
    Append(tests, [serialise_array([""]), '{0:""}'])
    Append(tests, [serialise_array([[]]), '{0:{}}'])
    Append(tests, [serialise_array([]), '{}'])
    run_tests(name, tests)
    end
    void test_serialise()
    string name = "serialise"
    array tests = []
    Append(tests, [serialise(false), 'f'])
    Append(tests, [serialise(-273.15), '-273.15'])
    Append(tests, [serialise(""), '""'])
    Append(tests, [serialise([]), '{}'])
    array a = [false]
    array keys = GetIndexes(a)
    Append(tests, [serialise(keys[0]), '0'])
    run_tests(name, tests)
    end
    void test_deserialise_string()
    string name = "deserialise_string"
    array tests = []
    Append(tests, [deserialise_string('"a"'), 'a'])
    Append(tests, [deserialise_string('""'), ''])
    Append(tests, [deserialise_string('"\\"'), '\'])
    Append(tests, [deserialise_string('"\""'), '"'])
    Append(tests, [deserialise_string('"\\\\"'), '\\'])
    run_tests(name, tests)
    end
    void test_is_digit()
    string name = "is_digit"
    array tests = []
    Append(tests, [is_digit("0"), true])
    Append(tests, [is_digit("1"), true])
    Append(tests, [is_digit("2"), true])
    Append(tests, [is_digit("3"), true])
    Append(tests, [is_digit("4"), true])
    Append(tests, [is_digit("5"), true])
    Append(tests, [is_digit("6"), true])
    Append(tests, [is_digit("7"), true])
    Append(tests, [is_digit("8"), true])
    Append(tests, [is_digit("9"), true])
    Append(tests, [is_digit("a"), false])
    run_tests(name, tests)
    end
    void test_deserialise_array()
    string name = "deserialise_array"
    array tests = []
    array a = []
    a = deserialise_array('{0:f}')
    Append(tests, [a, [false]])
    a = deserialise_array('{0:-273.15}')
    Append(tests, [a, [-273.15]])
    a = deserialise_array('{0:"a"}')
    Append(tests, [a, ["a"]])
    a = deserialise_array('{0:""}')
    Append(tests, [a, [""]])
    a = deserialise_array('{0:{}}')
    Append(tests, [a, [[]]])
    a = deserialise_array('{}')
    Append(tests, [a, []])
    run_tests(name, tests)
    end
    void test_deserialise()
    string name = "deserialise"
    array tests = []
    Append(tests, [deserialise('f'), false])
    Append(tests, [deserialise('-273.15'), -273.15])
    Append(tests, [deserialise('""'), ""])
    Append(tests, [deserialise('{}'), []])
    array a = [false]
    array keys = GetIndexes(a)
    number b = keys[0]
    Append(tests, [deserialise('0'), b])
    run_tests(name, tests)
    end
    DisconnectAll()
    ClearText()
    test_serialise_string()
    test_serialise_array()
    test_serialise()
    test_deserialise_string()
    test_is_digit()
    test_deserialise_array()
    test_deserialise()
  • file addition: serde.sprak (----------)
    [0.2]
    ###############
    # serde.sprak #
    ###############
    string serialise_string(string input)
    string output = ""
    loop character in input
    if character == '"'
    output += "\"
    else if character == "\"
    output += "\"
    end
    output += character
    end
    return '"' + output + '"'
    end
    string serialise_array(array input)
    string output = ""
    bool not_start = false
    loop key in GetIndexes(input)
    string key_type = Type(key)
    if key_type != "array"
    if not_start
    output += ","
    else
    not_start = true
    end
    output += serialise(key) + ":" + serialise(input[key])
    end
    end
    return "{" + output + "}"
    end
    string serialise(var input)
    string input_type = Type(input)
    if input_type == "unknown"
    string output = ""
    loop character in "" + input
    if character != "i"
    output += character
    end
    end
    return output
    else if input_type == "string"
    return serialise_string(input)
    else if input_type == "number"
    return "" + input
    else if input_type == "bool"
    if input
    return "t"
    end
    return "f"
    else if input_type == "array"
    return serialise_array(input)
    end
    end
    string deserialise_string(string input)
    string output = ""
    bool escaped = false
    loop character in input
    if character != "\"
    if character != '"'
    output += character
    end
    else if escaped
    output += character
    escaped = false
    else if character == '\'
    escaped = true
    end
    end
    return output
    end
    bool is_digit(string input)
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    var deserialise_array(string input)
    array accumulator = []
    bool in_string = false
    bool escaped = false
    bool in_value = false
    string buffer = ""
    number key_type = 0
    bool key_bool = false
    number key_number = 0
    string key_string = ""
    number value_type = 0
    bool value_bool = false
    number value_number = 0
    string value_string = ""
    array contexts = []
    loop character in input
    bool is_numeric = false
    if character == ":"
    if !in_string
    in_value = true
    if key_type == 2
    key_number = buffer
    buffer = ""
    end
    else if in_value
    value_string += ":"
    else
    key_string += ":"
    end
    else if character == ","
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    in_value = false
    buffer = ""
    key_string = ""
    value_string = ""
    else if in_value
    value_string += ","
    else
    key_string += ","
    end
    else if is_digit(character)
    is_numeric = true
    else if character == "."
    is_numeric = true
    else if character == "-"
    is_numeric = true
    else if character == '"'
    if !in_string
    in_string = true
    if in_value
    value_type = 3
    else
    key_type = 3
    end
    else if !escaped
    in_string = false
    else if in_value
    value_string += '"'
    else
    key_string += '"'
    end
    else if character == "t"
    if !in_string
    if in_value
    value_bool = true
    value_type = 1
    else
    key_bool = true
    key_type = 1
    end
    else if in_value
    value_string += "t"
    else
    key_string += "t"
    end
    else if character == "f"
    if !in_string
    if in_value
    value_bool = false
    value_type = 1
    else
    key_bool = false
    key_type = 1
    end
    else if in_value
    value_string += "f"
    else
    key_string += "f"
    end
    else if character == "{"
    if !in_string
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    else
    value_string += "{"
    end
    else if character == "}"
    if !in_string
    if key_type == 2
    if value_type == 3
    accumulator[key_number] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_number] = value_number
    else if value_type == 1
    accumulator[key_number] = value_bool
    end
    else if key_type == 3
    if value_type == 3
    accumulator[key_string] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_string] = value_number
    else if value_type == 1
    accumulator[key_string] = value_bool
    end
    else if key_type == 1
    if value_type == 3
    accumulator[key_bool] = value_string
    else if value_type == 2
    value_number = buffer
    accumulator[key_bool] = value_number
    else if value_type == 1
    accumulator[key_bool] = value_bool
    end
    end
    array last_context = contexts[Count(contexts) - 1]
    array last_accumulator = last_context[0]
    number last_key_type = last_context[1]
    if last_key_type != 0
    last_accumulator[last_context[2]] = accumulator
    else
    return accumulator
    end
    accumulator = last_accumulator
    value_type = 4
    Remove(contexts, Count(contexts) - 1)
    else
    value_string += "}"
    end
    else if character == "\"
    if !escaped
    escaped = true
    else
    escaped = false
    if in_value
    value_string += "\"
    else
    key_string += "\"
    end
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    if is_numeric
    if !in_string
    buffer += character
    if in_value
    value_type = 2
    else
    key_type = 2
    end
    else if in_value
    value_string += character
    else
    key_string += character
    end
    end
    end
    end
    var deserialise(string input)
    if input[0] == "{"
    return deserialise_array(input)
    else if is_digit(input[0])
    number output = input
    return output
    else if input[0] == "-"
    number output = input
    return output
    else if input[0] == '"'
    return deserialise_string(input)
    else if input == "t"
    return true
    else if input == "f"
    return false
    end
    end
  • file addition: serde.md (----------)
    [0.2]
    # serde.sprak
    Library for (de)serialising data.
    ## Functions
    ### `serialise_string`
    Returns the serialised form of input where `\` and `"` characters have been prepended with `\`.
    #### Type
    `string -> string`
    #### Arguments
    * `input`: String to serialise.
    #### Examples
    ```sprak
    Print(equal(serialise_string('foo"\\'), 'foo\"\\\\'))
    ```
    ### `serialise_array`
    Returns the serialised version of an `array`. Excludes elements whose keys are not of type `bool`, `number`, `string`, or `unknown`. Keys of type `unknown` are assumed to be `array` indices and will be converted to `number`.
    #### Type
    `array -> string`
    #### Arguments
    * `input`: Array to serialise.
    #### Examples
    ```sprak
    Print(equal(serialise_array([true, false]), "{0:t,1:f}"))
    ```
    ### `serialise`
    Returns the serialised version of the input. Assumes data of type `unknown` are `array` indices and are converted to `number`. Data of type `number` are rounded to include only up to 6 decimal places of precision.
    #### Type
    `var -> string`
    #### Arguments
    * `input`: Input to serialise.
    #### Examples
    ```sprak
    Print(equal(serialise(true), "t"))
    Print(equal(serialise(false), "f"))
    Print(equal(serialise(-273.15), "-273.15"))
    Print(equal(serialise([true, "false"]) == '{0:t,1:"false"}'))
    ```
    ### `deserialise_string`
    Returns the deserialised form of the input.
    #### Type
    `string -> string`
    #### Arguments
    * `input`: Serialised string to deserialise.
    #### Examples
    ```sprak
    Print(equal(deserialise_string('"foo\"\\\\"'), 'foo"\\'))
    ```
    ### `is_digit`
    Determines if the input character is a numeric digit.
    #### Type
    `string -> bool`
    #### Arguments
    * `input`: Character to test.
    #### Examples
    ```sprak
    Print(is_digit(0))
    Print(!is_digit(a))
    ```
    ### `deserialise_array`
    Returns the deserialised form of the input.
    Assumptions:
    * "\\" and whitespace characters only occur in strings.
    * Keys are only of type `bool`, `number` or `string`.
    * Input is valid.
    #### Type
    `string -> array`
    #### Arguments
    * `input`: Serialised array to deserialise.
    #### Examples
    ```sprak
    Print(equal(deserialise_array("{0:t,1:f}"), [true, false]))
    ```
    ### `deserialise`
    Returns the deserialised form of the input.
    Assumptions:
    * "\\" and whitespace characters only occur in strings.
    * `array` keys are only of type `bool`, `number` or `string`.
    * Input is valid.
    #### Type
    `string -> var`
    #### Arguments
    * `input`: Input to deserialise.
    #### Examples
    ```sprak
    Print(equal(deserialise("t"), true))
    Print(equal(deserialise("f"), false))
    Print(equal(deserialise("-273.15"), -273.15))
    Print(equal(deserialise('{0:t,1:"false"}'), [true, "false"]))
    ```
    ## TODO
    * Replace recursions with iterations in:
    * `serialise_array` and `serialise`
    * Add an option to serialise numbers using more precision.
  • file addition: equality.sprak (----------)
    [0.2]
    bool equal_array(array first, array second)
    if Count(first) == Count(second)
    if "" + first == "" + second
    loop key in GetIndexes(first)
    if !HasIndex(second, key)
    return false
    else if !equal(first[key], second[key])
    return false
    end
    end
    return true
    end
    end
    return false
    end
    bool equal(var first, var second)
    string type_first = Type(first)
    if type_first == Type(second)
    if type_first != "array"
    return first == second
    end
    return equal_array(first, second)
    end
    return false
    end
  • file addition: equality.md (----------)
    [0.2]
    # serde.sprak
    Library for testing data equality.
    ## Functions
    ### `equal_array`
    Determines if both inputs are equal to each other
    #### Type
    `array -> array -> bool`
    #### Arguments
    * `first`: Input to compare with `second`.
    * `second`: Input to compare with `first`.
    #### Examples
    ```sprak
    # TODO
    ```
    ### `equal`
    Determines if both inputs are equal to each other
    #### Type
    `var -> var -> bool`
    #### Arguments
    * `first`: Input to compare with `second`.
    * `second`: Input to compare with `first`.
    #### Examples
    ```sprak
    Print(equal(true, true))
    array a = []
    a[1] = 1
    a[0] = 0
    Print(equal([0, 1], a)[1])
    Print(!equal(true, false)[1])
    array b = []
    Append(b, [0])
    array c = []
    Append(c, b[0])
    Print(!equal(b, b)[0])
    ```
  • file addition: else_heart_break.code-workspace (----------)
    [0.2]
    {
    "folders": [
    {
    "name": "else_heart_break_scripts",
    "path": "."
    },
    {
    "name": "else_heart_break",
    "path": "../../../../else_heart_break"
    },
    {
    "name": "sprak-language-extension",
    "path": "../../../../projects/sprak-language-extension"
    },
    {
    "path": "../else_heart_break_scripts.1639998913"
    }
    ],
    "settings": {}
    }
  • file addition: array.sprak (----------)
    [0.2]
    ###############
    # array.sprak #
    ###############
    bool has(var elem, array arr)
    loop element in arr
    if equal(element, elem)
    return true
    end
    end
    return false
    end
  • file addition: array.md (----------)
    [0.2]
    # serde.sprak
    Library for `array` data.
    ## Functions
    ### `has`
    Determines if an array contains an element.
    #### Type
    `A -> array A -> bool`
    #### Arguments
    * `elem`: The value to search for.
    * `arr`: Array to search in.
    #### Examples
    ```sprak
    # TODO
    ```
    #### Imports
    * equality.sprak
    * `equal_array`
    * `equal`
  • file addition: README.md (----------)
    [0.2]
    # else-Heart.Break
    Code for items in the game [else Heart.Break()](http://elseheartbreak.com/ "else Heart.Break() Homepage").
    ---
    ## Notes
    * `bool` operators in Sprak don't seem to short-circuit. Unconcise usage of conditionals in this project may have been used to emulate short-circuiting `bool` operators.
    * Some functions have long execution durations and may stop after a while. To prevent this, pause the game when running them because they continue to run (and at a faster speed) even when the game is paused.
    ---
    ## License
    This software is distributed and licensed under the terms of the [Blue Oak Model License 1.0.0](https://web.archive.org/web/20190309191626/https://blueoakcouncil.org/license/1.0.0).
    ### Contribution
    Unless you explicitly state otherwise, any contribution submitted for inclusion in this software by you shall be licensed as above, without any additional terms or conditions.
  • file addition: LICENSE (----------)
    [0.2]
    # Blue Oak Model License
    Version 1.0.0
    ## Purpose
    This license gives everyone as much permission to work with
    this software as possible, while protecting contributors
    from liability.
    ## Acceptance
    In order to receive this license, you must agree to its
    rules. The rules of this license are both obligations
    under that agreement and conditions to your license.
    You must not do anything with this software that triggers
    a rule that you cannot or will not follow.
    ## Copyright
    Each contributor licenses you to do everything with this
    software that would otherwise infringe that contributor's
    copyright in it.
    ## Notices
    You must ensure that everyone who gets a copy of
    any part of this software from you, with or without
    changes, also gets the text of this license or a link to
    <https://blueoakcouncil.org/license/1.0.0>.
    ## Excuse
    If anyone notifies you in writing that you have not
    complied with [Notices](#notices), you can keep your
    license by taking all practical steps to comply within 30
    days after the notice. If you do not do so, your license
    ends immediately.
    ## Patent
    Each contributor licenses you to do everything with this
    software that would otherwise infringe any patent claims
    they can license or become able to license.
    ## Reliability
    No contributor can revoke this license.
    ## No Liability
    ***As far as the law allows, this software comes as is,
    without any warranty or condition, and no contributor
    will be liable to anyone for any damages related to this
    software or this license, under any kind of legal claim.***
  • file addition: .ignore (----------)
    [0.2]
    .git
    .DS_Store