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

###############
# 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