示例#1
0
 def movementCost(self, cur, dest):
     """Return the cost of moving from cur tile to dest tile, taking into account surface type. Only single step movement is considered. Returns 100 when movement is not possible."""
     if gridhelper.isDifficultSurface(cur.getSurface()):
         # moving from difficult terrain
         if gridhelper.horizontalDistance(cur.coords, dest.coords) == 1:
             if (cur.coords.z - dest.coords.z) <= 3 and (
                     cur.coords.z - dest.coords.z) >= -1:
                 return 2
     else:
         # moving from normal terrain
         if gridhelper.horizontalDistance(cur.coords, dest.coords) == 1:
             if (cur.coords.z - dest.coords.z) <= 3 and (
                     cur.coords.z - dest.coords.z) >= -2:
                 return 1
         elif gridhelper.horizontalDistance(cur.coords, dest.coords) == 2:
             if (cur.coords.z - dest.coords.z) <= 3 and (cur.coords.z >=
                                                         dest.coords.z):
                 x1 = int(cur.coords.x +
                          floor((dest.coords.x - cur.coords.x) / 2.0))
                 y1 = int(cur.coords.y +
                          floor((dest.coords.y - cur.coords.y) / 2.0))
                 x2 = int(cur.coords.x +
                          ceil((dest.coords.x - cur.coords.x) / 2.0))
                 y2 = int(cur.coords.y +
                          ceil((dest.coords.y - cur.coords.y) / 2.0))
                 loc1 = fife.ExactModelCoordinate(x1, y2, cur.coords.z)
                 loc2 = fife.ExactModelCoordinate(x2, y1, cur.coords.z)
                 if (not self.isBlocked(loc1, 4)) and (not self.isBlocked(
                         loc2, 4)):
                     return 3
     return 100
示例#2
0
 def isValidTarget(self, source, target, targeting_rules):
     """Return whether target can be targeted by source under targeting_rules. Source is a character and target is a character, tile or obstacle."""
     if targeting_rules.can_target_self and (source == target):
         return True
     if (not targeting_rules.can_target_self) and (source.coords
                                                   == target.coords):
         return False
     if type(target) == TacticsCharacter:
         if target.cur_HP <= 0:
             return False
     if (source != target) and ((targeting_rules.can_target_other and
                                 (type(target)) == TacticsCharacter) or
                                (targeting_rules.can_target_tile and
                                 (type(target)) == TacticsTile) or
                                (targeting_rules.can_target_obstacle and
                                 (type(target)) == Obstacle)):
         if targeting_rules.trajectory.type == targeting_rules.trajectory.TRAJECTORY_SINGLE:
             if (gridhelper.horizontalDistance(source.coords, target.coords)
                     <= targeting_rules.trajectory.range) and (
                         (source.coords.z - target.coords.z) <=
                         targeting_rules.trajectory.range_down) and (
                             (target.coords.z - source.coords.z) <=
                             targeting_rules.trajectory.range_up):
                 return True
         elif targeting_rules.trajectory.type == targeting_rules.trajectory.TRAJECTORY_LINE:
             if (gridhelper.horizontalDistance(source.coords, target.coords)
                     <= targeting_rules.trajectory.range) and self.isLOS(
                         source, target) and (
                             (source.coords.z - target.coords.z) <=
                             targeting_rules.trajectory.range_down) and (
                                 (target.coords.z - source.coords.z) <=
                                 targeting_rules.trajectory.range_up):
                 return True
         elif targeting_rules.trajectory.type == targeting_rules.trajectory.TRAJECTORY_ARC:
             if self.isTrajectory(source, target):
                 return True
     return False
