Пример #1
0
    def build_cycle(self, env: Environment) -> Optional[List[Vector]]:
        # Attempt to build the list of next actions
        head = env.snake.head()
        tail = env.snake.tail()
        # We build a cycle by building the longest path from the snakes
        # head to it's tail. If the snake is only 1 tile long, then we
        # make an 'adjustment' and choose a tile next to the head
        # as the target, essentially faking a tail.
        # This is necessary as our algorithm won't return any actions
        # if the from tile is the same as the target tile.
        if head == tail:
            if tail.x > 1:
                adjustment = Vector(-1, 0)
            else:
                adjustment = Vector(1, 0)
            tail = tail + adjustment
        built = self._bfsl.longest_path(env, head, tail,
                                        env.snake.action.vector)
        if built is None:
            return None

        # We've built the longest path from head to tail, but we need to
        # check that it covers all vectors.
        if len(built) != env.available_tiles_count():
            return None
        built.append(head)
        return built
Пример #2
0
 def setUp(self) -> None:
     self._vectors = [
         Vector(1, 1),
         Vector(1, 2),
         Vector(1, 3),
     ]
     self._o = objects.Object(self._vectors)
 def _unseen_adjacent_vectors(self, env: Environment, vector: Vector,
                              seen_vectors: List[Vector]) -> List[Vector]:
     adjacent_vectors = [
         Vector(
             vector.x - 1,
             vector.y,
         ),
         Vector(
             vector.x,
             vector.y - 1,
         ),
         Vector(
             vector.x + 1,
             vector.y,
         ),
         Vector(
             vector.x,
             vector.y + 1,
         ),
     ]
     searchable_vectors = []
     for v in adjacent_vectors:
         if v in seen_vectors:
             continue
         if self._should_search_vector(env, v):
             searchable_vectors.append(v)
     return searchable_vectors
Пример #4
0
 def test_unit(self):
     """
     L{Vector.unit} returns a L{Vector} in the same direction as the
     original, but with magnitude 1.
     """
     v = Vector(1, 2, 3)
     u = v.unit()
     scale = (1 ** 2 + 2 ** 2 + 3 ** 2) ** 0.5
     self.assertEquals(u, Vector(1 / scale, 2 / scale, 3 / scale))
Пример #5
0
 def test_move_to_not_adjacent(self):
     invalid_vectors = [
         Vector(5, 3),
         Vector(7, 5),
         Vector(5, 7),
         Vector(3, 5)
     ]
     for v in invalid_vectors:
         s = objects.Snake([Vector(5, 5)])
         self.assertFalse(s.move_to(v))
         self.assertEqual(len(s), 1)
Пример #6
0
 def _vectors_of(self, t: tile.Tile) -> List[Vector]:
     vectors = []
     for y in range(0, self._height):
         for x in range(0, self._width):
             if self._tiles[y][x] == t:
                 vectors.append(Vector(x, y))
     return vectors
Пример #7
0
 def _random_available_position(self) -> Vector:
     t = None
     rand_x, rand_y = 0, 0
     while t is None or t != tile.EMPTY:
         rand_x = random.randint(1, self._height - 1)
         rand_y = random.randint(1, self._width - 1)
         t = self._tiles[rand_x][rand_y]
     return Vector(rand_x, rand_y)
Пример #8
0
 def test_move_to_existing_vector(self):
     invalid_vectors = [Vector(6, 5), Vector(5, 6)]
     for v in invalid_vectors:
         s = objects.Snake(
             [Vector(5, 5),
              Vector(6, 5),
              Vector(6, 6),
              Vector(5, 6)])
         self.assertFalse(s.move_to(v))
         self.assertEqual(len(s), 4)
    def shortest_path(self, environment: Environment, from_vector: Vector,
                      to_vector: Vector,
                      first_move: Vector) -> Optional[List[Vector]]:
        # Search for path for fruit. Returned vector has the next vector.
        fruit_vector = self._search_from(environment, from_vector, to_vector,
                                         first_move)
        if fruit_vector is None:
            return None
        vector_steps = []

        # Traverse backwards from the fruit towards to snake
        current_step = fruit_vector
        while True:
            vector_steps.append(Vector(current_step.x, current_step.y))
            if isinstance(current_step, OwnedVector):
                current_step = current_step.owner
            else:
                break

        # We traversed from fruit to snake, so reverse the list
        vector_steps.reverse()
        return vector_steps
    def _search_from(self, env: Environment, start_vector: Vector,
                     end_vector: Vector,
                     first_move: Vector) -> Optional[OwnedVector]:
        seen_vectors = [start_vector]  # Don't process more than once
        queue = [start_vector]  # First-in-first-out queue

        while queue:
            # Get the first vector from the queue
            vector = queue.pop(0)
            # Check if the tile at the vector is the goal
            if vector == end_vector:
                return vector
            # Get adjacent vectors that we haven't seen yet
            adjacent_vectors = self._unseen_adjacent_vectors(
                env, vector, seen_vectors)
            # Add each adjacent vector to the queue
            for v in adjacent_vectors:
                if vector == start_vector:
                    dir_vec = v - vector
                    if first_move.is_reverse(dir_vec):
                        continue
                queue.append(OwnedVector(v.x, v.y, vector))
                seen_vectors.append(v)
