コード例 #1
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_double_parent(self):
        level = Level()
        level.upper_layer = np.array([[s, lR, e, lR, f], [kR, w, kR, w, e]],
                                     dtype=object)

        # S--L--L--E
        #  \ |\ |
        #   \| \|
        #    K  K
        start = Start()
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([key1, lock1])
        key1.add_lock_s(lock1)
        lock1.add_child_s([key2, lock2])
        key2.add_lock_s(lock2)
        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, True)
コード例 #2
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_linear_solvable(self):
        level = Level()
        level.upper_layer = np.array([[s, kR, lR, f]], dtype=object)

        # S--K--L--E
        start = Start()
        key = Key()
        lock = Lock()
        end = End()
        start.add_child_s([key, lock])
        key.add_lock_s(lock)
        lock.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key: np.array([0, 1]),
            lock: 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)

        expected_steps = [(start, []), (key, rM), (lock, rM), (end, rM)]
        self.assert_steps_equal(solution.steps, expected_steps)
コード例 #3
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_branch_trivial1(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, kR, lR, e, e, f], [lB, kB, w, w, e, e]], dtype=object)

        # S--K--L--L--E
        #  \      /
        #   K-----
        start = Start()
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([key1, key2])
        key1.add_child_s(lock1)
        key1.add_lock_s(lock1)
        lock1.add_child_s(lock2)
        key2.add_lock_s(lock2)
        lock2.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key1: np.array([0, 1]),
            lock1: np.array([0, 2]),
            key2: np.array([1, 1]),
            lock2: np.array([1, 0]),
            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)
コード例 #4
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_hazard_unsolvable(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, e, Fb, W, W, W, e, fl, e, F, F, e, F, F, e, f]], dtype=object)

        # S--K--L--E
        start = Start()
        key1 = Key("flippers")
        lock1 = Lock("water")
        key2 = Key("fireboots")
        lock2 = Lock("fire1")
        lock3 = Lock("fire2")
        end = End()
        start.add_child_s([key1, lock1])
        key1.add_lock_s(lock1)
        lock1.add_child_s([key2, lock2])
        key2.add_lock_s([lock2, lock3])
        lock2.add_child_s(lock3)
        lock3.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key1: np.array([0, 7]),
            lock1: np.array([0, 4]),
            key2: np.array([0, 2]),
            lock2: np.array([0, 10]),
            lock3: np.array([0, 13]),
            end: np.array([0, 15]),
        }

        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)
コード例 #5
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_sokoban_unsolvable(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, kR, e, e, e, e, g, lR, f], [e, e, b, e, e, e, w, w, e]],
            dtype=object)

        start = Start()
        key = Key("key")
        block = SokobanKey("block")
        water = SokobanLock("water")
        lock = Lock("lock")
        end = End()
        start.add_child_s([key, block, water])
        block.add_lock_s(water)
        key.add_lock_s(lock)
        water.add_child_s(lock)
        lock.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key: np.array([0, 1]),
            block: np.array([1, 2]),
            water: np.array([0, 6]),
            lock: np.array([0, 7]),
            end: np.array([0, 8]),
        }

        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)
コード例 #6
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_collectables_unreachable_collectable(self):
        level = Level()
        level.upper_layer = np.array([[s, e, B, f], [c, e, w, c]],
                                     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, barrier])
        barrier.add_child_s([c1, end])

        positions_map = {
            start: np.array([0, 0]),
            c0: np.array([1, 0]),
            c1: np.array([1, 3]),
            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, False)
コード例 #7
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_linear_trivial(self):
        level = Level()
        level.upper_layer = np.array([[s, kR, lR, f], [e, e, e, e]],
                                     dtype=object)

        # S--K--L--E
        start = Start()
        key = Key("key")
        lock = Lock("lock")
        end = End()
        start.add_child_s(key)
        key.add_lock_s(lock)
        lock.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key: np.array([0, 1]),
            lock: 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, False)
