def resolve_transformation_items(self, transformed_item, command, replacement, transformation_info, elements_by_id, validation): if not isinstance(replacement, Item): validation.append( Message(Message.ITEM_TRANSFORMATION_REPLACEMENT_NON_ITEM, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, replacement.data_id, replacement.shortname))) return if transformed_item.is_mobile(): if not replacement.is_mobile(): validation.append( Message( Message.ITEM_TRANSFORMATION_REPLACEMENT_NON_MOBILE, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, replacement.data_id, replacement.shortname))) elif replacement.size > transformed_item.size: validation.append( Message( Message.ITEM_TRANSFORMATION_REPLACEMENT_TOO_LARGE, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, replacement.data_id, replacement.shortname))) tool = self.resolve_transformation_optional_item( transformed_item, command, elements_by_id, transformation_info.tool_id, "tool_id", validation) material = self.resolve_transformation_optional_item( transformed_item, command, elements_by_id, transformation_info.material_id, "material_id", validation) transformed_item.transformations[command.data_id] = Transformation( replacement=replacement, tool=tool, material=material)
def parse_switch_info(self, attributes, item_input, related_command_id, validation, item_id, shortname): switched_element_id = None switch_info = None if (attributes & Item.ATTRIBUTE_SWITCHABLE): if "switch_info" in item_input: switch_info_input = item_input["switch_info"] switched_element_id = switch_info_input["element_id"] switched_attribute = int(switch_info_input["attribute"], 16) off_switch = switch_info_input["off"] on_switch = switch_info_input["on"] switch_info = SwitchInfo(attribute=switched_attribute, off=off_switch, on=on_switch) else: validation.append( Message(Message.ITEM_SWITCHABLE_NO_SWITCH_INFO, (item_id, shortname))) if not related_command_id: validation.append( Message(Message.ITEM_SWITCHABLE_NO_RELATED_COMMAND, (item_id, shortname))) elif "switch_info" in item_input: validation.append( Message(Message.ITEM_NON_SWITCHABLE_WITH_SWITCH_INFO, (item_id, shortname))) return switched_element_id, switch_info
def parse_commands(self, command_inputs): commands_by_name = {} commands_by_id = {} validation = [] teleport_infos = {} smash_command_ids = [] for command_input in command_inputs: command, teleport_info, is_smash = self.parse_command(command_input, validation) if command: for alias in command.aliases: if alias in commands_by_name: if command is commands_by_name[alias]: validation.append(Message(Message.COMMAND_SHARED_ALIAS_SAME_COMMAND, (alias, command.data_id, command.primary))) else: validation.append(Message(Message.COMMAND_SHARED_ALIAS_DIFFERENT_COMMANDS, (alias, command.data_id, command.primary))) commands_by_name[alias] = command if command.data_id in commands_by_id: validation.append(Message(Message.COMMAND_SHARED_ID, (command.data_id, command.primary))) commands_by_id[command.data_id] = command if teleport_info: teleport_infos[command] = teleport_info if is_smash: smash_command_ids.append(command.data_id) return commands_by_name, commands_by_id, teleport_infos, smash_command_ids, validation
def validate_item_usable(self, item, validation): if self.item_is_usable(item) and item.is_liquid(): validation.append( Message(Message.ITEM_USABLE_LIQUID, (item.data_id, item.shortname))) if item.is_wearable() and item.is_sailable(): validation.append( Message(Message.ITEM_WEARABLE_SAILABLE, (item.data_id, item.shortname)))
def validate_command_switchable(self, command, validation): if command.is_switchable(): if not command.switch_info: validation.append( Message(Message.COMMAND_SWITCHABLE_NO_SWITCH_INFO, (command.data_id, command.primary))) elif command.switch_info: validation.append( Message(Message.COMMAND_NON_SWITCHABLE_WITH_SWITCH_INFO, (command.data_id, command.primary)))
def validate_location_attributes(self, location, validation): if not location.has_floor() and not location.get_adjacent_location( Direction.DOWN): validation.append( Message(Message.LOCATION_NO_FLOOR_NO_DOWN, (location.data_id, Direction.DOWN.name))) if not location.has_land() and not location.has_floor(): validation.append( Message(Message.LOCATION_NO_LAND_NO_FLOOR, (location.data_id, )))
def validate_command_teleport(self, command, validation): if command.is_teleport(): if not command.teleport_info: validation.append( Message(Message.COMMAND_TELEPORT_NO_TELEPORT_INFO, (command.data_id, command.primary))) elif command.teleport_info: validation.append( Message(Message.COMMAND_NON_TELEPORT_WITH_TELEPORT_INFO, (command.data_id, command.primary)))
def validate_item_obstruction(self, item, validation): if item.is_obstruction(): if len(item.containers) > 1: validation.append( Message(Message.ITEM_OBSTRUCTION_MULTIPLE_CONTAINERS, (item.data_id, item.shortname))) elif len(item.containers) == 1 and not isinstance( item.get_first_container(), Location): validation.append( Message(Message.ITEM_OBSTRUCTION_NOT_AT_LOCATION, (item.data_id, item.shortname)))
def validate_item_size(self, item, validation): if item.size < Item.MIN_SIZE: validation.append( Message( Message.ITEM_BELOW_MINIMUM_SIZE, (item.data_id, item.shortname, item.size, Item.MIN_SIZE))) if isinstance(item, ContainerItem) and item.size < Item.MIN_SIZE + 1: validation.append( Message( Message.ITEM_CONTAINER_BELOW_MINIMUM_SIZE, (item.data_id, item.shortname, item.size, Item.MIN_SIZE)))
def validate_item_mobility(self, item, validation): if not item.is_mobile(): if any(not isinstance(container, Location) for container in item.containers): validation.append( Message(Message.ITEM_NON_MOBILE_NOT_AT_LOCATION, (item.data_id, item.shortname))) if item.is_sailable(): validation.append( Message(Message.ITEM_NON_MOBILE_SAILABLE, (item.data_id, item.shortname))) if item.is_wearable(): validation.append( Message(Message.ITEM_NON_MOBILE_WEARABLE, (item.data_id, item.shortname)))
def validate_item_attributes(self, item, validation, smash_command_id): self.validate_item_mobility(item, validation) self.validate_item_obstruction(item, validation) self.validate_item_usable(item, validation) if item.is_copyable() and not item.is_liquid(): validation.append( Message(Message.ITEM_COPYABLE_NON_LIQUID, (item.data_id, item.shortname))) if item.is_fragile(): if not smash_command_id: validation.append( Message(Message.ITEM_FRAGILE_NO_SMASH_COMMAND, ())) elif not smash_command_id in item.transformations: validation.append( Message(Message.ITEM_FRAGILE_NO_SMASH_TRANSFORMATION, (item.data_id, item.shortname)))
def cross_reference(self, locations, links, validation): for location, links in links.items(): for direction, linked_location_id in links.items(): if not linked_location_id in locations: validation.append(Message(Message.LOCATION_UNKNOWN_LINK_DESTINATION, (linked_location_id, direction, location.data_id))) else: linked_location = locations[linked_location_id] location.directions[direction] = linked_location
def parse(self, location_inputs, teleport_infos): links = {} locations, validation = self.parse_locations(location_inputs, links) self.cross_reference(locations, links, validation) for command, teleport_info in teleport_infos.items(): for source_id, destination_id in teleport_info.items(): if not source_id in locations: validation.append(Message(Message.COMMAND_TELEPORT_UNKNOWN_SOURCE_ID, (source_id, command.data_id, command.primary))) if source_id == destination_id: validation.append(Message(Message.COMMAND_TELEPORT_SOURCE_DESTINATION_SAME, (source_id, command.data_id, command.primary))) if not destination_id in locations: validation.append(Message(Message.COMMAND_TELEPORT_UNKNOWN_DESTINATION_ID, (destination_id, command.data_id, command.primary))) else: destination = locations[destination_id] command.teleport_info[source_id] = destination return LocationCollection(locations), validation
def validate_inventories_default(self, inventories, validation): default_inventories = [ inventory for inventory in inventories.values() if inventory.is_default() ] if len(default_inventories) < 1: validation.append(Message(Message.INVENTORY_NO_DEFAULT, ())) elif len(default_inventories) > 1: validation.append( Message( Message.INVENTORY_MULTIPLE_DEFAULT, ([inventory.data_id for inventory in default_inventories], ))) for inventory in default_inventories: if inventory.location_ids: validation.append( Message(Message.INVENTORY_DEFAULT_WITH_LOCATIONS, (inventory.data_id, inventory.shortname)))
def place_items(self, container_ids_by_item, containers, validation): for item, container_ids in container_ids_by_item.items(): for container_id in container_ids: container = containers.get(container_id) if container: container.add(item) else: validation.append( Message(Message.ITEM_CONTAINER_UNKNOWN, (item.data_id, item.shortname, container_id)))
def parse_writing(self, item_input, validation, item_id, shortname): if not "writing" in item_input: return None writing_input = item_input["writing"] if not writing_input: validation.append( Message(Message.ITEM_WRITING_EMPTY, (item_id, shortname))) return writing_input
def validate_item_list_templates(self, item, validation): list_templates = item.list_templates if item.is_switchable(): if not (ListTemplateType.DEFAULT in list_templates or (ListTemplateType.LOCATION in list_templates and ListTemplateType.CARRYING in list_templates)): validation.append( Message(Message.ITEM_SWITCHABLE_NO_LIST_TEMPLATES, (item.data_id, item.shortname))) if self.item_is_usable(item): if not ListTemplateType.USING in list_templates: validation.append( Message(Message.ITEM_USABLE_NO_LIST_TEMPLATE_USING, (item.data_id, item.shortname))) elif ListTemplateType.USING in list_templates: validation.append( Message(Message.ITEM_NON_USABLE_WITH_LIST_TEMPLATE_USING, (item.data_id, item.shortname)))
def validate_commands(self, command_collection): validation = [] for command in command_collection.commands_by_id.values(): self.validate_command_teleport(command, validation) self.validate_command_switchable(command, validation) if len(command_collection.smash_command_ids) > 1: validation.append(Message(Message.COMMAND_SMASH_MULTIPLE, ())) return validation
def parse_links(self, direction_inputs, validation, location_id): links = {} for direction_key_input, direction_value_input in direction_inputs.items(): direction_key = direction_key_input.upper() if not direction_key in Direction.__members__: validation.append(Message(Message.LOCATION_UNKNOWN_LINK_DIRECTION, (direction_key_input, location_id))) else: direction = Direction[direction_key] links[direction] = direction_value_input self.calculate_out(links) return links
def parse_locations(self, location_inputs, links): locations = {} validation = [] for location_input in location_inputs: location = self.parse_location(location_input, links, validation) if location.data_id in locations: validation.append(Message(Message.LOCATION_SHARED_ID, (location.data_id,))) locations[location.data_id] = location return locations, validation
def validate_inventories(self, inventory_collection, location_collection): validation = [] inventories = inventory_collection.inventories if len(inventories) < 1: validation.append(Message(Message.INVENTORY_NONE, ())) else: self.validate_inventories_default(inventories, validation) self.validate_inventories_non_default( inventories, location_collection.locations.keys(), validation) return validation
def resolve_switches(self, switched_element_ids, elements_by_id, validation): for switching_item, switched_element_id in switched_element_ids.items( ): if switched_element_id in elements_by_id: switching_item.switched_element = elements_by_id[ switched_element_id] else: validation.append( Message(Message.ITEM_SWITCHABLE_INVALID_SWITCHED_ELEMENT, (switching_item.data_id, switching_item.shortname, switched_element_id)))
def resolve_related_command(self, item, commands_by_id, related_command_id, related_commands, shortnames, validation): if related_command_id: if related_command_id in commands_by_id: related_command = commands_by_id[related_command_id] if item.is_switchable() and not related_command.is_switching(): validation.append( Message( Message. ITEM_SWITCHABLE_NON_SWITCHING_RELATED_COMMAND, (item.data_id, item.shortname, related_command.data_id, related_command.primary))) for shortname in shortnames: related_commands[shortname] = commands_by_id.get( related_command_id) else: validation.append( Message( Message.ITEM_INVALID_RELATED_COMMAND, (related_command_id, item.data_id, item.shortname)))
def resolve_transformation(self, transformed_item, command_id, transformation_info, elements_by_id, commands_by_id, validation): if not command_id in commands_by_id: validation.append( Message(Message.ITEM_TRANSFORMATION_COMMAND_UNKNOWN, (transformed_item.data_id, transformed_item.shortname, command_id))) return command = commands_by_id[command_id] self.resolve_transformation_command(transformed_item, command, transformation_info, elements_by_id, validation)
def parse_inventories(self, inventory_inputs): inventories = {} validation = [] for inventory_input in inventory_inputs: inventory = self.parse_inventory(inventory_input) if inventory.data_id in inventories: validation.append( Message(Message.INVENTORY_SHARED_ID, (inventory.data_id, ))) inventories[inventory.data_id] = inventory return inventories, validation
def parse_teleport_info(self, teleport_info_inputs, validation, command_id, primary): teleport_infos = {} if teleport_info_inputs: for teleport_info_input in teleport_info_inputs: source_id = teleport_info_input["source"] destination_id = teleport_info_input["destination"] if source_id in teleport_infos: validation.append(Message(Message.COMMAND_TELEPORT_SHARED_SOURCES, (source_id, command_id, primary, destination_id))) else: teleport_infos[source_id] = destination_id return teleport_infos
def validate_item_containers(self, item, nonempty_container_items, validation): for container in item.containers: if isinstance(container, Item): if container in nonempty_container_items: validation.append( Message(Message.ITEM_CONTAINER_SHARED, (container.data_id, container.shortname))) else: nonempty_container_items.add(container) if container.size <= item.size: validation.append( Message(Message.ITEM_CONTAINER_TOO_SMALL, ( item.data_id, item.shortname, item.size, container.data_id, container.shortname, container.size, ))) if item.is_liquid() and not container.is_liquid_container(): validation.append( Message(Message.ITEM_LIQUID_CONTAINER_NOT_LIQUID, (item.data_id, item.shortname, container.data_id, container.shortname))) if not item.is_liquid() and container.is_liquid_container(): validation.append( Message(Message.ITEM_NON_LIQUID_CONTAINER_LIQUID, (item.data_id, item.shortname, container.data_id, container.shortname))) elif isinstance( container, Location) and item.is_liquid() and not item.is_copyable(): validation.append( Message( Message.ITEM_LIQUID_NON_COPYABLE_CONTAINER_LOCATION, (item.data_id, item.shortname, container.data_id, container.shortname)))
def parse_labels(self, item_input, validation, item_id): label_input = item_input["labels"] shortnames = label_input["shortnames"] extended_descriptions = label_input.get("extended_descriptions", []) primary_shortname = None if shortnames: primary_shortname = shortnames[0] else: validation.append(Message(Message.ITEM_NO_SHORTNAMES, (item_id, ))) return Labels(primary_shortname, label_input["longname"], label_input["description"], extended_descriptions), shortnames
def resolve_transformation_optional_item(self, transformed_item, command, elements_by_id, item_id, field, validation): if not item_id: return None if not item_id in elements_by_id: validation.append( Message(Message.ITEM_TRANSFORMATION_OPTIONAL_UNKNOWN, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, field, item_id))) return None element = elements_by_id[item_id] if not isinstance(element, Item): validation.append( Message(Message.ITEM_TRANSFORMATION_OPTIONAL_NON_ITEM, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, field, item_id, element.shortname))) return None return element
def resolve_transformation_command(self, transformed_item, command, transformation_info, elements_by_id, validation): replacement_id = transformation_info.replacement_id if not replacement_id in elements_by_id: validation.append( Message(Message.ITEM_TRANSFORMATION_REPLACEMENT_UNKNOWN, (transformed_item.data_id, transformed_item.shortname, command.data_id, command.primary, replacement_id))) return replacement = elements_by_id[replacement_id] self.resolve_transformation_items(transformed_item, command, replacement, transformation_info, elements_by_id, validation)