def is_finished(self, current_node: Node): """ Finish if the current node is the destination node. :param current_node: The current node. :return: If the path has been found or not, if so, return the cheapest path. """ if current_node == self.dest_node: # Destroying the vinculum costs 5 minutes, with a tritanium-blaster 1 minute if current_node.tritanium_blaster >= 1: current_node.g = current_node.g + 1 current_node.f = current_node.g + current_node.h current_node.tritanium_blaster = current_node.tritanium_blaster - 1 current_node.regeneration_time = current_node.regeneration_time - 1 else: current_node.g = current_node.g + 5 current_node.f = current_node.g + current_node.h current_node.regeneration_time = current_node.regeneration_time - 5 # Reconstruct the path path = self.reconstruct_path(current_node) for node in path: logging.debug(node) logging.info('Destination reached, final cost: %f' % current_node.g) return path return False
def is_ladder(self, current_node: Node, child_node: Node, current_link: Link): """ Check whether the link is a ladder and the path is cheaper. Up the ladder costs 2 minutes. Down costs 1/2 minute. :param current_node: The current node. :param child_node: The child node of the current node. :param current_link: The link from the current to the child node. :return: Whether the link is a ladder and cheaper or not. """ if current_link.is_ladder: # Check if the ladder has been went up or down if current_node.position[2] <= child_node.position[2]: if not self.is_cheaper(current_node, child_node, 2, energy_unit_cost=2): return False child_node.g = current_node.g + 2 child_node.regeneration_time = current_node.regeneration_time - 2 child_node.parent_link_type = 'ladder up' else: if not self.is_cheaper(current_node, child_node, 0.5, energy_unit_cost=2): return False child_node.g = current_node.g + 0.5 child_node.regeneration_time = current_node.regeneration_time - 0.5 child_node.parent_link_type = 'ladder down' child_node.tritanium_blaster = current_node.tritanium_blaster child_node.energy_units = current_node.energy_units return True return False
def g(self, current_link: Link, current_node: Node, child_node: Node): """ Calculate the cost/ distance from start to the child node. :param current_link: Current link from the current node to the child node. :param current_node: Current parent node. :param child_node: Child node of the current node. :return: Whether the g score could be set or not. """ # No link to the neighbor room, link can be blasted # Blasting a hole in a wall with a tritanium-blaster costs 3 minutes, can be used in all # directions expect up if current_link is None: if not self.is_cheaper(current_node, child_node, 3): return False child_node.g = current_node.g + 3 child_node.regeneration_time = current_node.regeneration_time - 3 child_node.tritanium_blaster = current_node.tritanium_blaster - 1 child_node.energy_units = current_node.energy_units child_node.parent_link_type = 'wall or ground blasted' return True # Path with or without a drone if self.is_open(current_node, child_node, current_link): return True # Door costs 2 minutes if self.is_door(current_node, child_node, current_link): return True # Up the ladder costs 2 minutes # Down costs 1/2 minute if self.is_ladder(current_node, child_node, current_link): return True return False
def is_open(self, current_node: Node, child_node: Node, current_link: Link): """ Check whether the link is open and the path is cheaper. Path with or without a drone. :param current_node: The current node. :param child_node: The child node of the current node. :param current_link: The link from the current to the child node. :return: Whether the link is open and cheaper or not. """ if current_link.is_open: # Destroying a drone costs 3 minutes and one energy unit # 5 minute regeneration time before a new drone can be fought if current_link.is_sentinel: # Check if any energy units are left if current_node.energy_units == 0: return False # Check whether a regeneration is set or not, if so, take a brake # A 1 minute Break can always be used and repeated if current_node.regeneration_time == 0: if not self.is_cheaper(current_node, child_node, 3, energy_unit_cost=1): return False child_node.g = current_node.g + 3 child_node.parent_link_type = 'drone' else: if not self.is_cheaper(current_node, child_node, 3 + current_node.regeneration_time, energy_unit_cost=1): return False child_node.g = current_node.g + 3 + current_node.regeneration_time child_node.parent_link_type = 'drone & %f minutes regeneration' %\ current_node.regeneration_time child_node.energy_units = current_node.energy_units - 1 child_node.regeneration_time = 5 child_node.tritanium_blaster = current_node.tritanium_blaster # No obstacle, costs 1 minute else: if not self.is_cheaper(current_node, child_node, 1): return False child_node.g = current_node.g + 1 child_node.regeneration_time = current_node.regeneration_time - 1 child_node.tritanium_blaster = current_node.tritanium_blaster child_node.energy_units = current_node.energy_units child_node.parent_link_type = 'open' return True return False
def is_door(self, current_node: Node, child_node: Node, current_link: Link): """ Check whether the link is a door and the path is cheaper. Door costs 2 minutes. :param current_node: The current node. :param child_node: The child node of the current node. :param current_link: The link from the current to the child node. :return: Whether the link is a door and cheaper or not. """ if current_link.is_door: if not self.is_cheaper(current_node, child_node, 2): return False child_node.g = current_node.g + 2 child_node.regeneration_time = current_node.regeneration_time - 2 child_node.tritanium_blaster = current_node.tritanium_blaster child_node.energy_units = current_node.energy_units child_node.parent_link_type = 'door' return True return False