S7BXWG4QQMJ6M4XDUNDLJGD4BXB4QVZKXWSHXXVGKMNDWB5WV5LQC ################ types.sprak ################array Left(var input)return [false, input]endarray Right(var input)return [true, input]end
# types.sprakLibrary 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```
bool is_numeric = falseif character == ":"
if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"
else if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"end
var MemoryAPIif MemoryAPI_thing != nameMemoryAPI = Connect(MemoryAPI_thing)elsereturn [false, "MemoryAPI unavailable."]
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, @)
var TingrunnerAPIif TingrunnerAPI_thing != nameTingrunnerAPI = Connect(TingrunnerAPI_thing)elsereturn [false, "TingrunnerAPI unavailable."]
array skip_things = []loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]Append(skip_things, @)
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
string load_buffer = ""
load_buffer = MemoryAPI.LoadMemory("skip_types")if load_buffer != 0skip_types = deserialise(load_buffer)
if MemoryAPI.HasMemory("skip_types")load_buffer = MemoryAPI.LoadMemory("skip_types")RemoveAll(skip_types)loop deserialise(load_buffer)Append(skip_types, @)end
load_buffer = MemoryAPI.LoadMemory("skip_things")if load_buffer != 0skip_things = deserialise(load_buffer)
if MemoryAPI.HasMemory("skip_things")load_buffer = MemoryAPI.LoadMemory("skip_things")RemoveAll(skip_things)loop deserialise(load_buffer)Append(skip_things, @)end
load_buffer = MemoryAPI.LoadMemory(function)if load_buffer != 0if load_buffer != nameif !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]
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)endend
if thing != nameif !has(thing, skip_things)if !has(TingrunnerAPI.GetTypeOfThing(thing), skip_types)var connection = Connect(thing)if connection.HasFunction(function)
if !has(skip_things, thing)if !has(skip_types, TingrunnerAPI.GetTypeOfThing(thing))if Connect(thing).HasFunction(function)
return [false, "`" + function + "` not found."]
return Left("`" + function + "` not found.")endstring supplier_of_unwrapped(array overrides, string function)array array_buffer = supplier_of(overrides, function)return array_buffer[1]endarray supply(array overrides, string function)array array_buffer = supplier_of(overrides, function)if array_buffer[0]return Right(Connect(array_buffer[1]))elsereturn Left(array_buffer[1])endendnumber supply_unwrapped(array overrides, string function)array array_buffer = supply(overrides, function)return array_buffer[1]
### 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```sprakarray array_buffer = supplier_of([], "IsNight")string supplier = array_buffer[1]Say(Connect(supplier).IsNight())```
### `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```sprakstring supplier = supplier_of_unwrapped([], "IsNight")Say(Connect(supplier).IsNight())```
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.
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.
`["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> [true, connection] | [false, string]`
`["MemoryAPI"?: string, "TingrunnerAPI"?: string, "skip_types"?: [string], "skip_things"?: [string], "more_skip_types"?: [string], "more_skip_things"?: [string]] -> string -> Either(string, number)`
#### Imports* serde.sprak* `deserialise`* equality.sprak* array.sprak* `has`
### `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```sprakstring connection = supply_unwrapped([], "IsNight")Say(connection.IsNight())```
DisconnectAll()
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, @)endendif MemoryAPI.HasMemory("skip_things")load_buffer = MemoryAPI.LoadMemory("skip_things")RemoveAll(skip_things)loop deserialise(load_buffer)Append(skip_things, @)endendload_buffer = ""bool seen_last_thing = falsestring last_thing = ""number number_buffer = Count(skip_things)if number_buffer > 0last_thing = skip_things[number_buffer - 1]elseseen_last_thing = trueendloop room in TingrunnerAPI.GetAllRooms()loop thing in TingrunnerAPI.GetThingsInRoom(room)if seen_last_thingstring thing_type = TingrunnerAPI.GetTypeOfThing(thing)if thing != nameif !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))endRemove(skip_things, Count(skip_things) - 1)endendendelse if thing == last_thingseen_last_thing = trueendendendMemoryAPI.SaveMemory("skip_things", serialise(skip_things))Say("Done.")DisconnectAll()endbool no_SprakAPI(string thing)return Connect(thing).HasFunction("") == 0end
bool is_numeric = falseif character == ":"
if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"
else if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"end
end############## Functions ##############bool no_SprakAPI(string thing)return Connect(thing).HasFunction("") == 0end######### 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 != 0skip_types = deserialise(load_buffer)endload_buffer = MemoryAPI.LoadMemory("skip_things")if load_buffer != 0skip_things = deserialise(load_buffer)
load_buffer = 0bool seen_last_thing = falsestring last_thing = ""number number_buffer = Count(skip_things)if number_buffer > 0last_thing = skip_things[number_buffer - 1]elseseen_last_thing = trueendloop room in TingrunnerAPI.GetAllRooms()loop thing in TingrunnerAPI.GetThingsInRoom(room)if seen_last_thingstring thing_type = TingrunnerAPI.GetTypeOfThing(thing)if thing != nameif !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))endRemove(skip_things, Count(skip_things) - 1)endendendelse if thing == last_thingseen_last_thing = trueendendendMemoryAPI.SaveMemory("skip_things", serialise(skip_things))Say("Done.")DisconnectAll()
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 = []loopif MemoryAPI.HasMemory(KEY_NUMERIC_DATA)load_buffer = MemoryAPI.LoadMemory(KEY_NUMERIC_DATA)if data_serialised != load_bufferdata_serialised = load_bufferdata = deserialise(data_serialised)endthings = GetIndexes(data)loop thing in thingsdata_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])elseHeartAPI.SetNumericData(thing, key_data_point, data_points[key_data_point])endendendendSleep(1)endendmain()# Imports################ serde.sprak ################string deserialise_string(string input)string output = ""bool escaped = falseloop character in inputif !escapedif character == '\'escaped = trueelse if character != '"'output += characterendelseoutput += characterescaped = falseendendreturn outputendbool is_digit(string input)array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]loop digitsif input == @return trueendendreturn falseend# Types:# * 0: none# * 1: bool# * 2: number# * 3: string# * 4: arrayarray deserialise_array(string input)array accumulator = []bool is_numeric = falsebool in_string = falsebool escaped = falsebool in_value = falsestring buffer = ""number key_type = 0bool key_bool = falsenumber key_number = 0string key_string = ""number value_type = 0bool value_bool = falsenumber value_number = 0string value_string = ""array contexts = []loop character in inputif character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"if !in_stringin_value = trueif key_type == 2key_number = bufferbuffer = ""endelse if in_valuevalue_string += ":"elsekey_string += ":"endelse if character == ","if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendin_value = falsebuffer = ""key_string = ""value_string = ""else if in_valuevalue_string += ","elsekey_string += ","endelse if is_digit(character)is_numeric = trueelse if character == "."is_numeric = trueelse if character == "-"is_numeric = trueelse if character == "{"if !in_stringif key_type == 2Append(contexts, [accumulator, key_type, key_number])else if key_type == 3Append(contexts, [accumulator, key_type, key_string])else if key_type == 0Append(contexts, [accumulator, key_type])elseAppend(contexts, [accumulator, key_type, key_bool])endaccumulator = []is_numeric = falsein_string = falseescaped = falsein_value = falsebuffer = ""key_type = 0key_bool = falsekey_number = 0key_string = ""value_type = 0value_bool = falsevalue_number = 0value_string = ""elsevalue_string += "{"endelse if character == "}"if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendarray last_context = contexts[Count(contexts) - 1]array last_accumulator = last_context[0]number last_key_type = last_context[1]if last_key_type != 0last_accumulator[last_context[2]] = accumulatorelsereturn accumulatorendaccumulator = last_accumulatorvalue_type = 4Remove(contexts, Count(contexts) - 1)elsevalue_string += "}"endelse if character == "\"if !escapedescaped = trueelseescaped = falseif in_valuevalue_string += "\"elsekey_string += "\"endendelse if in_valuevalue_string += characterelsekey_string += characterendif is_numericif !in_stringbuffer += characterif in_valuevalue_type = 2elsekey_type = 2endelse if in_valuevalue_string += characterelsekey_string += characterendis_numeric = falseendendendvar deserialise(string input)if input[0] == "{"return deserialise_array(input)else if is_digit(input[0])number output = inputreturn outputelse if input[0] == "-"number output = inputreturn outputelse if input[0] == '"'return deserialise_string(input)else if input == "t"return trueelse if input == "f"return falseendend################### equality.sprak ###################bool equal_array(array first, array second)if Count(first) == Count(second)loop key in GetIndexes(first)if !HasIndex(second, key)return falseelse if !equal(first[key], second[key])return falseendendreturn trueendreturn falseendbool equal(var first, var second)string type_first = Type(first)if type_first == Type(second)if type_first != "array"return first == secondendreturn equal_array(first, second)endreturn falseend################ array.sprak ################bool has(array arr, var element)loop arrif equal(@, element)return trueendendreturn falseend################ types.sprak ################array Left(var input)return [false, input]endarray 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"]endif HasIndex(overrides, "TingrunnerAPI")TingrunnerAPI_thing = overrides["TingrunnerAPI"]endnumber 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, @)endarray skip_things = []loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]Append(skip_things, @)endstring 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, @)endendelseRemoveAll(skip_types)loop overrides["skip_types"]Append(skip_types, @)endendif !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, @)endendelseRemoveAll(skip_things)loop overrides["skip_things"]Append(skip_things, @)endendif HasIndex(overrides, "more_skip_types")loop overrides["more_skip_types"]if !has(skip_types, @)Append(skip_types, @)endendendif HasIndex(overrides, "more_skip_things")loop overrides["more_skip_things"]if !has(skip_things, @)Append(skip_things, @)endendendif 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)endendendendload_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)endendendendendreturn Left("`" + function + "` not found.")endarray supply(array overrides, string function)array array_buffer = supplier_of(overrides, function)if array_buffer[0]return Right(Connect(array_buffer[1]))elsereturn Left(array_buffer[1])endendnumber supply_unwrapped(array overrides, string function)array array_buffer = supply(overrides, function)return array_buffer[1]end
# server.sprakAllows 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`
a = deserialise_array('{}')Append(tests, [a, []])
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] = falseb[true] = trueAppend(tests, [a, b])a = deserialise_array('{f:0,t:-273.15}')b = []b[false] = 0b[true] = -273.15Append(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] = falseb[-273.15] = trueAppend(tests, [a, b])a = deserialise_array('{0:0,-273.15:-273.15}')b = []b[0] = 0b[-273.15] = -273.15Append(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"] = falseb["def"] = trueAppend(tests, [a, b])a = deserialise_array('{"abc":0,"def":-273.15}')b = []b["abc"] = 0b["def"] = -273.15Append(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"] = falseb["a"] = cAppend(tests, [a, b])
bool is_numeric = falseif character == ":"
if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"
else if character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"end
Returns the serialised form of input where `\` and `"` characters have been prepended with `\`.
Returns the serialised form of a string input where `\` and `"` characters have been prepended with `\`.
* Replace recursions with iterations in:* `serialise_array` and `serialise`* Add an option to serialise numbers using more precision.
* Handle failures during deserialisations by outputting `[true, parse]` or `[false, error]`.* Replace mutual recursions with iterations in:* `serialise_array` and `serialise`
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 APIsEnableAPI(@)endend
# screwdriver.sprakAllows 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.
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.")elseDoorAPI.Lock(target)MemoryAPI.SaveMemory("lock " + target, true)connection_target.Say(target + " locked.")endendif MemoryAPI.HasMemory(KEY_COPY_TARGET)if MemoryAPI.LoadMemory(KEY_COPY_TARGET)connection_extractor.CopyToClipboard(target)endendDisconnectAll()return trueend################ serde.sprak ################string deserialise_string(string input)string output = ""bool escaped = falseloop character in inputif !escapedif character == '\'escaped = trueelse if character != '"'output += characterendelseoutput += characterescaped = falseendendreturn outputendbool is_digit(string input)array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]loop digitsif input == @return trueendendreturn falseend# Types:# * 0: none# * 1: bool# * 2: number# * 3: string# * 4: arrayarray deserialise_array(string input)array accumulator = []bool is_numeric = falsebool in_string = falsebool escaped = falsebool in_value = falsestring buffer = ""number key_type = 0bool key_bool = falsenumber key_number = 0string key_string = ""number value_type = 0bool value_bool = falsenumber value_number = 0string value_string = ""array contexts = []loop character in inputif character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"if !in_stringin_value = trueif key_type == 2key_number = bufferbuffer = ""endelse if in_valuevalue_string += ":"elsekey_string += ":"endelse if character == ","if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendin_value = falsebuffer = ""key_string = ""value_string = ""else if in_valuevalue_string += ","elsekey_string += ","endelse if is_digit(character)is_numeric = trueelse if character == "."is_numeric = trueelse if character == "-"is_numeric = trueelse if character == "{"if !in_stringif key_type == 2Append(contexts, [accumulator, key_type, key_number])else if key_type == 3Append(contexts, [accumulator, key_type, key_string])else if key_type == 0Append(contexts, [accumulator, key_type])elseAppend(contexts, [accumulator, key_type, key_bool])endaccumulator = []is_numeric = falsein_string = falseescaped = falsein_value = falsebuffer = ""key_type = 0key_bool = falsekey_number = 0key_string = ""value_type = 0value_bool = falsevalue_number = 0value_string = ""elsevalue_string += "{"endelse if character == "}"if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendarray last_context = contexts[Count(contexts) - 1]array last_accumulator = last_context[0]number last_key_type = last_context[1]if last_key_type != 0last_accumulator[last_context[2]] = accumulatorelsereturn accumulatorendaccumulator = last_accumulatorvalue_type = 4Remove(contexts, Count(contexts) - 1)elsevalue_string += "}"endelse if character == "\"if !escapedescaped = trueelseescaped = falseif in_valuevalue_string += "\"elsekey_string += "\"endendelse if in_valuevalue_string += characterelsekey_string += characterendif is_numericif !in_stringbuffer += characterif in_valuevalue_type = 2elsekey_type = 2endelse if in_valuevalue_string += characterelsekey_string += characterendis_numeric = falseendendendvar deserialise(string input)if input[0] == "{"return deserialise_array(input)else if is_digit(input[0])number output = inputreturn outputelse if input[0] == "-"number output = inputreturn outputelse if input[0] == '"'return deserialise_string(input)else if input == "t"return trueelse if input == "f"return falseendend################### equality.sprak ###################bool equal_array(array first, array second)if Count(first) == Count(second)loop key in GetIndexes(first)if !HasIndex(second, key)return falseelse if !equal(first[key], second[key])return falseendendreturn trueendreturn falseendbool equal(var first, var second)string type_first = Type(first)if type_first == Type(second)if type_first != "array"return first == secondendreturn equal_array(first, second)endreturn falseend################ array.sprak ################bool has(array arr, var element)loop arrif equal(@, element)return trueendendreturn falseend################ types.sprak ################array Left(var input)return [false, input]endarray 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"]endif HasIndex(overrides, "TingrunnerAPI")TingrunnerAPI_thing = overrides["TingrunnerAPI"]endnumber 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, @)endarray skip_things = []loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]Append(skip_things, @)endstring 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, @)endendelseRemoveAll(skip_types)loop overrides["skip_types"]Append(skip_types, @)endendif !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, @)endendelseRemoveAll(skip_things)loop overrides["skip_things"]Append(skip_things, @)endendif HasIndex(overrides, "more_skip_types")loop overrides["more_skip_types"]if !has(skip_types, @)Append(skip_types, @)endendendif HasIndex(overrides, "more_skip_things")loop overrides["more_skip_things"]if !has(skip_things, @)Append(skip_things, @)endendendif 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)endendendendload_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)endendendendendreturn Left("`" + function + "` not found.")endarray supply(array overrides, string function)array array_buffer = supplier_of(overrides, function)if array_buffer[0]return Right(Connect(array_buffer[1]))elsereturn Left(array_buffer[1])endendnumber supply_unwrapped(array overrides, string function)array array_buffer = supply(overrides, function)return array_buffer[1]end
# modifier.sprakAllows 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`
string MOVE_DATA = '' # '{"Sebastian_inventory":{"things":{0:"RustyModder",1:"Typer1Modifier",2:"Screwdriver_ScrewDriver"}}}'bool WILL_TOGGLE_MODIFIER_COPY = falsearray WHATS_IN = []array WHERES = []string NUMERIC_DATA = '' # '{"Sebastian":{"cash":999,"walkSpeed":10,"sleepiness":0,"wellspring":10,"corruption":0,"drunkenness":0,"smelliness":0}}'bool COPYING = falsebool SAVING = falsestring 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, @)endendif Count(WHERES) > 0loop get_rooms_of(WHERES)Append(results, @)endendif NUMERIC_DATA != ""ARRAY_BUFFER = set_data(NUMERIC_DATA, KEY_NUMERIC_DATA)Append(results, ARRAY_BUFFER)endif Count(results) > 0outputs = format_results(results)endif Count(WHATS_IN) > 0STRING_BUFFER = get_things_in(WHATS_IN)Append(outputs, STRING_BUFFER)endif WILL_TOGGLE_MODIFIER_COPYSTRING_BUFFER = toggle_modifier_copy(KEY_COPY_TARGET)Append(outputs, STRING_BUFFER)endif Count(outputs) > 0say(concatenate(outputs, " "), COPYING, SAVING, KEY_SAY)endDisconnectAll()endarray ARRAY_BUFFERarray CONNECTION_CACHE = []array SUPPLIER_CACHE = []string STRING_BUFFERmain()# Functionsstring concatenate(array strings, string separator)string output = ""loop stringsoutput += @ + separatorendreturn outputendstring format_result(array either)if either[0]return either[1]endreturn "ERROR: " + either[1]endarray format_results(array results)array output = []loop resultsAppend(output, format_result(@))endreturn outputendstring room_of(string thing)if !HasIndex(CONNECTION_CACHE, "GetRoom")array overrides = []overrides["more_skip_types"] = ["drink"]CONNECTION_CACHE["GetRoom"] = supply_unwrapped(overrides, "GetRoom")endreturn CONNECTION_CACHE["GetRoom"].GetRoom(thing)endbool thing_exists(string thing)return room_of(thing) != ""endarray invalid_thing(string thing)return Left('"' + thing + '" is not a valid thing.')endnumber cached_connection(string function)if HasIndex(CONNECTION_CACHE, function)return CONNECTION_CACHE[function]endCONNECTION_CACHE[function] = supply_unwrapped([], function)return CONNECTION_CACHE[function]endstring cached_supplier(string function)if HasIndex(SUPPLIER_CACHE, function)return SUPPLIER_CACHE[function]endSUPPLIER_CACHE[function] = supplier_of_unwrapped([], function)return SUPPLIER_CACHE[function]endbool is_person(string person)return cached_connection("GetTypeOfThing").GetTypeOfThing(person) == "character"endstring move_to_thing(string destination, array move_these)array output = []loop move_theseif is_person(@)string TingrunnerAPI_thing = cached_supplier("MovePerson")cached_connection("SetPosition").SetPosition(TingrunnerAPI_thing, @)Connect(TingrunnerAPI_thing).MovePerson(@, destination)elsecached_connection("SetPosition").SetPosition(@, destination)endAppend(output, 'Moved "' + @ + '" to "' + destination + '".')endreturn concatenate(output, " ")endarray move(string serialised_schedule)array schedule = deserialise(serialised_schedule)array destinations = GetIndexes(schedule)loop destination in destinationsif thing_exists(destination)array task = schedule[destination]loop task["things"]if !thing_exists(@)return [invalid_thing(@)]endendelsearray things = cached_connection("GetThingsInRoom").GetThingsInRoom(destination)number count_things = Count(things)if count_things > 0array task = schedule[destination]number index = 0if HasIndex(task, "index")index = task["index"]endif index < 0return [Left("`index` should be >= 0.")]else if index - Int(index) != 0return [Left("`index` should be an integer.")]else if index + 1 > count_thingsreturn [Left("" + (count_things - 1) + 'is the max `index` value for "' + destination + '".')]elseloop task["things"]if !thing_exists(@)return [invalid_thing(@)]endendendelsereturn [Left('"' + destination + '" is not a valid destination.')]endendendarray output = []loop destination in destinationsarray task = schedule[destination]if thing_exists(destination)ARRAY_BUFFER = Right(move_to_thing(destination, task["things"]))Append(output, ARRAY_BUFFER)elsearray things = cached_connection("GetThingsInRoom").GetThingsInRoom(destination)number index = 0if HasIndex(task, "index")index = task["index"]endARRAY_BUFFER = Right(move_to_thing(things[index], task["things"]))Append(output, ARRAY_BUFFER)endendreturn outputendstring get_things_in(array rooms)array outputs = []number TingrunnerAPI = cached_connection("GetThingsInRoom")loop roomsAppend(outputs, 'Serialised list of things in "' + @ + '": ' + "'" + serialise(TingrunnerAPI.GetThingsInRoom(@)) + "'.")endreturn concatenate(outputs, " ")endarray get_rooms_of(array things)array outputs = []loop thingsif !thing_exists(@)return [invalid_thing(@)]endendloop thingsAppend(outputs, Right('"' + @ + '" is in "' + room_of(@) + '".'))endreturn outputsendstring toggle_modifier_copy(string key)string MemoryAPI_thing = cached_supplier("SaveMemory")number MemoryAPI = Connect(MemoryAPI_thing)if !MemoryAPI.HasMemory(key)MemoryAPI.SaveMemory(key, false)endbool 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) + "`."endarray set_data(string serialised_data, string key)array data = deserialise(serialised_data)array things = GetIndexes(data)loop thing in thingsif !thing_exists(thing)return invalid_thing(thing)endarray 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.")endif key_data_point == "cash" || key_data_point == "wellspring"if !is_person(thing)return Left('"' + thing + '" is not a valid person.')endendendendstring 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 + '".')endvoid say(string output, bool copying, bool saving, string key)if output != ""if copyingif !HasIndex(CONNECTION_CACHE, "CopyToClipboard")array overrides = []overrides["more_skip_types"] = ["taser"]CONNECTION_CACHE["CopyToClipboard"] = supply_unwrapped(overrides, "CopyToClipboard")endif savingCONNECTION_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)elseCONNECTION_CACHE["CopyToClipboard"].CopyToClipboard(output)Say("Copied: " + output)endelse if savingstring MemoryAPI_thing = cached_supplier("SaveMemory")Connect(MemoryAPI_thing).SaveMemory(key, output)Say('The following was saved to "' + MemoryAPI_thing + '" using the key "' + key + '": ' + output)elseSay(output)endendend# Imports################ serde.sprak ################string serialise_string(string input)string output = ""loop character in inputif character == '"'output += "\"else if character == "\"output += "\"endoutput += characterendreturn '"' + output + '"'endstring serialise_array(array input)string output = ""bool not_start = falseloop key in GetIndexes(input)if Type(key) != "array"if not_startoutput += ","elsenot_start = trueendoutput += serialise(key) + ":" + serialise(input[key])endendreturn "{" + output + "}"endstring serialise(var input)string input_type = Type(input)if input_type == "unknown"string output = ""loop character in "" + inputif character != "i"output += characterendendreturn outputelse if input_type == "string"return serialise_string(input)else if input_type == "number"return "" + inputelse if input_type == "bool"if inputreturn "t"endreturn "f"else if input_type == "array"return serialise_array(input)endendstring deserialise_string(string input)string output = ""bool escaped = falseloop character in inputif !escapedif character == '\'escaped = trueelse if character != '"'output += characterendelseoutput += characterescaped = falseendendreturn outputendbool is_digit(string input)array digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]loop digitsif input == @return trueendendreturn falseend# Types:# * 0: none# * 1: bool# * 2: number# * 3: string# * 4: arrayarray deserialise_array(string input)array accumulator = []bool is_numeric = falsebool in_string = falsebool escaped = falsebool in_value = falsestring buffer = ""number key_type = 0bool key_bool = falsenumber key_number = 0string key_string = ""number value_type = 0bool value_bool = falsenumber value_number = 0string value_string = ""array contexts = []loop character in inputif character == '"'if !in_stringin_string = trueif in_valuevalue_type = 3elsekey_type = 3endelse if !escapedin_string = falseelse if in_valuevalue_string += '"'elsekey_string += '"'endelse if character == "t"if !in_stringif in_valuevalue_bool = truevalue_type = 1elsekey_bool = truekey_type = 1endelse if in_valuevalue_string += "t"elsekey_string += "t"endelse if character == "f"if !in_stringif in_valuevalue_bool = falsevalue_type = 1elsekey_bool = falsekey_type = 1endelse if in_valuevalue_string += "f"elsekey_string += "f"endelse if character == ":"if !in_stringin_value = trueif key_type == 2key_number = bufferbuffer = ""endelse if in_valuevalue_string += ":"elsekey_string += ":"endelse if character == ","if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendin_value = falsebuffer = ""key_string = ""value_string = ""else if in_valuevalue_string += ","elsekey_string += ","endelse if is_digit(character)is_numeric = trueelse if character == "."is_numeric = trueelse if character == "-"is_numeric = trueelse if character == "{"if !in_stringif key_type == 2Append(contexts, [accumulator, key_type, key_number])else if key_type == 3Append(contexts, [accumulator, key_type, key_string])else if key_type == 0Append(contexts, [accumulator, key_type])elseAppend(contexts, [accumulator, key_type, key_bool])endaccumulator = []is_numeric = falsein_string = falseescaped = falsein_value = falsebuffer = ""key_type = 0key_bool = falsekey_number = 0key_string = ""value_type = 0value_bool = falsevalue_number = 0value_string = ""elsevalue_string += "{"endelse if character == "}"if !in_stringif key_type == 2if value_type == 3accumulator[key_number] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_number] = value_numberelse if value_type == 1accumulator[key_number] = value_boolendelse if key_type == 3if value_type == 3accumulator[key_string] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_string] = value_numberelse if value_type == 1accumulator[key_string] = value_boolendelse if key_type == 1if value_type == 3accumulator[key_bool] = value_stringelse if value_type == 2value_number = bufferaccumulator[key_bool] = value_numberelse if value_type == 1accumulator[key_bool] = value_boolendendarray last_context = contexts[Count(contexts) - 1]array last_accumulator = last_context[0]number last_key_type = last_context[1]if last_key_type != 0last_accumulator[last_context[2]] = accumulatorelsereturn accumulatorendaccumulator = last_accumulatorvalue_type = 4Remove(contexts, Count(contexts) - 1)elsevalue_string += "}"endelse if character == "\"if !escapedescaped = trueelseescaped = falseif in_valuevalue_string += "\"elsekey_string += "\"endendelse if in_valuevalue_string += characterelsekey_string += characterendif is_numericif !in_stringbuffer += characterif in_valuevalue_type = 2elsekey_type = 2endelse if in_valuevalue_string += characterelsekey_string += characterendis_numeric = falseendendendvar deserialise(string input)if input[0] == "{"return deserialise_array(input)else if is_digit(input[0])number output = inputreturn outputelse if input[0] == "-"number output = inputreturn outputelse if input[0] == '"'return deserialise_string(input)else if input == "t"return trueelse if input == "f"return falseendend################### equality.sprak ###################bool equal_array(array first, array second)if Count(first) == Count(second)loop key in GetIndexes(first)if !HasIndex(second, key)return falseelse if !equal(first[key], second[key])return falseendendreturn trueendreturn falseendbool equal(var first, var second)string type_first = Type(first)if type_first == Type(second)if type_first != "array"return first == secondendreturn equal_array(first, second)endreturn falseend################ array.sprak ################bool has(array arr, var element)loop arrif equal(@, element)return trueendendreturn falseend################ types.sprak ################array Left(var input)return [false, input]endarray 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"]endif HasIndex(overrides, "TingrunnerAPI")TingrunnerAPI_thing = overrides["TingrunnerAPI"]endnumber 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, @)endarray skip_things = []loop ["ComputerTerminalBoard1_ComputerTerminalBoard1", "Hotel_Diner_Fountain", "TrainingCube", "Internet_Internet_MediumComputer_10", "Internet_MediumComputer", "ArcadeHall_ArcadeMachine_ArcadeMachine_3"]Append(skip_things, @)endstring 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, @)endendelseRemoveAll(skip_types)loop overrides["skip_types"]Append(skip_types, @)endendif !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, @)endendelseRemoveAll(skip_things)loop overrides["skip_things"]Append(skip_things, @)endendif HasIndex(overrides, "more_skip_types")loop overrides["more_skip_types"]if !has(skip_types, @)Append(skip_types, @)endendendif HasIndex(overrides, "more_skip_things")loop overrides["more_skip_things"]if !has(skip_things, @)Append(skip_things, @)endendendif 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)endendendendload_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)endendendendendreturn Left("`" + function + "` not found.")endstring supplier_of_unwrapped(array overrides, string function)array array_buffer = supplier_of(overrides, function)return array_buffer[1]endarray supply(array overrides, string function)array array_buffer = supplier_of(overrides, function)if array_buffer[0]return Right(Connect(array_buffer[1]))elsereturn Left(array_buffer[1])endendnumber supply_unwrapped(array overrides, string function)array array_buffer = supply(overrides, function)return array_buffer[1]end
# drink.sprakAllows 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```sprakstring 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```sprakstring 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.
array push(array arr, var element)array output = []loop arrAppend(output, @)endAppend(output, element)return outputend
#### Imports* equality.sprak* `equal_array`* `equal`
### `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```
---
* 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.
else_heart_break.code-workspace