示例#3
0
    def testTrajectory(self, coords1, coords2, trajectory, visualize=False):
        """
		Return False if an arc from loc1 to loc2 defined by trajectory is blocked by a wall or outside range, True if the arc is clear and in range.
		Uses locations slightly above the ones given.
		Creates an optional visual trajectory.
		"""
        # TODO: visualization probably should not be done here
        ex_coords1 = gridhelper.toExact(coords1)
        ex_coords2 = gridhelper.toExact(coords2)

        z_scale = 3.0
        dist = gridhelper.horizontalDistance(coords1, coords2) * z_scale
        if dist == 0:
            return False
        z = coords2.z - coords1.z
        g = 5.0 / z_scale
        d2 = pow(trajectory.range,
                 4) - g * (g * pow(dist, 2) + 2 * z * pow(trajectory.range, 2))
        if d2 < 0:
            return False
        angle1 = atan((pow(trajectory.range, 2) - sqrt(d2)) / (g * dist))
        #angle2 = atan((pow(trajectory.range, 2) + sqrt(d2)) / (g * dist))

        step = (ex_coords2 - ex_coords1) / 20.0
        if self.visual and visualize:
            los = VisualLOS(self.application)
            self.application.real_timeline.addTimer(
                TacticsTimer("line of sight", 1, 1, los.destroy))
        for i in range(1, 20):
            ex_coords = ex_coords1 + step * float(i)
            ex_coords.z = ex_coords1.z + float(dist) / 20.0 * float(i) * tan(
                angle1) - g * pow(float(dist) / 20.0 * float(i), 2) / (
                    2 * pow(trajectory.range * cos(angle1), 2))
            if self.visual and visualize:
                location = fife.Location(self.maplayer)
                location.setExactLayerCoordinates(
                    fife.ExactModelCoordinate(ex_coords.x, ex_coords.y,
                                              ex_coords.z + 2))
                los.addDot(location, self.shadowLocation(location))
            if self.isBlockedByWall(
                    fife.ExactModelCoordinate(ex_coords.x, ex_coords.y,
                                              ex_coords.z + 1.5), 1):
                if self.visual and visualize:
                    self.application.gui.sayBubble(los.instances[-1],
                                                   "blocked", 50)
                return False
        return True
示例#4
0
 def targetAction(self):
     if self.source.visual:
         self.application.sound_fire.play()
     for target in self.target_list:
         if type(target) == TacticsCharacter:
             target.takeDamage(
                 DamagePacket(
                     self.source, target,
                     5 - 2 * gridhelper.horizontalDistance(
                         target.coords, self.initial_target.coords), "fire",
                     "burn"))
         if type(target) == TacticsTile:
             if target.visual:
                 self.explosions.append(
                     Explosion(self.application, target.coords,
                               "explosion"))
             for surface in target.surface_effects:
                 surface.startBurning()
示例#5
0
    def follow(self):
        instance_coords = self.map_object.instance.getLocation(
        ).getExactLayerCoordinates()

        # distance from the current partial position to the destination
        dx = (self.destination.x - instance_coords.x)
        dy = (self.destination.y - instance_coords.y)
        dz = (self.destination.z - instance_coords.z)
        distance = sqrt(dx * dx + dy * dy)
        # distance from the origin to the destination
        path_dx = (self.destination.x - self.origin.x)
        path_dy = (self.destination.y - self.origin.y)
        path_dz = (self.destination.z - self.origin.z)
        path_distance = sqrt(path_dx * path_dx + path_dy * path_dy)

        z_scale = 3.0
        grid_distance = gridhelper.horizontalDistance(
            self.origin, self.destination) * z_scale

        if (distance < self.speed) or (grid_distance == 0):
            # pop to the destination
            self.map_object.moveInstance(self.destination)
            return False
        else:
            g = 5.0 / z_scale
            d2 = pow(self.trajectory.range,
                     4) - g * (g * pow(grid_distance, 2) +
                               2 * path_dz * pow(self.trajectory.range, 2))
            angle1 = atan((pow(self.trajectory.range, 2) - sqrt(d2)) /
                          (g * grid_distance))

            # normal partial movement
            instance_coords.x += (dx / distance) * self.speed
            instance_coords.y += (dy / distance) * self.speed
            # z calculation
            instance_coords.z = self.origin.z + grid_distance * (
                1 - distance / path_distance) * tan(angle1) - g * pow(
                    grid_distance * (1 - distance / path_distance),
                    2) / (2 * pow(self.trajectory.range * cos(angle1), 2)) + 2
            self.map_object.moveInstance(instance_coords)
            return True
