2: Add programs for drink, modifier, screwdriver and server.

[?]
9Zb2bmkejrNknawUtr3MKvVstZkVDR8x8ritfgZXKrky
Oct 1, 2022, 8:53 AM
S7BXWG4QQMJ6M4XDUNDLJGD4BXB4QVZKXWSHXXVGKMNDWB5WV5LQC

Dependencies

Change contents

  • file addition: types.sprak (----------)
    [3.2]
    ###############
    # types.sprak #
    ###############
    array Left(var input)
    return [false, input]
    end
    array Right(var input)
    return [true, input]
    end
  • file addition: types.md (----------)
    [3.2]
    # types.sprak
    Library of types.
    ## Functions
    ### `Left`
    Constructor for the `Left` variant of the `Either` type
    #### Type
    `A -> [false, A]`
    #### Arguments
    * `input`: Value to wrap in the `Either` type.
    #### Examples
    ```sprak
    # TODO
    ```
    ### `Right`
    Constructor for the `Reft` variant of the `Either` type
    #### Type
    `A -> [true, A]`
    #### Arguments
    * `input`: Value to wrap in the `Either` type.
    #### Examples
    ```sprak
    # TODO
    ```
  • edit in test.md at line 2
    [3.393][3.393:394]()
  • edit in test.md at line 8
    [3.466]
    [3.466]
    ### Imports
    * equality.sprak
  • replacement in test.md at line 22
    [3.701][3.701:730]()
    #### Imports
    * equality.sprak
    [3.701]
    ## TODO
    * Add option to copy output to clipboard.
  • replacement in supply.sprak at line 8
    [3.924][3.924:1015]()
    if character != "\"
    if character != '"'
    output += character
    end
    else if escaped
    [3.924]
    [3.1015]
    if !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
  • edit in supply.sprak at line 17
    [3.1057][3.1057:1102]()
    else if character == '\'
    escaped = true
  • replacement in supply.sprak at line 23
    [3.1161][3.1161:1239]()
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    [3.1161]
    [3.1239]
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
  • edit in supply.sprak at line 29
    [3.1244][3.1244:1249]()
    end
  • replacement in supply.sprak at line 38
    [3.1342][3.1342:1378]()
    var deserialise_array(string input)
    [3.1342]
    [3.1378]
    array deserialise_array(string input)
  • edit in supply.sprak at line 40
    [3.1402]
    [3.1402]
    bool is_numeric = false
  • replacement in supply.sprak at line 55
    [3.1727][3.1727:1775]()
    bool is_numeric = false
    if character == ":"
    [3.1727]
    [3.1775]
    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 == ":"
  • edit in supply.sprak at line 155
    [3.3146][3.3146:3887]()
    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
  • edit in supply.sprak at line 159
    [3.4011][3.4011:4084]()
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in supply.sprak at line 161
    [3.4169]
    [3.4169]
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in supply.sprak at line 167
    [3.4264]
    [3.4264]
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
  • edit in supply.sprak at line 256
    [3.6062]
    [3.6062]
    is_numeric = false
  • edit in supply.sprak at line 284
    [3.6573][3.6573:6603]()
    if "" + first == "" + second
  • edit in supply.sprak at line 292
    [3.6768][3.6768:6773]()
    end
  • replacement in supply.sprak at line 310
    [3.7062][3.7062:7159]()
    bool has(var test_element, array input)
    loop element in input
    if equal(element, test_element)
    [3.7062]
    [3.7159]
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
  • edit in supply.sprak at line 317
    [3.7199]
    [3.7199]
    end
    ###############
    # types.sprak #
    ###############
    array Left(var input)
    return [false, input]
  • replacement in supply.sprak at line 326
    [3.7204][3.7204:7293]()
    #############
    # Functions #
    #############
    array supply(array overrides, string function)
    [3.7204]
    [3.7293]
    array Right(var input)
    return [true, input]
    end
    ################
    # supply.sprak #
    ################
    array supplier_of(array overrides, string function)
  • edit in supply.sprak at line 336
    [3.7426][3.7426:7448]()
    string name = Name()
  • replacement in supply.sprak at line 342
    [3.7630][3.7630:7761]()
    var MemoryAPI
    if MemoryAPI_thing != name
    MemoryAPI = Connect(MemoryAPI_thing)
    else
    return [false, "MemoryAPI unavailable."]
    [3.7630]
    [3.7761]
    number MemoryAPI = Connect(MemoryAPI_thing)
    number TingrunnerAPI = Connect(TingrunnerAPI_thing)
    array skip_types = []
    loop ["floppy", "navnode", "bed", "point", "seat", "locker", "memory", "portal", "character", "map", "suitcase", "goods"]
    Append(skip_types, @)
  • replacement in supply.sprak at line 348
    [3.7766][3.7766:7917]()
    var TingrunnerAPI
    if TingrunnerAPI_thing != name
    TingrunnerAPI = Connect(TingrunnerAPI_thing)
    else
    return [false, "TingrunnerAPI unavailable."]
    [3.7766]
    [3.7917]
    array skip_things = []
    loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]
    Append(skip_things, @)
  • replacement in supply.sprak at line 352
    [3.7922][3.7922:8297]()
    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
    [3.7922]
    [3.8297]
    string load_buffer = ""
  • replacement in supply.sprak at line 354
    [3.8336][3.8336:8450]()
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    if load_buffer != 0
    skip_types = deserialise(load_buffer)
    [3.8336]
    [3.8450]
    if MemoryAPI.HasMemory("skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    RemoveAll(skip_types)
    loop deserialise(load_buffer)
    Append(skip_types, @)
    end
  • replacement in supply.sprak at line 362
    [3.8462][3.8462:8501]()
    skip_types = overrides["skip_types"]
    [3.8462]
    [3.8501]
    RemoveAll(skip_types)
    loop overrides["skip_types"]
    Append(skip_types, @)
    end
  • replacement in supply.sprak at line 368
    [3.8546][3.8546:8662]()
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    if load_buffer != 0
    skip_things = deserialise(load_buffer)
    [3.8546]
    [3.8662]
    if MemoryAPI.HasMemory("skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    RemoveAll(skip_things)
    loop deserialise(load_buffer)
    Append(skip_things, @)
    end
  • replacement in supply.sprak at line 376
    [3.8674][3.8674:8715]()
    skip_things = overrides["skip_things"]
    [3.8674]
    [3.8715]
    RemoveAll(skip_things)
    loop overrides["skip_things"]
    Append(skip_things, @)
    end
  • replacement in supply.sprak at line 382
    [3.8763][3.8763:8865]()
    loop type in overrides["more_skip_types"]
    if !has(type, skip_types)
    Append(skip_types, type)
    [3.8763]
    [3.8865]
    loop overrides["more_skip_types"]
    if !has(skip_types, @)
    Append(skip_types, @)
  • replacement in supply.sprak at line 389
    [3.8927][3.8927:9035]()
    loop thing in overrides["more_skip_things"]
    if !has(thing, skip_things)
    Append(skip_things, thing)
    [3.8927]
    [3.9035]
    loop overrides["more_skip_things"]
    if !has(skip_things, @)
    Append(skip_things, @)
  • replacement in supply.sprak at line 395
    [3.9053][3.9053:9350]()
    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]
    [3.9053]
    [3.9350]
    if MemoryAPI.HasMemory(function)
    load_buffer = MemoryAPI.LoadMemory(function)
    if !has(skip_things, load_buffer)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(load_buffer))
    if Connect(load_buffer).HasFunction(function)
    return Right(load_buffer)
    end
    end
  • edit in supply.sprak at line 404
    [3.9356][3.9356:9366]()
    end
    end
  • replacement in supply.sprak at line 405
    [3.9371][3.9371:9393]()
    end
    load_buffer = 0
    [3.9371]
    [3.9393]
    load_buffer = ""
  • replacement in supply.sprak at line 408
    [3.9487][3.9487:9674]()
    if thing != name
    if !has(thing, skip_things)
    if !has(TingrunnerAPI.GetTypeOfThing(thing), skip_types)
    var connection = Connect(thing)
    if connection.HasFunction(function)
    [3.9487]
    [3.9674]
    if !has(skip_things, thing)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(thing))
    if Connect(thing).HasFunction(function)
  • replacement in supply.sprak at line 412
    [3.9717][3.9717:9748]()
    return [true, connection]
    [3.9717]
    [3.9748]
    return Right(thing)
  • edit in supply.sprak at line 414
    [3.9756][3.9756:9763]()
    end
  • replacement in supply.sprak at line 418
    [3.9788][3.9788:9837]()
    return [false, "`" + function + "` not found."]
    [3.9788]
    [3.9837]
    return Left("`" + function + "` not found.")
    end
    string supplier_of_unwrapped(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    return array_buffer[1]
    end
    array supply(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    if array_buffer[0]
    return Right(Connect(array_buffer[1]))
    else
    return Left(array_buffer[1])
    end
    end
    number supply_unwrapped(array overrides, string function)
    array array_buffer = supply(overrides, function)
    return array_buffer[1]
  • edit in supply.md at line 2
    [3.9891][3.9891:9892]()
  • edit in supply.md at line 5
    [3.9937][3.9937:9938]()
  • edit in supply.md at line 7
    [3.10159]
    [3.10159]
    * May fail if the thing containing the function found is the same thing that is programmed with this program. `Name()` function isn't used to detect this as that isn't available in all things. Use `overrides` to skip these things instead.
  • edit in supply.md at line 10
    [3.10173]
    [3.10173]
    ### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
    * types.sprak
    * `Left`
    * `Right`
    ### `supplier_of`
    Returns `Either(string, string)` where `Right` is the name of a thing that supplies the input function if anything in the game world is able to supply the function, and `Left` is a error message 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 -> Either(string, string)`
    #### Arguments
    * `overrides`: `array` that may contain data to replace or supplement variables used by the function.
    * `function`: Function to find a supplier of.
    #### Examples
    ```sprak
    array array_buffer = supplier_of([], "IsNight")
    string supplier = array_buffer[1]
    Say(Connect(supplier).IsNight())
    ```
  • edit in supply.md at line 34
    [3.10174]
    [3.10174]
    ### `supplier_of_unwrapped`
    Returns a `string` representing the name of a thing that supplies the input function. 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. May fail silently if nothing in the game world is able to supply the function.
    #### Type
    `["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> string`
    #### Arguments
    * `overrides`: `array` that may contain data to replace or supplement variables used by the function.
    * `function`: Function to find a supplier of.
    #### Examples
    ```sprak
    string supplier = supplier_of_unwrapped([], "IsNight")
    Say(Connect(supplier).IsNight())
    ```
  • replacement in supply.md at line 48
    [3.10187][3.10187:10689]()
    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.
    [3.10187]
    [3.10689]
    Returns `Either(string, number)` where `Right` is the connection to a thing that supplies the input function if anything in the game world is able to supply the function, and `Left` is an error message 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.
  • replacement in supply.md at line 50
    [3.10699][3.10699:10912]()
    `["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> [true, connection] | [false, string]`
    [3.10699]
    [3.10912]
    `["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> Either(string, number)`
  • replacement in supply.md at line 56
    [3.11101][3.11101:11174]()
    var connection = supply([], "IsNight")
    Say("" + connection[1].IsNight())
    [3.11101]
    [3.11174]
    array array_buffer = supply([], "IsNight")
    number connection = array_buffer[1]
    Say(connection.IsNight())
  • replacement in supply.md at line 60
    [3.11178][3.11178:11261]()
    #### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
    [3.11178]
    ### `supply_unwrapped`
    Returns a `number` representing the connection to a thing that supplies the input function. 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. May fail silently if nothing in the game world is able to supply the function.
    #### Type
    `["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> number`
    #### 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
    string connection = supply_unwrapped([], "IsNight")
    Say(connection.IsNight())
    ```
  • replacement in skip.sprak at line 1
    [3.11297][3.11298:11314]()
    DisconnectAll()
    [3.11297]
    [3.11314]
    main()
    void main()
    DisconnectAll()
    ClearText()
    string MemoryAPI_thing = "FinanceComputer"
    string TingrunnerAPI_thing = "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1"
    string name = Name()
    number MemoryAPI = Connect(MemoryAPI_thing)
    number TingrunnerAPI = Connect(TingrunnerAPI_thing)
    array skip_types = []
    skip_types[0] = "floppy"
    array skip_things = []
    string load_buffer = ""
    if MemoryAPI.HasMemory("skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    RemoveAll(skip_types)
    loop deserialise(load_buffer)
    Append(skip_types, @)
    end
    end
    if MemoryAPI.HasMemory("skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    RemoveAll(skip_things)
    loop deserialise(load_buffer)
    Append(skip_things, @)
    end
    end
    load_buffer = ""
    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()
    end
    bool no_SprakAPI(string thing)
    return Connect(thing).HasFunction("") == 0
    end
  • replacement in skip.sprak at line 129
    [3.12520][3.12520:12564]()
    if character != "\"
    if character != '"'
    [3.12520]
    [3.12564]
    if !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
  • edit in skip.sprak at line 137
    [3.12587][3.12587:12634]()
    end
    else if escaped
    output += character
  • edit in skip.sprak at line 138
    [3.12653][3.12653:12698]()
    else if character == '\'
    escaped = true
  • replacement in skip.sprak at line 144
    [3.12757][3.12757:12840]()
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    end
    [3.12757]
    [3.12840]
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
  • replacement in skip.sprak at line 159
    [3.12938][3.12938:12974]()
    var deserialise_array(string input)
    [3.12938]
    [3.12974]
    array deserialise_array(string input)
  • edit in skip.sprak at line 161
    [3.12998]
    [3.12998]
    bool is_numeric = false
  • replacement in skip.sprak at line 176
    [3.13323][3.13323:13371]()
    bool is_numeric = false
    if character == ":"
    [3.13323]
    [3.13371]
    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 == ":"
  • edit in skip.sprak at line 276
    [3.14742][3.14742:15483]()
    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
  • edit in skip.sprak at line 280
    [3.15607][3.15607:15680]()
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in skip.sprak at line 282
    [3.15765]
    [3.15765]
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in skip.sprak at line 288
    [3.15860]
    [3.15860]
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
  • edit in skip.sprak at line 377
    [3.17658]
    [3.17658]
    is_numeric = false
  • edit in skip.sprak at line 405
    [3.18169][3.18169:18199]()
    if "" + first == "" + second
  • edit in skip.sprak at line 414
    [3.18369][3.18369:18374]()
    end
  • replacement in skip.sprak at line 431
    [3.18658][3.18658:18755]()
    bool has(array input, var test_element)
    loop element in input
    if equal(element, test_element)
    [3.18658]
    [3.18755]
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
  • edit in skip.sprak at line 438
    [3.18795][3.18795:19415]()
    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)
  • edit in skip.sprak at line 439
    [3.19419][3.19419:20327](),[3.20327][2.27:43]()
    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()
  • edit in skip.md at line 2
    [3.20389][3.20389:20390]()
  • edit in skip.md at line 5
    [3.20644][3.20644:20645]()
  • edit in skip.md at line 11
    [3.21479]
    [3.21479]
    ### Imports
    * serde.sprak
    * equality.sprak
    * array.sprak
    * `has`
  • replacement in skip.md at line 26
    [3.21634][3.21634:21741]()
    ```
    ## Imports
    * supply.sprak
    * `hardcoded_supply`
    * serde.sprak
    * equality.sprak
    * array.sprak
    * `has`
    [3.21634]
    ```
  • file addition: server.sprak (----------)
    [3.2]
    string KEY_NUMERIC_DATA = "numeric_data"
    void main()
    DisconnectAll()
    ClearText()
    string data_serialised = ""
    array data = []
    string load_buffer = ""
    number MemoryAPI = supply_unwrapped([], "LoadMemory")
    number FinanceAPI = supply_unwrapped([], "ChangeBalance")
    number WellspringAPI = supply_unwrapped([], "RegisterSeller")
    number HeartAPI = supply_unwrapped([], "SetNumericData")
    array things = []
    array data_points = []
    loop
    if MemoryAPI.HasMemory(KEY_NUMERIC_DATA)
    load_buffer = MemoryAPI.LoadMemory(KEY_NUMERIC_DATA)
    if data_serialised != load_buffer
    data_serialised = load_buffer
    data = deserialise(data_serialised)
    end
    things = GetIndexes(data)
    loop thing in things
    data_points = data[thing]
    loop key_data_point in GetIndexes(data_points)
    if key_data_point == "cash"
    FinanceAPI.SaveMemory(thing, data_points[key_data_point])
    else if key_data_point == "wellspring"
    WellspringAPI.RegisterSeller(thing, data_points[key_data_point])
    else
    HeartAPI.SetNumericData(thing, key_data_point, data_points[key_data_point])
    end
    end
    end
    end
    Sleep(1)
    end
    end
    main()
    # Imports
    ###############
    # serde.sprak #
    ###############
    string deserialise_string(string input)
    string output = ""
    bool escaped = false
    loop character in input
    if !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
    output += character
    escaped = false
    end
    end
    return output
    end
    bool is_digit(string input)
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    array deserialise_array(string input)
    array accumulator = []
    bool is_numeric = false
    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
    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
    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
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
    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
    is_numeric = false
    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)
    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
    ###############
    # array.sprak #
    ###############
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
    return true
    end
    end
    return false
    end
    ###############
    # types.sprak #
    ###############
    array Left(var input)
    return [false, input]
    end
    array Right(var input)
    return [true, input]
    end
    ################
    # supply.sprak #
    ################
    array supplier_of(array overrides, string function)
    string MemoryAPI_thing = "FinanceComputer"
    string TingrunnerAPI_thing = "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1"
    if HasIndex(overrides, "MemoryAPI")
    MemoryAPI_thing = overrides["MemoryAPI"]
    end
    if HasIndex(overrides, "TingrunnerAPI")
    TingrunnerAPI_thing = overrides["TingrunnerAPI"]
    end
    number MemoryAPI = Connect(MemoryAPI_thing)
    number TingrunnerAPI = Connect(TingrunnerAPI_thing)
    array skip_types = []
    loop ["floppy", "navnode", "bed", "point", "seat", "locker", "memory", "portal", "character", "map", "suitcase", "goods"]
    Append(skip_types, @)
    end
    array skip_things = []
    loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]
    Append(skip_things, @)
    end
    string load_buffer = ""
    if !HasIndex(overrides, "skip_types")
    if MemoryAPI.HasMemory("skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    RemoveAll(skip_types)
    loop deserialise(load_buffer)
    Append(skip_types, @)
    end
    end
    else
    RemoveAll(skip_types)
    loop overrides["skip_types"]
    Append(skip_types, @)
    end
    end
    if !HasIndex(overrides, "skip_things")
    if MemoryAPI.HasMemory("skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    RemoveAll(skip_things)
    loop deserialise(load_buffer)
    Append(skip_things, @)
    end
    end
    else
    RemoveAll(skip_things)
    loop overrides["skip_things"]
    Append(skip_things, @)
    end
    end
    if HasIndex(overrides, "more_skip_types")
    loop overrides["more_skip_types"]
    if !has(skip_types, @)
    Append(skip_types, @)
    end
    end
    end
    if HasIndex(overrides, "more_skip_things")
    loop overrides["more_skip_things"]
    if !has(skip_things, @)
    Append(skip_things, @)
    end
    end
    end
    if MemoryAPI.HasMemory(function)
    load_buffer = MemoryAPI.LoadMemory(function)
    if !has(skip_things, load_buffer)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(load_buffer))
    if Connect(load_buffer).HasFunction(function)
    return Right(load_buffer)
    end
    end
    end
    end
    load_buffer = ""
    loop room in TingrunnerAPI.GetAllRooms()
    loop thing in TingrunnerAPI.GetThingsInRoom(room)
    if !has(skip_things, thing)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(thing))
    if Connect(thing).HasFunction(function)
    MemoryAPI.SaveMemory(function, thing)
    return Right(thing)
    end
    end
    end
    end
    end
    return Left("`" + function + "` not found.")
    end
    array supply(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    if array_buffer[0]
    return Right(Connect(array_buffer[1]))
    else
    return Left(array_buffer[1])
    end
    end
    number supply_unwrapped(array overrides, string function)
    array array_buffer = supply(overrides, function)
    return array_buffer[1]
    end
  • file addition: server.md (----------)
    [3.2]
    # server.sprak
    Allows computers programmed with it to set the numeric data of things, as set by the `NUMERIC_DATA` variable in "drink.sprak".
    ## Usage
    * May fail if the `supply` function supplies a function from the same server, since `Name()` is not used to check this.
    ## Functions
    ### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
    * types.sprak
    * `Left`
    * `Right`
    * supply.sprak
    * `supplier_of`
    * `supply`
    * `supply_unwrapped`
  • replacement in serde.tests.sprak at line 5
    [3.21886][3.21886:21949]()
    if Count(first) == Count(second) && "" + first == "" + second
    [3.21886]
    [3.21949]
    if Count(first) == Count(second)
  • replacement in serde.tests.sprak at line 114
    [3.24730][3.24730:24744]()
    array a = []
    [3.24730]
    [3.24744]
    array a
    array b
    array c
    a = deserialise_array('{}')
    Append(tests, [a, []])
  • replacement in serde.tests.sprak at line 123
    [3.24874][3.24874:24994]()
    a = deserialise_array('{0:"a"}')
    Append(tests, [a, ["a"]])
    a = deserialise_array('{0:""}')
    Append(tests, [a, [""]])
    [3.24874]
    [3.24994]
    a = deserialise_array('{0:"abc"}')
    Append(tests, [a, ["abc"]])
  • replacement in serde.tests.sprak at line 127
    [3.25053][3.25053:25106]()
    a = deserialise_array('{}')
    Append(tests, [a, []])
    [3.25053]
    [3.25106]
    a = deserialise_array('{0:f,1:t}')
    Append(tests, [a, [false,true]])
    a = deserialise_array('{0:0,1:-273.15}')
    Append(tests, [a, [0,-273.15]])
    a = deserialise_array('{0:"abc",1:"def"}')
    Append(tests, [a, ["abc","def"]])
    a = deserialise_array('{0:{},1:{}}')
    Append(tests, [a, [[],[]]])
    a = deserialise_array('{f:f,t:t}')
    b = []
    b[false] = false
    b[true] = true
    Append(tests, [a, b])
    a = deserialise_array('{f:0,t:-273.15}')
    b = []
    b[false] = 0
    b[true] = -273.15
    Append(tests, [a, b])
    a = deserialise_array('{f:"abc",t:"def"}')
    b = []
    b[false] = "abc"
    b[true] = "def"
    Append(tests, [a, b])
    a = deserialise_array('{f:{},t:{}}')
    b = []
    b[false] = []
    b[true] = []
    Append(tests, [a, b])
    a = deserialise_array('{0:f,-273.15:t}')
    b = []
    b[0] = false
    b[-273.15] = true
    Append(tests, [a, b])
    a = deserialise_array('{0:0,-273.15:-273.15}')
    b = []
    b[0] = 0
    b[-273.15] = -273.15
    Append(tests, [a, b])
    a = deserialise_array('{0:"abc",-273.15:"def"}')
    b = []
    b[0] = "abc"
    b[-273.15] = "def"
    Append(tests, [a, b])
    a = deserialise_array('{0:{},-273.15:{}}')
    b = []
    b[0] = []
    b[-273.15] = []
    Append(tests, [a, b])
    a = deserialise_array('{"abc":f,"def":t}')
    b = []
    b["abc"] = false
    b["def"] = true
    Append(tests, [a, b])
    a = deserialise_array('{"abc":0,"def":-273.15}')
    b = []
    b["abc"] = 0
    b["def"] = -273.15
    Append(tests, [a, b])
    a = deserialise_array('{"abc":"abc","def":"def"}')
    b = []
    b["abc"] = "abc"
    b["def"] = "def"
    Append(tests, [a, b])
    a = deserialise_array('{"abc":{},"def":{}}')
    b = []
    b["abc"] = []
    b["def"] = []
    Append(tests, [a, b])
    a = deserialise_array('{"a":{"b":f}}')
    b = []
    c = []
    c["b"] = false
    b["a"] = c
    Append(tests, [a, b])
  • replacement in serde.sprak at line 61
    [3.26932][3.26932:26976]()
    if character != "\"
    if character != '"'
    [3.26932]
    [3.26976]
    if !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
  • edit in serde.sprak at line 69
    [3.26999][3.26999:27046]()
    end
    else if escaped
    output += character
  • edit in serde.sprak at line 70
    [3.27065][3.27065:27110]()
    else if character == '\'
    escaped = true
  • replacement in serde.sprak at line 76
    [3.27169][3.27169:27252]()
    number code = CharToInt(input)
    if code >= -49
    if code <= -40
    return true
    end
    [3.27169]
    [3.27252]
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
  • replacement in serde.sprak at line 91
    [3.27350][3.27350:27386]()
    var deserialise_array(string input)
    [3.27350]
    [3.27386]
    array deserialise_array(string input)
  • edit in serde.sprak at line 93
    [3.27410]
    [3.27410]
    bool is_numeric = false
  • replacement in serde.sprak at line 108
    [3.27735][3.27735:27783]()
    bool is_numeric = false
    if character == ":"
    [3.27735]
    [3.27783]
    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 == ":"
  • edit in serde.sprak at line 208
    [3.29154][3.29154:29895]()
    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
  • edit in serde.sprak at line 212
    [3.30019][3.30019:30092]()
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in serde.sprak at line 214
    [3.30177]
    [3.30177]
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
  • edit in serde.sprak at line 220
    [3.30272]
    [3.30272]
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
  • edit in serde.sprak at line 309
    [3.32070]
    [3.32070]
    is_numeric = false
  • replacement in serde.sprak at line 330
    [3.32441][2.71:75]()
    end
    [3.32441]
    end
  • edit in serde.md at line 2
    [3.32493][3.32493:32494]()
  • edit in serde.md at line 5
    [3.32542][3.32542:32543]()
  • replacement in serde.md at line 6
    [3.32566][3.32566:32662]()
    Returns the serialised form of input where `\` and `"` characters have been prepended with `\`.
    [3.32566]
    [3.32662]
    Returns the serialised form of a string input where `\` and `"` characters have been prepended with `\`.
  • replacement in serde.md at line 53
    [3.33993][3.33993:34047]()
    Determines if the input character is a numeric digit.
    [3.33993]
    [3.34047]
    Determines if the input character is a numeric digit. `CharToInt` isn't used as this isn't always available.
  • replacement in serde.md at line 100
    [3.35076][3.35076:35212]()
    * Replace recursions with iterations in:
    * `serialise_array` and `serialise`
    * Add an option to serialise numbers using more precision.
    [3.35076]
    * Handle failures during deserialisations by outputting `[true, parse]` or `[false, error]`.
    * Replace mutual recursions with iterations in:
    * `serialise_array` and `serialise`
  • file addition: screwdriver.sprak (----------)
    [3.2]
    array APIs = []
    Append(APIs, "arcade")
    Append(APIs, "door")
    Append(APIs, "floppy")
    Append(APIs, "internet")
    Append(APIs, "memory")
    main()
    void main()
    SetMaxTime(-2)
    SetMhz(500)
    loop APIs
    EnableAPI(@)
    end
    end
  • file addition: screwdriver.md (----------)
    [3.2]
    # screwdriver.sprak
    Allows screwdrivers programmed with it, when used on computers, to set their execution times to infinite, their clockspeed to 500 MHz, and enables the "arcade", "door", "floppy", "internet" and "memory" APIs on them.
  • file addition: modifier.sprak (----------)
    [3.2]
    string KEY_COPY_TARGET = "copy_target"
    bool Allow(string target, number level)
    DisconnectAll()
    number connection_target = Connect(target)
    number TingrunnerAPI = supply_unwrapped([], "GetTypeOfThing")
    number MemoryAPI = supply_unwrapped([], "LoadMemory")
    array overrides = []
    overrides["more_skip_types"] = ["key"]
    number DoorAPI = supply_unwrapped(overrides, "Lock")
    overrides["more_skip_types"] = ["taser"]
    number connection_extractor = supply_unwrapped(overrides, "CopyToClipboard")
    if TingrunnerAPI.GetTypeOfThing(target) == "door"
    if MemoryAPI.LoadMemory("lock " + target)
    DoorAPI.Unlock(target)
    MemoryAPI.SaveMemory("lock " + target, false)
    connection_target.Say(target + " unlocked.")
    else
    DoorAPI.Lock(target)
    MemoryAPI.SaveMemory("lock " + target, true)
    connection_target.Say(target + " locked.")
    end
    end
    if MemoryAPI.HasMemory(KEY_COPY_TARGET)
    if MemoryAPI.LoadMemory(KEY_COPY_TARGET)
    connection_extractor.CopyToClipboard(target)
    end
    end
    DisconnectAll()
    return true
    end
    ###############
    # serde.sprak #
    ###############
    string deserialise_string(string input)
    string output = ""
    bool escaped = false
    loop character in input
    if !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
    output += character
    escaped = false
    end
    end
    return output
    end
    bool is_digit(string input)
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    array deserialise_array(string input)
    array accumulator = []
    bool is_numeric = false
    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
    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
    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
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
    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
    is_numeric = false
    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)
    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
    ###############
    # array.sprak #
    ###############
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
    return true
    end
    end
    return false
    end
    ###############
    # types.sprak #
    ###############
    array Left(var input)
    return [false, input]
    end
    array Right(var input)
    return [true, input]
    end
    ################
    # supply.sprak #
    ################
    array supplier_of(array overrides, string function)
    string MemoryAPI_thing = "FinanceComputer"
    string TingrunnerAPI_thing = "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1"
    if HasIndex(overrides, "MemoryAPI")
    MemoryAPI_thing = overrides["MemoryAPI"]
    end
    if HasIndex(overrides, "TingrunnerAPI")
    TingrunnerAPI_thing = overrides["TingrunnerAPI"]
    end
    number MemoryAPI = Connect(MemoryAPI_thing)
    number TingrunnerAPI = Connect(TingrunnerAPI_thing)
    array skip_types = []
    loop ["floppy", "navnode", "bed", "point", "seat", "locker", "memory", "portal", "character", "map", "suitcase", "goods"]
    Append(skip_types, @)
    end
    array skip_things = []
    loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]
    Append(skip_things, @)
    end
    string load_buffer = ""
    if !HasIndex(overrides, "skip_types")
    if MemoryAPI.HasMemory("skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    RemoveAll(skip_types)
    loop deserialise(load_buffer)
    Append(skip_types, @)
    end
    end
    else
    RemoveAll(skip_types)
    loop overrides["skip_types"]
    Append(skip_types, @)
    end
    end
    if !HasIndex(overrides, "skip_things")
    if MemoryAPI.HasMemory("skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    RemoveAll(skip_things)
    loop deserialise(load_buffer)
    Append(skip_things, @)
    end
    end
    else
    RemoveAll(skip_things)
    loop overrides["skip_things"]
    Append(skip_things, @)
    end
    end
    if HasIndex(overrides, "more_skip_types")
    loop overrides["more_skip_types"]
    if !has(skip_types, @)
    Append(skip_types, @)
    end
    end
    end
    if HasIndex(overrides, "more_skip_things")
    loop overrides["more_skip_things"]
    if !has(skip_things, @)
    Append(skip_things, @)
    end
    end
    end
    if MemoryAPI.HasMemory(function)
    load_buffer = MemoryAPI.LoadMemory(function)
    if !has(skip_things, load_buffer)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(load_buffer))
    if Connect(load_buffer).HasFunction(function)
    return Right(load_buffer)
    end
    end
    end
    end
    load_buffer = ""
    loop room in TingrunnerAPI.GetAllRooms()
    loop thing in TingrunnerAPI.GetThingsInRoom(room)
    if !has(skip_things, thing)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(thing))
    if Connect(thing).HasFunction(function)
    MemoryAPI.SaveMemory(function, thing)
    return Right(thing)
    end
    end
    end
    end
    end
    return Left("`" + function + "` not found.")
    end
    array supply(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    if array_buffer[0]
    return Right(Connect(array_buffer[1]))
    else
    return Left(array_buffer[1])
    end
    end
    number supply_unwrapped(array overrides, string function)
    array array_buffer = supply(overrides, function)
    return array_buffer[1]
    end
  • file addition: modifier.md (----------)
    [3.2]
    # modifier.sprak
    Allows any modifier programmed with it to hack any hackable object as well as toggle the lock state of any door hacked with it.
    ## Usage
    * The toggle states for each door are stored in a computer's memory.
    * May fail if the `supply` function supplies a function from the same modifier, since `Name()` is not used to check this.
    ## Functions
    ### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
    * types.sprak
    * `Left`
    * `Right`
    * supply.sprak
    * `supplier_of`
    * `supply`
    * `supply_unwrapped`
  • edit in equality.sprak at line 1
    [3.35252]
    [3.35253]
    ##################
    # equality.sprak #
    ##################
  • edit in equality.sprak at line 6
    [3.35331][3.35331:35361]()
    if "" + first == "" + second
  • edit in equality.sprak at line 15
    [3.35531][3.35531:35536]()
    end
  • replacement in equality.md at line 1
    [3.35807][3.35808:35823]()
    # serde.sprak
    [3.35807]
    [3.35823]
    # equality.sprak
  • edit in equality.md at line 5
    [3.35872][3.35872:35873]()
  • file addition: drink.sprak (----------)
    [3.2]
    string MOVE_DATA = '' # '{"Sebastian_inventory":{"things":{0:"RustyModder",1:"Typer1Modifier",2:"Screwdriver_ScrewDriver"}}}'
    bool WILL_TOGGLE_MODIFIER_COPY = false
    array WHATS_IN = []
    array WHERES = []
    string NUMERIC_DATA = '' # '{"Sebastian":{"cash":999,"walkSpeed":10,"sleepiness":0,"wellspring":10,"corruption":0,"drunkenness":0,"smelliness":0}}'
    bool COPYING = false
    bool SAVING = false
    string KEY_COPY_TARGET = "copy_target"
    string KEY_NUMERIC_DATA = "numeric_data"
    string KEY_SAY = "output_drink"
    void main()
    DisconnectAll()
    array results = []
    array outputs = []
    if MOVE_DATA != ""
    loop move(MOVE_DATA)
    Append(results, @)
    end
    end
    if Count(WHERES) > 0
    loop get_rooms_of(WHERES)
    Append(results, @)
    end
    end
    if NUMERIC_DATA != ""
    ARRAY_BUFFER = set_data(NUMERIC_DATA, KEY_NUMERIC_DATA)
    Append(results, ARRAY_BUFFER)
    end
    if Count(results) > 0
    outputs = format_results(results)
    end
    if Count(WHATS_IN) > 0
    STRING_BUFFER = get_things_in(WHATS_IN)
    Append(outputs, STRING_BUFFER)
    end
    if WILL_TOGGLE_MODIFIER_COPY
    STRING_BUFFER = toggle_modifier_copy(KEY_COPY_TARGET)
    Append(outputs, STRING_BUFFER)
    end
    if Count(outputs) > 0
    say(concatenate(outputs, " "), COPYING, SAVING, KEY_SAY)
    end
    DisconnectAll()
    end
    array ARRAY_BUFFER
    array CONNECTION_CACHE = []
    array SUPPLIER_CACHE = []
    string STRING_BUFFER
    main()
    # Functions
    string concatenate(array strings, string separator)
    string output = ""
    loop strings
    output += @ + separator
    end
    return output
    end
    string format_result(array either)
    if either[0]
    return either[1]
    end
    return "ERROR: " + either[1]
    end
    array format_results(array results)
    array output = []
    loop results
    Append(output, format_result(@))
    end
    return output
    end
    string room_of(string thing)
    if !HasIndex(CONNECTION_CACHE, "GetRoom")
    array overrides = []
    overrides["more_skip_types"] = ["drink"]
    CONNECTION_CACHE["GetRoom"] = supply_unwrapped(overrides, "GetRoom")
    end
    return CONNECTION_CACHE["GetRoom"].GetRoom(thing)
    end
    bool thing_exists(string thing)
    return room_of(thing) != ""
    end
    array invalid_thing(string thing)
    return Left('"' + thing + '" is not a valid thing.')
    end
    number cached_connection(string function)
    if HasIndex(CONNECTION_CACHE, function)
    return CONNECTION_CACHE[function]
    end
    CONNECTION_CACHE[function] = supply_unwrapped([], function)
    return CONNECTION_CACHE[function]
    end
    string cached_supplier(string function)
    if HasIndex(SUPPLIER_CACHE, function)
    return SUPPLIER_CACHE[function]
    end
    SUPPLIER_CACHE[function] = supplier_of_unwrapped([], function)
    return SUPPLIER_CACHE[function]
    end
    bool is_person(string person)
    return cached_connection("GetTypeOfThing").GetTypeOfThing(person) == "character"
    end
    string move_to_thing(string destination, array move_these)
    array output = []
    loop move_these
    if is_person(@)
    string TingrunnerAPI_thing = cached_supplier("MovePerson")
    cached_connection("SetPosition").SetPosition(TingrunnerAPI_thing, @)
    Connect(TingrunnerAPI_thing).MovePerson(@, destination)
    else
    cached_connection("SetPosition").SetPosition(@, destination)
    end
    Append(output, 'Moved "' + @ + '" to "' + destination + '".')
    end
    return concatenate(output, " ")
    end
    array move(string serialised_schedule)
    array schedule = deserialise(serialised_schedule)
    array destinations = GetIndexes(schedule)
    loop destination in destinations
    if thing_exists(destination)
    array task = schedule[destination]
    loop task["things"]
    if !thing_exists(@)
    return [invalid_thing(@)]
    end
    end
    else
    array things = cached_connection("GetThingsInRoom").GetThingsInRoom(destination)
    number count_things = Count(things)
    if count_things > 0
    array task = schedule[destination]
    number index = 0
    if HasIndex(task, "index")
    index = task["index"]
    end
    if index < 0
    return [Left("`index` should be >= 0.")]
    else if index - Int(index) != 0
    return [Left("`index` should be an integer.")]
    else if index + 1 > count_things
    return [Left("" + (count_things - 1) + 'is the max `index` value for "' + destination + '".')]
    else
    loop task["things"]
    if !thing_exists(@)
    return [invalid_thing(@)]
    end
    end
    end
    else
    return [Left('"' + destination + '" is not a valid destination.')]
    end
    end
    end
    array output = []
    loop destination in destinations
    array task = schedule[destination]
    if thing_exists(destination)
    ARRAY_BUFFER = Right(move_to_thing(destination, task["things"]))
    Append(output, ARRAY_BUFFER)
    else
    array things = cached_connection("GetThingsInRoom").GetThingsInRoom(destination)
    number index = 0
    if HasIndex(task, "index")
    index = task["index"]
    end
    ARRAY_BUFFER = Right(move_to_thing(things[index], task["things"]))
    Append(output, ARRAY_BUFFER)
    end
    end
    return output
    end
    string get_things_in(array rooms)
    array outputs = []
    number TingrunnerAPI = cached_connection("GetThingsInRoom")
    loop rooms
    Append(outputs, 'Serialised list of things in "' + @ + '": ' + "'" + serialise(TingrunnerAPI.GetThingsInRoom(@)) + "'.")
    end
    return concatenate(outputs, " ")
    end
    array get_rooms_of(array things)
    array outputs = []
    loop things
    if !thing_exists(@)
    return [invalid_thing(@)]
    end
    end
    loop things
    Append(outputs, Right('"' + @ + '" is in "' + room_of(@) + '".'))
    end
    return outputs
    end
    string toggle_modifier_copy(string key)
    string MemoryAPI_thing = cached_supplier("SaveMemory")
    number MemoryAPI = Connect(MemoryAPI_thing)
    if !MemoryAPI.HasMemory(key)
    MemoryAPI.SaveMemory(key, false)
    end
    bool copying_target = MemoryAPI.LoadMemory(key)
    MemoryAPI.SaveMemory(key, !copying_target)
    return 'The value accessed by the key "' + key + '" on the server "' + MemoryAPI_thing + '" was set to `' + (!copying_target) + "`."
    end
    array set_data(string serialised_data, string key)
    array data = deserialise(serialised_data)
    array things = GetIndexes(data)
    loop thing in things
    if !thing_exists(thing)
    return invalid_thing(thing)
    end
    array data_points = data[thing]
    loop key_data_point in GetIndexes(data_points)
    if Type(data_points[key_data_point]) != "number"
    return Left("`" + thing + "[" + key_data_point + "]` should be set to a numeric value.")
    end
    if key_data_point == "cash" || key_data_point == "wellspring"
    if !is_person(thing)
    return Left('"' + thing + '" is not a valid person.')
    end
    end
    end
    end
    string MemoryAPI_thing = cached_supplier("SaveMemory")
    Connect(MemoryAPI_thing).SaveMemory(key, serialised_data)
    return Right('The value accessed by the key "' + key + '" on the server "' + MemoryAPI_thing + '" was set to "' + serialised_data + '".')
    end
    void say(string output, bool copying, bool saving, string key)
    if output != ""
    if copying
    if !HasIndex(CONNECTION_CACHE, "CopyToClipboard")
    array overrides = []
    overrides["more_skip_types"] = ["taser"]
    CONNECTION_CACHE["CopyToClipboard"] = supply_unwrapped(overrides, "CopyToClipboard")
    end
    if saving
    CONNECTION_CACHE["CopyToClipboard"].CopyToClipboard(output)
    string MemoryAPI_thing = cached_supplier("SaveMemory")
    Connect(MemoryAPI_thing).SaveMemory(key, output)
    Say('The following was copied to the clipboard and saved to "' + MemoryAPI_thing + '" using the key "' + key + '": ' + output)
    else
    CONNECTION_CACHE["CopyToClipboard"].CopyToClipboard(output)
    Say("Copied: " + output)
    end
    else if saving
    string MemoryAPI_thing = cached_supplier("SaveMemory")
    Connect(MemoryAPI_thing).SaveMemory(key, output)
    Say('The following was saved to "' + MemoryAPI_thing + '" using the key "' + key + '": ' + output)
    else
    Say(output)
    end
    end
    end
    # Imports
    ###############
    # 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)
    if Type(key) != "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 !escaped
    if character == '\'
    escaped = true
    else if character != '"'
    output += character
    end
    else
    output += character
    escaped = false
    end
    end
    return output
    end
    bool is_digit(string input)
    array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    loop digits
    if input == @
    return true
    end
    end
    return false
    end
    # Types:
    # * 0: none
    # * 1: bool
    # * 2: number
    # * 3: string
    # * 4: array
    array deserialise_array(string input)
    array accumulator = []
    bool is_numeric = false
    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
    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
    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
    if key_type == 2
    Append(contexts, [accumulator, key_type, key_number])
    else if key_type == 3
    Append(contexts, [accumulator, key_type, key_string])
    else if key_type == 0
    Append(contexts, [accumulator, key_type])
    else
    Append(contexts, [accumulator, key_type, key_bool])
    end
    accumulator = []
    is_numeric = false
    in_string = false
    escaped = false
    in_value = false
    buffer = ""
    key_type = 0
    key_bool = false
    key_number = 0
    key_string = ""
    value_type = 0
    value_bool = false
    value_number = 0
    value_string = ""
    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
    is_numeric = false
    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)
    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
    ###############
    # array.sprak #
    ###############
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
    return true
    end
    end
    return false
    end
    ###############
    # types.sprak #
    ###############
    array Left(var input)
    return [false, input]
    end
    array Right(var input)
    return [true, input]
    end
    ################
    # supply.sprak #
    ################
    array supplier_of(array overrides, string function)
    string MemoryAPI_thing = "FinanceComputer"
    string TingrunnerAPI_thing = "PoliceOfficeInterior_MinistryOfficeWorkstationComputer_1"
    if HasIndex(overrides, "MemoryAPI")
    MemoryAPI_thing = overrides["MemoryAPI"]
    end
    if HasIndex(overrides, "TingrunnerAPI")
    TingrunnerAPI_thing = overrides["TingrunnerAPI"]
    end
    number MemoryAPI = Connect(MemoryAPI_thing)
    number TingrunnerAPI = Connect(TingrunnerAPI_thing)
    array skip_types = []
    loop ["floppy", "navnode", "bed", "point", "seat", "locker", "memory", "portal", "character", "map", "suitcase", "goods"]
    Append(skip_types, @)
    end
    array skip_things = []
    loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]
    Append(skip_things, @)
    end
    string load_buffer = ""
    if !HasIndex(overrides, "skip_types")
    if MemoryAPI.HasMemory("skip_types")
    load_buffer = MemoryAPI.LoadMemory("skip_types")
    RemoveAll(skip_types)
    loop deserialise(load_buffer)
    Append(skip_types, @)
    end
    end
    else
    RemoveAll(skip_types)
    loop overrides["skip_types"]
    Append(skip_types, @)
    end
    end
    if !HasIndex(overrides, "skip_things")
    if MemoryAPI.HasMemory("skip_things")
    load_buffer = MemoryAPI.LoadMemory("skip_things")
    RemoveAll(skip_things)
    loop deserialise(load_buffer)
    Append(skip_things, @)
    end
    end
    else
    RemoveAll(skip_things)
    loop overrides["skip_things"]
    Append(skip_things, @)
    end
    end
    if HasIndex(overrides, "more_skip_types")
    loop overrides["more_skip_types"]
    if !has(skip_types, @)
    Append(skip_types, @)
    end
    end
    end
    if HasIndex(overrides, "more_skip_things")
    loop overrides["more_skip_things"]
    if !has(skip_things, @)
    Append(skip_things, @)
    end
    end
    end
    if MemoryAPI.HasMemory(function)
    load_buffer = MemoryAPI.LoadMemory(function)
    if !has(skip_things, load_buffer)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(load_buffer))
    if Connect(load_buffer).HasFunction(function)
    return Right(load_buffer)
    end
    end
    end
    end
    load_buffer = ""
    loop room in TingrunnerAPI.GetAllRooms()
    loop thing in TingrunnerAPI.GetThingsInRoom(room)
    if !has(skip_things, thing)
    if !has(skip_types, TingrunnerAPI.GetTypeOfThing(thing))
    if Connect(thing).HasFunction(function)
    MemoryAPI.SaveMemory(function, thing)
    return Right(thing)
    end
    end
    end
    end
    end
    return Left("`" + function + "` not found.")
    end
    string supplier_of_unwrapped(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    return array_buffer[1]
    end
    array supply(array overrides, string function)
    array array_buffer = supplier_of(overrides, function)
    if array_buffer[0]
    return Right(Connect(array_buffer[1]))
    else
    return Left(array_buffer[1])
    end
    end
    number supply_unwrapped(array overrides, string function)
    array array_buffer = supply(overrides, function)
    return array_buffer[1]
    end
  • file addition: drink.md (----------)
    [3.2]
    # drink.sprak
    Allows any drink programmed with it when drunk to:
    * Set the location of things.
    * Get the location of things.
    * Get the names of things in a room.
    * Set the numeric data of things, e.g., their cash balance, sleepiness, walking speed, etc.
    * Copy or save any outputs.
    ## Usage
    * May fail if the `supply` function supplies a function from the same modifier, since `Name()` is not used to check this.
    The following global variables at the top of the program are intended to be set by the user:
    ### `MOVE_THESE`
    Accepts an `string` representing a serialised `array` in the format:
    ```
    {DESTINATION_THING:{"things":{0:THING_A,1:THING_B,...}},DESTINATION_ROOM:{"index":NATURAL_NUMBER,"things":{0:THING_C,1:THING_D,...}},...}
    ```
    Representing:
    * `DESTINATION_THING` - A `string` representing the name of a thing that things `THING_A`, `THING_B`, ... will be moved to.
    * `THING_A`, `THING_B`, ... - `string`s representing the names of things that things that will be moved to `DESTINATION_THING`.
    * `DESTINATION_ROOM` - A `string` representing the name of a room that things `THING_C`, `THING_D`, ... will be moved to.
    * `NATURAL_NUMBER` - An integer `number` >= 0 representing the index of a thing in `DESTINATION_ROOM`.
    * `THING_C`, `THING_D`, ... - `string`s representing the names of things that things that will be moved to the thing in `DESTINATION_ROOM` indexed by `NATURAL_NUMBER`.
    The `"index"` attribute is optional and will default to `0` if unset.
    #### Example
    ```sprak
    string MOVE_DATA = '{"Sebastian_inventory":{"things":{0:"RustyModder",1:"Typer1Modifier",2:"Screwdriver_ScrewDriver"}}}'
    ```
    ### `WILL_TOGGLE_MODIFIER_COPY`
    If set to `true`, drinking will toggle the `bool` value in memory accessed by the key `KEY_COPY_TARGET`, which determines if a modifier programmed with "modifier.sprak" will copy the name of its target.
    ### `WHATS_IN`
    Accepts an `array` containing strings, each representing the name of a room. The names of the contents of these rooms are outputted after drinking.
    ### `WHERES`
    Accepts an array containing strings, each representing the name of a thing whose current locations are outputted after drinking.
    ### `NUMERIC_DATA`
    Accepts an `string` representing a serialised `array` in the format:
    ```
    {THING:{DATA_POINT:NUMBER,...},...}
    ```
    Representing:
    * `THING` - A `string` representing the name of a thing whose numeric data will be set.
    * `DATA_POINT` - A `string` representing a data point whose value will be set. Known valid values are "cash", "wellspring", "walkSpeed", "sleepiness", "corruption", "drunkenness", "smelliness", "charisma", "happiness", "supremacy".
    * `NUMBER` - A `number` representing the value that `DATA_POINT` will be set to.
    After drinking, the value of `NUMERIC_DATA` will be saved to memory, to be accessed by servers programmed with "server.sprak" which will use the value to set the data every tick of their main loop.
    #### Example
    ```sprak
    string NUMERIC_DATA = '{"Sebastian":{"cash":999,"walkSpeed":10,"sleepiness":0,"wellspring":10,"corruption":0,"drunkenness":0,"smelliness":0},"Babcia":{"supremacy":9001}}'
    ```
    ### `COPYING`
    If set to `true`, causes outputs to be copied to the clipboard after drinking.
    ### `SAVING`
    If set to `true`, causes outputs to be saved after drinking.
    ### `KEY_COPY_TARGET`
    A `string` representing the key used to access the memory value determining whether a modifier programmed with "modifier.sprak" will copy its target.
    ### `KEY_NUMERIC_DATA`
    A `string` representing the key used to access the memory value determining the values that a modifier programmed with "server.sprak" will set.
    ### `KEY_SAY`
    A `string` representing the key used to access the memory value that will store the outputs of the program.
    ## Functions
    ### Imports
    * serde.sprak
    * `deserialise`
    * equality.sprak
    * array.sprak
    * `has`
    * types.sprak
    * `Left`
    * `Right`
    * supply.sprak
    * `supplier_of`
    * `supplier_of_unwrapped`
    * `supply`
    * `supply_unwrapped`
    ## TODO
    * Handle invalid inputs for `get_things_in`.
    * Return early if any results are left/errors.
  • replacement in array.sprak at line 4
    [3.37018][3.37018:37095]()
    bool has(var elem, array arr)
    loop element in arr
    if equal(element, elem)
    [3.37018]
    [3.37095]
    bool has(array arr, var element)
    loop arr
    if equal(@, element)
  • edit in array.sprak at line 12
    [3.37139]
    array push(array arr, var element)
    array output = []
    loop arr
    Append(output, @)
    end
    Append(output, element)
    return output
    end
  • replacement in array.md at line 1
    [3.37173][3.37174:37189]()
    # serde.sprak
    [3.37173]
    [3.37189]
    # array.sprak
  • edit in array.md at line 5
    [3.37229]
    [3.37229]
    ### Imports
    * equality.sprak
    * `equal_array`
    * `equal`
  • replacement in array.md at line 13
    [3.37294][3.37294:37317]()
    `A -> array A -> bool`
    [3.37294]
    [3.37317]
    `[A] -> A -> bool`
  • edit in array.md at line 15
    [3.37332][3.37332:37367]()
    * `elem`: The value to search for.
  • edit in array.md at line 16
    [3.37396]
    [3.37396]
    * `element`: The value to search for.
  • replacement in array.md at line 21
    [3.37430][3.37430:37488]()
    #### Imports
    * equality.sprak
    * `equal_array`
    * `equal`
    [3.37430]
    ### `push`
    Return a new array containing a new element along with the elements of an input array. Exists because `Append` on `array` types [don't work properly](https://steamcommunity.com/app/400110/discussions/0/2992043384032764071/).
    #### Type
    `[A] -> A -> [A]`
    #### Arguments
    * `arr`: Array to get the elements of.
    * `element`: The element to add to the new array.
    #### Examples
    ```sprak
    # TODO
    ```
  • edit in README.md at line 3
    [3.37650][3.37650:37655]()
    ---
  • edit in README.md at line 5
    [3.37665][3.37665:37835]()
    * `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.
  • replacement in README.md at line 6
    [3.38043][3.38043:38048]()
    ---
    [3.38043]
    [3.38048]
    * The deserialisation machinery in "serde.sprak" don't currently have any error-handling for bad inputs, so ensure all inputs to these are correct.
    * `bool` operators in Sprak [don't short-circuit](https://steamcommunity.com/app/400110/discussions/0/523898291507887095/). Unconcise usage of conditionals in this project may have been used to emulate short-circuiting `bool` operators.
    * `Append` on `array` types [don't work properly](https://steamcommunity.com/app/400110/discussions/0/2992043384032764071/) and only works when the array started as an empty array and hasn't been set to a pre-populated one.
  • edit in .ignore at line 3
    [3.40070]
    else_heart_break.code-workspace