S7BXWG4QQMJ6M4XDUNDLJGD4BXB4QVZKXWSHXXVGKMNDWB5WV5LQC
###############
# types.sprak #
###############
array Left(var input)
return [false, input]
end
array Right(var input)
return [true, input]
end
# 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
```
bool is_numeric = false
if character == ":"
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 == ":"
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
var MemoryAPI
if MemoryAPI_thing != name
MemoryAPI = Connect(MemoryAPI_thing)
else
return [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 TingrunnerAPI
if TingrunnerAPI_thing != name
TingrunnerAPI = Connect(TingrunnerAPI_thing)
else
return [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 != 0
skip_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 != 0
skip_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 != 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]
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
if thing != name
if !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.")
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]
### 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())
```
### `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())
```
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
```sprak
string 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, @)
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
bool is_numeric = false
if character == ":"
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 == ":"
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
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)
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()
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
# 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`
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] = 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])
bool is_numeric = false
if character == ":"
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 == ":"
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
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 APIs
EnableAPI(@)
end
end
# 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.
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
# 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`
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
# 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.
array push(array arr, var element)
array output = []
loop arr
Append(output, @)
end
Append(output, element)
return output
end
#### 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