# Copyright (c) 1997 Cabochon Technologies, Inc.  All rights reserved.

"""
Teleports caster randomly a few squares away.
Author: rhialto
"""

from wyvern.lib import Point, Range
from wyvern.lib.classes.magic import Spell

class blink(Spell):

    def start(self):
        """Tries a number of times to teleport the caster."""

        if self.fails_preconditions():
            return

        level = self.compute_level()

        failed, x, y = self.computeDestination(level)

        if failed:
            self.tellCaster('The spell fails!')
            return

        path = self.agent.map.virtualPath
        cmd = "teleport %s %d %d" % (path, x, y)

        self.agent.commandNow(cmd)


    def computeDestination(self, level):
        """Finds a destination point for the teleport.

        Pass:
          - level:  the spell level (affects num retries)

        Returns three values:
          - failed:  true if we couldn't find a free point
                     inside the map bounds, else false

          - x:   the x location to blink to (if not failed)
          - y:   the y location to blink to (if not failed)
        """

        agent = self.agent
        map = self.agent.map
        bounds = map.bounds

        failed = 1
        success = 0

        ref = agent.referenceLoc
        refx, refy = ref.x(), ref.y()

        count = level

        while count > 0:

            count = count - 1

            # choose random location 0 to 3 squares away
            # (maybe 3 should go up with another element skill?)

            x, y = self.random_offsets()
            nx = refx + x
            ny = refy + y

            p = Point(nx, ny)
            if (bounds.contains(nx, ny) and agent.canMoveTo(map, p)):
                return success, nx, ny

        return failed, 0, 0



    def random_offsets(self):
        """Chooses a random pair of (x, y) offsets.
        Will not return (0, 0).
        """

        x = 0
        y = 0
        while x == 0 and y == 0:
            x = Range.randomValue(-3, 3)
            y = Range.randomValue(-3, 3)
        return x, y


    def fails_preconditions(self):
        """Returns true if there's no caster, or the map
        doesn't support teleporting.

        Issues appropriate message to caster.
        """

        if self.agent is None or self.agent.map is None:
            return 1

        agent = self.agent
        if agent.map.hasProperty('no-teleport'):
            if self.agent.isWizard():
                return 0
            agent.message('You cannot teleport here.')
            return 1

        # passed all preconditions
        return 0


    def compute_level(self):
        """Computes spell level based on SPIRIT skill.
        Never returns less than 1.
        """
        level = self.getLevel(self.SPIRIT) * 2 + 4
        if level < 1:  level = 1
        return level