コード例 #8
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_wrong_key_color(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, e, lR, kR], [kR, e, w, w], [e, e, lR, f]], dtype=object)

        start = Start()
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([key1, lock1, lock2])
        lock1.add_child_s(key2)
        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, 0]),
            lock1: np.array([0, 2]),
            key2: np.array([0, 3]),
            lock2: np.array([2, 2]),
            end: np.array([2, 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, False)
コード例 #9
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_difficult(self):
        level = Level()
        level.upper_layer = np.array(
            [[f, e, e, w, e, W, e, w], [e, w, lG, w, e, w, Fb, w],
             [e, w, F, w, W, w, e, w], [e, w, s, w, e, w, F, w],
             [e, w, kR, w, fl, w, e, w], [e, w, e, lR, e, w, kG, w]],
            dtype=object)

        start = Start()
        key_red = Key("red")
        lock_red = Lock("red")
        flippers = Key("flippers")
        water1 = Lock("water1")
        water2 = Lock("water2")
        key_green = Key("green")
        lock_green = Lock("green")
        fire_boots = Key("fireboots")
        fire1 = Lock("fire1")
        fire2 = Lock("fire2")
        end = End()
        start.add_child_s([fire2, key_red, lock_red])
        key_red.add_lock_s(lock_red)
        lock_red.add_child_s([flippers, water1])
        flippers.add_lock_s([water1, water2])
        water1.add_child_s(water2)
        water2.add_child_s([fire_boots, fire1])
        fire_boots.add_lock_s([fire1, fire2])
        fire1.add_child_s(key_green)
        key_green.add_lock_s(lock_green)
        fire2.add_child_s(lock_green)
        lock_green.add_child_s(end)

        # [ f, e, e, w, e, W, e, w],
        # [ e, w,lG, w, e, w,Fb, w],
        # [ e, w, F, w, W, w, e, w],
        # [ e, w, s, w, e, w, F, w],
        # [ e, w,kR, w,fl, w, e, w],
        # [ e, w, e,lR, e, w,kG, w]], dtype=object)
        positions_map = {
            start: np.array([3, 2]),
            key_red: np.array([4, 2]),
            lock_red: np.array([5, 3]),
            flippers: np.array([4, 4]),
            water1: np.array([2, 4]),
            water2: np.array([0, 5]),
            key_green: np.array([5, 6]),
            lock_green: np.array([1, 2]),
            fire_boots: np.array([1, 6]),
            fire1: np.array([3, 6]),
            fire2: np.array([2, 2]),
            end: np.array([0, 0])
        }

        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)
コード例 #10
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_linear_solvable_multicolored_keys(self):
        level = Level()
        level.upper_layer = np.array([[kY, lG, kB, lR, s, kR, lB, kG, lY, f]],
                                     dtype=object)

        # S--K--L--K--L--K--L--K--L--E
        start = Start()
        key_red = Key("red")
        lock_red = Lock("red")
        key_blue = Key("blue")
        lock_blue = Lock("blue")
        key_green = Key("green")
        lock_green = Lock("green")
        key_yellow = Key("yellow")
        lock_yellow = Lock("yellow")
        end = End()

        start.add_child_s([lock_red, key_red, lock_blue])
        lock_red.add_child_s([lock_green, key_blue])
        lock_green.add_child_s(key_yellow)
        lock_blue.add_child_s([lock_yellow, key_green])
        lock_yellow.add_child_s(end)
        key_red.add_child_s(lock_red)
        key_red.add_lock_s(lock_red)
        key_blue.add_child_s(lock_blue)
        key_blue.add_lock_s(lock_blue)
        key_green.add_child_s(lock_green)
        key_green.add_lock_s(lock_green)
        key_yellow.add_child_s(lock_yellow)
        key_yellow.add_lock_s(lock_yellow)

        positions_map = {
            start: np.array([0, 4]),
            key_red: np.array([0, 5]),
            lock_red: np.array([0, 3]),
            key_blue: np.array([0, 2]),
            lock_blue: np.array([0, 6]),
            key_green: np.array([0, 7]),
            lock_green: np.array([0, 1]),
            key_yellow: np.array([0, 0]),
            lock_yellow: np.array([0, 8]),
            end: np.array([0, 9]),
        }

        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)

        expected_steps = [(start, []), (key_red, rM), (lock_red, 2 * lM),
                          (key_blue, lM), (lock_blue, 4 * rM), (key_green, rM),
                          (lock_green, 6 * lM), (key_yellow, lM),
                          (lock_yellow, 8 * rM), (end, rM)]
        self.assert_steps_equal(solution.steps, expected_steps)
コード例 #11
0
    def generate_mission(level, mission_aesthetic):
        node_to_tile = dict()
        solution_node_order = Node.find_all_nodes(level.mission,
                                                  method="topological-sort")

        spatial_graph = SpatialGraph(level.upper_layer)
        mission_spatial_nodes, mission_to_mission_spatial = MissionGenerator.convert_mission_graph_to_spatial_subgraph_form(
            solution_node_order)
        mission_to_spaces_mapping = SubgraphFinder.get_subgraph_mapping(
            spatial_graph.nodes, mission_spatial_nodes)
        if mission_to_spaces_mapping is not None:
            MissionGenerator.apply_mission_mapping_to_level(
                level, solution_node_order, mission_to_mission_spatial,
                mission_to_spaces_mapping, node_to_tile, mission_aesthetic)

            level.required_collectable_count = np.count_nonzero(
                level.upper_layer == Tiles.collectable)
            return Solver.does_level_follow_mission(level)
        return False, None