Пример #11
0
 def _vector_of(self, t: tile.Tile) -> Optional[Vector]:
     for y in range(0, self._height):
         for x in range(0, self._width):
             if self._tiles[y][x] == t:
                 return Vector(x, y)
     return None
Пример #12
0
 def setUp(self) -> None:
     self._vector = Vector(4, 3)
     self._f = objects.Fruit(self._vector)
Пример #13
0
 def test_at_vector(self):
     self.assertTrue(self._f.at_vector(Vector(4, 3)))
     self.assertFalse(self._f.at_vector(Vector(1, 2)))
     self.assertFalse(self._f.at_vector(Vector(1, 3)))
Пример #14
0
from typing import List

from game.vector import Vector


class Action:
    def __init__(self, vector: Vector, description: str):
        self.vector = vector
        self.description = description

    def __eq__(self, other: 'Action'):
        return self.vector == other.vector


NONE = Action(Vector(0, 0), "none")
LEFT = Action(Vector(-1, 0), "left")
UP = Action(Vector(0, -1), "up")
RIGHT = Action(Vector(1, 0), "right")
DOWN = Action(Vector(0, 1), "down")

ALL = (
    LEFT,
    UP,
    RIGHT,
    DOWN,
)


def vector_to_action(vector: Vector) -> Action:
    for a in ALL:
        if a.vector == vector:
Пример #15
0
 def test_vectors_to_action(self):
     vectors = [Vector(-1, 0), Vector(1, 0), Vector(0, -1), Vector(0, 1)]
     self.assertEqual(action.vectors_to_action(vectors),
                      [action.LEFT, action.RIGHT, action.UP, action.DOWN])
Пример #16
0
 def test_vector_to_action(self):
     self.assertEqual(action.vector_to_action(Vector(-1, 0)), action.LEFT)
     self.assertEqual(action.vector_to_action(Vector(1, 0)), action.RIGHT)
     self.assertEqual(action.vector_to_action(Vector(0, -1)), action.UP)
     self.assertEqual(action.vector_to_action(Vector(0, 1)), action.DOWN)
Пример #17
0
 def _normalise_vector(self, vector: Vector) -> Vector:
     return Vector(vector.x * self.tile_width, vector.y * self.tile_height)
Пример #18
0
 def test_move_to_valid_vectors(self):
     valid_vectors = [Vector(4, 5), Vector(5, 4), Vector(5, 6)]
     for v in valid_vectors:
         s = objects.Snake([Vector(5, 5), Vector(6, 5)])
         self.assertTrue(s.move_to(v))
         self.assertEqual(len(s), 3)
Пример #19
0
 def test_tail(self):
     self.assertEqual(self._s.tail(), Vector(3, 0))
Пример #20
0
 def test_head(self):
     self.assertEqual(self._s.head(), Vector(1, 2))
Пример #21
0
 def setUp(self) -> None:
     ######
     #  TSS
     #HSS S
     #  S S
     #  S S
     #  SSS
     ######
     self._s = objects.Snake([
         Vector(1, 2),
         Vector(2, 2),
         Vector(3, 2),
         Vector(3, 3),
         Vector(3, 4),
         Vector(3, 5),
         Vector(4, 5),
         Vector(5, 5),
         Vector(5, 4),
         Vector(5, 3),
         Vector(5, 2),
         Vector(5, 1),
         Vector(5, 0),
         Vector(4, 0),
         Vector(3, 0),
     ])