示例#6
0
    def follow(self):
        # fixed?: inconsistent speed because of using exact layer coordinates instead of map coordinates
        # there's also a rotation problem at some angles, probably for the same reason
        if self.next >= len(self.path):
            #	print "Warning: Next node out of range. Path:"
            #	for node in self.path:
            #		print node.coords.x, node.coords.y, node.coords.z
            return False

        grid = self.map_object.visual.instance.getLocation().getLayer(
        ).getCellGrid()

        next_node = self.path[self.next]
        next_node_coords = grid.toMapCoordinates(next_node.coords)
        instance_coords = self.map_object.visual.instance.getLocation(
        ).getMapCoordinates()
        prev_node = self.path[self.next - 1]
        prev_node_coords = grid.toMapCoordinates(prev_node.coords)

        # distance from the current partial position to the target node
        dx = (next_node_coords.x - instance_coords.x)
        dy = (next_node_coords.y - instance_coords.y)
        dz = (next_node_coords.z - instance_coords.z)
        distance = sqrt(dx * dx + dy * dy)
        # distance from the previous node to the target node
        cell_dx = (next_node_coords.x - prev_node_coords.x)
        cell_dy = (next_node_coords.y - prev_node_coords.y)
        cell_dz = (next_node_coords.z - prev_node_coords.z)
        cell_distance = sqrt(cell_dx * cell_dx + cell_dy * cell_dy)

        if distance < self.speed:
            # pop to next node
            self.next += 1
            self.map_object.visual.moveInstance(next_node.coords)
            continue_route = (self.next < len(self.path))
            if continue_route:
                #print "A:", fife.getAngleBetween(instance_coords, grid.toMapCoordinates(self.path[self.next].coords))
                self.map_object.visual.instance.setRotation(
                    fife.getAngleBetween(
                        instance_coords,
                        grid.toMapCoordinates(self.path[self.next].coords)))
            return continue_route
        else:
            #print "B:", fife.getAngleBetween(instance_coords, next_node_coords)
            self.map_object.visual.instance.setRotation(
                fife.getAngleBetween(instance_coords, next_node_coords))
            # normal partial movement
            instance_coords.x += (dx / distance) * self.speed
            instance_coords.y += (dy / distance) * self.speed
            # z calculation
            if gridhelper.horizontalDistance(prev_node.coords,
                                             next_node.coords) == 1:
                # walking between adjacent nodes
                if cell_dz > 0:
                    # uphill
                    if (distance / cell_distance) < 0.5:
                        # flat movement on target tile
                        instance_coords.z = next_node_coords.z
                    else:
                        # jumping up from previous tile
                        instance_coords.z = prev_node_coords.z + cell_dz - 4 * (
                            0.5 - distance / cell_distance) * (
                                0.5 - distance / cell_distance) * cell_dz
                elif cell_dz < 0:
                    # downhill
                    if (distance / cell_distance) < 0.5:
                        # jumping down on target tile
                        instance_coords.z = prev_node_coords.z + 4 * (
                            0.5 - distance / cell_distance) * (
                                0.5 - distance / cell_distance) * cell_dz
            elif gridhelper.horizontalDistance(prev_node_coords,
                                               next_node_coords) == 2:
                # jumping 2 tiles
                if (distance / cell_distance) > 0.5:
                    # up
                    instance_coords.z = prev_node_coords.z + 1 - 4 * (
                        0.5 - distance / cell_distance) * (
                            0.5 - distance / cell_distance)
                else:
                    # down
                    instance_coords.z = prev_node_coords.z + 1 + 4 * (
                        0.5 - distance / cell_distance) * (
                            0.5 - distance / cell_distance) * (cell_dz - 1)
            self.map_object.visual.moveInstance(
                grid.toExactLayerCoordinates(instance_coords))
            return True
示例#7
0
	def scoreAction(self, action, target, world):
		score = 0
		if action.name == "Kick":
			score += self.scoreDamage(DamagePacket(world.current_character_turn, target, 6, "kinetic", "push"))
		elif action.name == "Throw Stone":
			score += self.scoreDamage(DamagePacket(world.current_character_turn, target, 4, "kinetic"))
		elif action.name == "Fireball":
			targeting_rules = TargetingRules(action.targeting_rules.trajectory, action.targeting_rules.area, False, True, False, False)
			targets = world.getTargetsInArea(world.current_character_turn, target, targeting_rules)
			for aoe_target in targets:
				if type(aoe_target) == TacticsCharacter:
					if aoe_target.cur_HP > 0:
						score += self.scoreDamage(DamagePacket(world.current_character_turn, aoe_target, 5 - 2 * gridhelper.horizontalDistance(target.coords, aoe_target.coords), "fire", "burn"))
		elif action.name == "Cone of Cold":
			targeting_rules = TargetingRules(action.targeting_rules.trajectory, action.targeting_rules.area, False, True, False, False)
			targets = world.getTargetsInArea(world.current_character_turn, target, targeting_rules)
			for aoe_target in targets:
				if type(aoe_target) == TacticsCharacter:
					if aoe_target.cur_HP > 0:
						score += self.scoreDamage(DamagePacket(world.current_character_turn, aoe_target, 4, "cold", "freeze"))
		self.actions_considered += 1
		return score * uniform(1, 1.1)
