def test_two_keys_soon_unneeded(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, kR, lR, e, e, f], [e, kR, lR, e, e, e]], dtype=object)

        # S----------
        # |    |    |
        # lR   kR   kB
        # |
        # lB
        # |
        # E
        start = Start()
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([lock1, key1, key2])
        lock1.add_child_s(lock2)
        lock2.add_child_s(end)
        key1.add_lock_s(lock1)
        key2.add_lock_s(lock2)

        positions_map = {
            start: np.array([0, 0]),
            key1: np.array([1, 1]),
            lock1: np.array([0, 2]),
            key2: np.array([0, 1]),
            lock2: np.array([0, 3]),
            end: np.array([0, 5]),
        }

        level.mission = start
        level.positions_map = positions_map
        does_level_follow_mission, solution = Solver.does_level_follow_mission(
            level)
        self.assertEqual(does_level_follow_mission, False)
    def test_solver_collectables(self):
        level = Level()
        level.upper_layer = np.array([[s, e, B, f], [c, c, w, e]],
                                     dtype=object)
        level.required_collectable_count = 2

        start = Start()
        c0 = Collectable("c0")
        c1 = Collectable("c1")
        barrier = CollectableBarrier("B", collectables=[c0, c1])
        end = End()

        start.add_child_s([c0, c1, barrier])
        barrier.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            c0: np.array([1, 0]),
            c1: np.array([1, 1]),
            barrier: np.array([0, 2]),
            end: np.array([0, 3]),
        }

        level.mission = start
        level.positions_map = positions_map
        does_level_follow_mission, solution = Solver.does_level_follow_mission(
            level)
        self.assertEqual(does_level_follow_mission, True)

        if solution.steps[1][0] == c1:
            expected_steps = [(start, []), (c1, dM + rM), (c0, lM),
                              (barrier, rM + uM + rM), (end, rM)]
        else:
            expected_steps = [(start, []), (c0, dM), (c1, rM),
                              (barrier, uM + rM), (end, rM)]
        self.assert_steps_equal(solution.steps, expected_steps)
    def test_node_seen_too_soon_incorrect_layout(self):
        level = Level()
        level.upper_layer = np.array([[s, lR, e, lB, f], [kR, w, kB, w, w]],
                                     dtype=object)

        # S---------
        # |   |    |
        # L1  L2   K1
        # |   |
        # K2  E
        start = Start()
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([lock1, lock2, key1])
        key1.add_lock_s(lock1)
        key2.add_lock_s(lock2)
        lock1.add_child_s(key2)
        lock2.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key1: np.array([1, 0]),
            lock1: np.array([0, 1]),
            key2: np.array([1, 2]),
            lock2: np.array([0, 3]),
            end: np.array([0, 4]),
        }

        level.mission = start
        level.positions_map = positions_map
        does_level_follow_mission, solution = Solver.does_level_follow_mission(
            level)
        self.assertEqual(does_level_follow_mission, False)
    def get_level(self):
        start = Start()
        key = Key()
        lock = Lock()
        c0 = Collectable()
        sokoban_key = SokobanKey()
        sokoban_lock = SokobanLock()
        c1 = Collectable()
        key2 = Key()
        lock2 = Lock()
        barrier = CollectableBarrier()
        end = End()
        start.add_child_s([key, lock, c0])
        key.add_lock_s(lock)
        lock.add_child_s([sokoban_key, sokoban_lock, c1])
        sokoban_key.add_lock_s(sokoban_lock)
        sokoban_lock.add_child_s([key2, lock2])
        key2.add_lock_s(lock2)
        lock2.add_child_s(barrier)
        barrier.add_key_s([c0, c1])
        barrier.add_child_s(end)

        level = Level()
        level.mission = start
        level.upper_layer = np.array([
            [s, e, w, e, e, e, w, e],
            [e, e, w,kB, e, e,lB, B],
            [e, e, w, e, e, e, w, e],
            [e,kR, w, g, w, w, w, f],
            [e, e, w, e, c, e, w, e],
            [e, e, w, e, e, e, w, e],
            [c, e,lR, e, b, e, w, e],
            [e, e, w, e, e, e, w, e]
        ])
        level.positions_map = {
            start:          np.array([0,0]),
            key:            np.array([3,1]),
            lock:           np.array([6,2]),
            c0:             np.array([6,0]),
            c1:             np.array([4,4]),
            sokoban_key:    np.array([6,4]),
            sokoban_lock:   np.array([3,3]),
            key2:           np.array([1,3]),
            lock2:          np.array([1,6]),
            barrier:        np.array([1,7]),
            end:            np.array([3,7])}

        solution = Solver.does_level_follow_mission(level)

        level.solution = Solution(np.array([0, 0]))
        level.solution.add_step(start, [])
        level.solution.add_step(c0, 6*dM)
        level.solution.add_step(key, 3*uM + rM)
        level.solution.add_step(lock, 3*dM + rM)
        level.solution.add_step(c1, rM + uM + rM + uM)
        level.solution.add_step(sokoban_key, [])
        level.solution.add_step(sokoban_lock, dM + rM + dM + lM + dM + lM + 3*uM)
        level.solution.add_step(key2, 3*uM)
        level.solution.add_step(lock2, 3*rM)
        level.solution.add_step(barrier, rM)
        level.solution.add_step(end, dM)

        return level