コード例 #12
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_degenerate_loop_layout(self):
        level = Level()
        level.upper_layer = np.array(
            [[w, w, w, w, w, w, w, w, w], [w, s, w, e, e, e, e, f, w],
             [w, kR, w, w, w, w, lG, w, w], [w, kG, lR, e, e, e, e, e, w],
             [w, e, w, e, e, e, e, kR, w], [w, e, w, w, lR, w, e, w, w],
             [w, e, w, e, e, e, e, e, w], [w, w, w, w, w, w, w, w, w]],
            dtype=object)

        start = Start()
        key0 = Key("key0")
        lock0 = Lock("lock0")
        key1 = Key("key1")
        lock1 = Lock("lock1")
        key2 = Key("key2")
        lock2 = Lock("lock2")
        end = End()
        start.add_child_s([lock0, key0, key2])
        lock0.add_child_s([lock1, key1])
        lock1.add_child_s(lock2)
        lock2.add_child_s(end)
        key0.add_lock_s(lock0)
        key1.add_lock_s(lock1)
        key2.add_lock_s(lock2)

        positions_map = {
            start: np.array([1, 1]),
            key0: np.array([2, 1]),
            key2: np.array([3, 1]),
            lock0: np.array([3, 2]),
            key1: np.array([4, 7]),
            lock1: np.array([5, 4]),
            lock2: np.array([2, 6]),
            end: np.array([1, 7]),
        }

        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)
コード例 #13
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_node_seen_too_soon_incorrect_layout2(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, e, lR, kB], [kR, e, w, w], [e, e, lB, f]], dtype=object)

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

        positions_map = {
            start: np.array([0, 0]),
            key1: np.array([1, 0]),
            lock1: np.array([0, 2]),
            key2: np.array([0, 3]),
            lock2: np.array([2, 2]),
            end: np.array([2, 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, False)
コード例 #14
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_sokoban_solvable_lock_in_middle(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, kR, b, e, lR, e, g, e, f], [e, e, e, e, w, e, w, w, e]],
            dtype=object)

        start = Start()
        key = Key("key")
        block = SokobanKey("block")
        water = SokobanLock("water")
        lock = Lock("lock")
        end = End()
        start.add_child_s([key, block, lock])
        block.add_lock_s([water])
        key.add_lock_s(lock)
        lock.add_child_s(water)
        water.add_child_s(end)

        positions_map = {
            start: np.array([0, 0]),
            key: np.array([0, 1]),
            block: np.array([0, 2]),
            water: np.array([0, 6]),
            lock: np.array([0, 4]),
            end: np.array([0, 8]),
        }

        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)

        expected_steps = [(start, []), (key, rM), (block, []),
                          (lock, dM + 2 * rM + uM + rM),
                          (water, lM + dM + 2 * lM + uM + 4 * rM),
                          (end, 3 * rM)]
        self.assert_steps_equal(solution.steps, expected_steps)
コード例 #15
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    def test_solver_hazard_too_soon(self):
        level = Level()
        level.upper_layer = np.array(
            [[s, e, W, e, fl], [e, fl, w, w, w], [e, e, W, e, f]],
            dtype=object)

        # S--K--L--E
        start = Start()
        flippers1 = Key("flippers 1")
        water1 = Lock("water 1")
        flippers2 = Key("flippers 2")
        water2 = Lock("water 2")
        end = End()

        start.add_child_s([flippers1, water1, water2])
        flippers1.add_lock_s(water1)
        water1.add_child_s(flippers2)
        flippers2.add_lock_s(water2)
        water2.add_child_s(end)

        # [ s, e, W, e,fl],
        # [ e,fl, w, w, w],
        # [ e, e, W, e, f]], dtype=object)

        positions_map = {
            start: np.array([0, 0]),
            flippers1: np.array([1, 1]),
            water1: np.array([0, 2]),
            flippers2: np.array([0, 4]),
            water2: np.array([2, 2]),
            end: np.array([2, 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)
コード例 #16
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    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)
コード例 #17
0
    def add_mission_node(level, solution_node_order, node, node_index,
                         positions_map, node_to_tile, random_positions,
                         start_position, mission_aesthetic):
        original_layer = level.upper_layer.copy()
        for position in random_positions:
            level.upper_layer = original_layer.copy()
            MissionGenerator.add_mission_tile(level.upper_layer, node,
                                              position, positions_map,
                                              node_to_tile, mission_aesthetic)

            Log.print("\n\n")
            Log.print(level)

            if Solver.does_level_follow_mission(
                    level, solution_node_order[:node_index + 1],
                    positions_map):
                was_successful, level = MissionGenerator._generate_mission(
                    level, node_index + 1, solution_node_order, positions_map,
                    node_to_tile, start_position, mission_aesthetic)
                if was_successful:
                    return was_successful, level
                elif not MissionGenerator.is_generator_recursive:
                    return False, level
        return False, level
コード例 #18
0
ファイル: test_solver.py プロジェクト: bjatkin/dungeon-design
    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)
コード例 #19
0
    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