示例#8
0
    def getTargetsInArea(self, source, target, targeting_rules):
        """Return all objects affected by an action performed by source targeting target under targeting_rules. Source is a character and target is a character, tile or obstacle."""
        targets = []

        if targeting_rules.area.type == targeting_rules.area.AREA_SINGLE:
            targets.append(target)

        if targeting_rules.area.type == targeting_rules.area.AREA_CIRCLE:
            if targeting_rules.can_target_tile:
                for tile in self.tiles:
                    if gridhelper.horizontalDistance(
                            target.coords,
                            tile.coords) < targeting_rules.area.radius and (
                                (target.coords.z - tile.coords.z) <=
                                targeting_rules.area.range_down) and (
                                    (tile.coords.z - target.coords.z) <=
                                    targeting_rules.area.range_up):
                        if self.isLOS(target, tile):
                            targets.append(tile)
            if targeting_rules.can_target_other:
                for char in self.characters:
                    if gridhelper.horizontalDistance(
                            target.coords,
                            char.coords) < targeting_rules.area.radius and (
                                (target.coords.z - char.coords.z) <=
                                targeting_rules.area.range_down) and (
                                    (char.coords.z - target.coords.z) <=
                                    targeting_rules.area.range_up):
                        if self.isLOS(target, char):
                            targets.append(char)
            if targeting_rules.can_target_obstacle:
                for obstacle in self.obstacles:
                    if gridhelper.horizontalDistance(
                            target.coords, obstacle.coords
                    ) < targeting_rules.area.radius and (
                        (target.coords.z - obstacle.coords.z) <=
                            targeting_rules.area.range_down) and (
                                (obstacle.coords.z - target.coords.z) <=
                                targeting_rules.area.range_up):
                        if self.isLOS(target, obstacle):
                            targets.append(obstacle)

        if targeting_rules.area.type == targeting_rules.area.AREA_LINE:
            targets.append(target)

        if targeting_rules.area.type == targeting_rules.area.AREA_CONE:
            if targeting_rules.can_target_tile:
                for tile in self.tiles:
                    if gridhelper.horizontalDistance(
                            source.coords,
                            tile.coords) < targeting_rules.area.radius and (
                                (source.coords.z - tile.coords.z) <=
                                targeting_rules.area.range_down) and (
                                    (tile.coords.z - source.coords.z) <=
                                    targeting_rules.area.range_up):
                        if (gridhelper.calcDirectionDiagonal(
                                source.coords, target.coords)
                                == gridhelper.calcDirection(
                                    source.coords, tile.coords)) or (
                                        gridhelper.calcDirectionDiagonal(
                                            source.coords, target.coords)
                                        == gridhelper.calcDirectionDiagonal(
                                            source.coords, tile.coords)):
                            if self.isLOS(source, tile):
                                targets.append(tile)
            if targeting_rules.can_target_other:
                for char in self.characters:
                    if gridhelper.horizontalDistance(
                            source.coords,
                            char.coords) < targeting_rules.area.radius and (
                                (source.coords.z - char.coords.z) <=
                                targeting_rules.area.range_down) and (
                                    (char.coords.z - source.coords.z) <=
                                    targeting_rules.area.range_up):
                        if (gridhelper.calcDirectionDiagonal(
                                source.coords, target.coords)
                                == gridhelper.calcDirection(
                                    source.coords, char.coords)) or (
                                        gridhelper.calcDirectionDiagonal(
                                            source.coords, target.coords)
                                        == gridhelper.calcDirectionDiagonal(
                                            source.coords, char.coords)):
                            if self.isLOS(source, char):
                                targets.append(char)
            if targeting_rules.can_target_obstacle:
                for obstacle in self.obstacles:
                    if gridhelper.horizontalDistance(
                            source.coords, obstacle.coords
                    ) < targeting_rules.area.radius and (
                        (source.coords.z - obstacle.coords.z) <=
                            targeting_rules.area.range_down) and (
                                (obstacle.coords.z - source.coords.z) <=
                                targeting_rules.area.range_up):
                        if (gridhelper.calcDirectionDiagonal(
                                source.coords, target.coords)
                                == gridhelper.calcDirection(
                                    source.coords, obstacle.coords)) or (
                                        gridhelper.calcDirectionDiagonal(
                                            source.coords, target.coords)
                                        == gridhelper.calcDirectionDiagonal(
                                            source.coords, obstacle.coords)):
                            if self.isLOS(source, obstacle):
                                targets.append(obstacle)

        return targets