diff --git a/app/css/bootcamp/exercises/maze.css b/app/css/bootcamp/exercises/maze.css
index e6610addb4..86abf4767c 100644
--- a/app/css/bootcamp/exercises/maze.css
+++ b/app/css/bootcamp/exercises/maze.css
@@ -71,22 +71,22 @@
background: radial-gradient(
circle,
transparent 20%,
- #f9dcdc 20%,
- #f9dcdc 80%,
+ #dcdef9 20%,
+ #dcdef9 80%,
transparent 80%,
transparent
),
radial-gradient(
circle,
transparent 20%,
- #f9dcdc 20%,
- #f9dcdc 80%,
+ #dcdef9 20%,
+ #dcdef9 80%,
transparent 80%,
transparent
)
10px 10px,
- linear-gradient(#f74545 0.8px, transparent 0.8px) 0 -0.4px,
- linear-gradient(90deg, #f74545 0.8px, #f9dcdc 0.8px) -0.4px 0;
+ linear-gradient(#6645f7 0.8px, transparent 0.8px) 0 -0.4px,
+ linear-gradient(90deg, #6645f7 0.8px, #dcdef9 0.8px) -0.4px 0;
background-size: 10px 10px, 10px 10px, 5px 5px, 5px 5px;
}
&.start {
diff --git a/app/javascript/components/bootcamp/SolveExercisePage/exercises/maze/MazeExercise.tsx b/app/javascript/components/bootcamp/SolveExercisePage/exercises/maze/MazeExercise.tsx
index 0ba1bbb15a..4f99e5e82e 100644
--- a/app/javascript/components/bootcamp/SolveExercisePage/exercises/maze/MazeExercise.tsx
+++ b/app/javascript/components/bootcamp/SolveExercisePage/exercises/maze/MazeExercise.tsx
@@ -520,6 +520,9 @@ export default class MazeExercise extends Exercise {
this.character.style.left = `${this.characterPosition.x * this.squareSize}%`
this.character.style.top = `${this.characterPosition.y * this.squareSize}%`
}
+ public getLayout(_: ExecutionContext): SquareInstance[][] {
+ return Jiki.wrapJSToJikiObject(this.mazeLayout)
+ }
public announceEmojis(_: ExecutionContext, emojis: Jiki.Dictionary) {
this.collectedEmojis = Jiki.unwrapJikiObject(emojis)
}
@@ -575,5 +578,10 @@ export default class MazeExercise extends Exercise {
func: this.removeEmoji.bind(this),
description: 'removed the emoji from the current square',
},
+ {
+ name: 'get_layout',
+ func: this.getLayout.bind(this),
+ description: 'got the current layout of the maze',
+ },
]
}
diff --git a/bootcamp_content/projects/maze/config.json b/bootcamp_content/projects/maze/config.json
index 0105059ba6..db02f18276 100644
--- a/bootcamp_content/projects/maze/config.json
+++ b/bootcamp_content/projects/maze/config.json
@@ -9,6 +9,7 @@
"look-around",
"emoji-collector",
"squares-not-strings",
- "omniscience"
+ "omniscience",
+ "classy-maze"
]
}
diff --git a/bootcamp_content/projects/maze/exercises/omniscience/config.json b/bootcamp_content/projects/maze/exercises/omniscience/config.json
index 843a5ed31a..0dda6a0958 100644
--- a/bootcamp_content/projects/maze/exercises/omniscience/config.json
+++ b/bootcamp_content/projects/maze/exercises/omniscience/config.json
@@ -49,7 +49,7 @@
],
"checks": [
{
- "property": "position",
+ "function": "new Maze(get_layout())",
"value": [4, 6],
"error_html": "You didn't reach the end of the maze."
}
diff --git a/bootcamp_content/projects/maze/exercises/pacman/config.json b/bootcamp_content/projects/maze/exercises/pacman/config.json
new file mode 100644
index 0000000000..92cd8030c2
--- /dev/null
+++ b/bootcamp_content/projects/maze/exercises/pacman/config.json
@@ -0,0 +1,342 @@
+{
+ "title": "Omniscience",
+ "description": "Navigate the maze without any help!",
+ "level": 9,
+ "idx": 4,
+ "project_type": "maze",
+ "tests_type": "state",
+ "blocks_level_progression": false,
+ "exercise_functions": [
+ "move",
+ "turn_left",
+ "turn_right",
+ "announce_emojis",
+ "get_initial_maze"
+ ],
+ "interpreter_options": {
+ "max_repeat_until_game_over_iterations": 50,
+ "max_total_loop_iterations": 20000,
+ "max_total_execution_time": 30000,
+ "time_per_frame": 0.01
+ },
+ "tasks": [
+ {
+ "name": "A straight path",
+ "tests": [
+ {
+ "slug": "diamonds",
+ "name": "Collect the diamonds",
+ "function": "build_maze",
+ "args": ["get_layout()"],
+ "codeRun": "new Maze(...)",
+ "description_html": "Collect and announce the diamonds.",
+ "setup_functions": [
+ ["enableEmojiMode"],
+ ["enableOOP"],
+ [
+ "setupGrid",
+ [
+ [
+ [1, 1, 1, 1, 2, 1, 1],
+ [1, 1, 1, 1, 0, 1, 1],
+ [1, 1, 1, 1, 0, 1, 1],
+ [1, 1, 1, 1, 0, 1, 1],
+ [1, 1, 1, 1, 0, 1, 1],
+ [1, 1, 1, 1, 0, 1, 1],
+ [1, 1, 1, 1, 3, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [4, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [4, 6],
+ "error_html": "You didn't reach the end of the maze."
+ }
+ ]
+ },
+ {
+ "slug": "left-turn",
+ "name": "A single left turn",
+ "setup_functions": [
+ [
+ "setupGrid",
+ [
+ [
+ [2, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 0, 0, 0, 0, 0, 0, 0, 3],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [0, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [8, 5],
+ "error_html": "You didn't reach the end of the maze."
+ },
+ {
+ "property": "direction",
+ "value": "right",
+ "error_html": "You seem to have done an extra unnecessary turn at the end."
+ }
+ ]
+ },
+ {
+ "slug": "right-turn",
+ "name": "A single right turn",
+ "setup_functions": [
+ [
+ "setupGrid",
+ [
+ [
+ [1, 1, 1, 1, 1, 1, 1, 1, 2],
+ [1, 1, 1, 1, 1, 1, 1, 1, 0],
+ [1, 1, 1, 1, 1, 1, 1, 1, 0],
+ [1, 1, 1, 1, 1, 1, 1, 1, 0],
+ [1, 1, 1, 1, 1, 1, 1, 1, 0],
+ [3, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [8, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [0, 5],
+ "error_html": "You didn't reach the end of the maze."
+ }
+ ]
+ },
+ {
+ "slug": "forks",
+ "name": "Choose left if you can, otherwise choose right",
+ "setup_functions": [
+ [
+ "setupGrid",
+ [
+ [
+ [2, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 0, 0, 0, 0, 3],
+ [0, 1, 1, 1, 0, 1, 1, 1, 1],
+ [0, 1, 1, 1, 0, 1, 1, 1, 1],
+ [0, 0, 0, 0, 0, 1, 1, 1, 1],
+ [1, 4, 1, 1, 4, 1, 1, 1, 1],
+ [1, 4, 4, 4, 4, 1, 1, 1, 1],
+ [1, 1, 1, 1, 4, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [0, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [8, 2],
+ "error_html": "You didn't reach the end of the maze."
+ }
+ ]
+ },
+
+ {
+ "slug": "turn-around",
+ "name": "Turn around if you can't move straight, left, or right",
+ "setup_functions": [
+ [
+ "setupGrid",
+ [
+ [
+ [1, 1, 1, 2, 1, 1, 1, 1, 1],
+ [1, 1, 1, 0, 1, 1, 1, 1, 1],
+ [1, 1, 1, 0, 1, 1, 1, 1, 1],
+ [1, 4, 4, 0, 1, 1, 0, 1, 1],
+ [1, 4, 1, 0, 1, 1, 0, 1, 1],
+ [1, 4, 4, 0, 0, 0, 0, 0, 1],
+ [1, 1, 1, 0, 1, 1, 1, 1, 1],
+ [3, 0, 0, 0, 1, 1, 1, 1, 1],
+ [1, 1, 1, 0, 1, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [3, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [0, 7],
+ "error_html": "You didn't reach the end of the maze."
+ }
+ ]
+ },
+ {
+ "slug": "forks-2",
+ "name": "Choose right if you can, otherwise choose left",
+ "setup_functions": [
+ [
+ "setupGrid",
+ [
+ [
+ [2, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 0, 0, 1, 1, 1, 1],
+ [0, 1, 1, 1, 0, 0, 0, 0, 1],
+ [0, 1, 1, 0, 0, 1, 0, 1, 1],
+ [0, 1, 1, 1, 0, 1, 0, 1, 1],
+ [0, 0, 0, 0, 0, 1, 0, 0, 1],
+ [1, 4, 1, 1, 0, 1, 1, 0, 1],
+ [1, 4, 4, 4, 0, 1, 0, 0, 1],
+ [1, 1, 1, 1, 3, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [0, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [4, 8],
+ "error_html": "You didn't reach the end of the maze."
+ }
+ ]
+ },
+ {
+ "slug": "poo",
+ "name": "Watch out!",
+ "description_html": "Collect the animals - not their waste!",
+ "setup_functions": [
+ ["enableEmojiMode"],
+ ["enableOOP"],
+ [
+ "setupGrid",
+ [
+ [
+ [2, 1, 1, 1, 1, 1, 1, 1, 1],
+ [0, 1, 1, 0, 0, 1, 1, 1, 1],
+ [0, 1, 1, 1, 0, 0, 0, 0, 1],
+ ["🐶", 1, 1, 0, 0, 1, 0, 1, 1],
+ [0, 1, 1, 1, 0, 1, 0, 1, 1],
+ [0, 0, 0, "🐈", "🐶", 1, 0, 0, 1],
+ [1, 4, 1, 1, 0, 1, 1, 5, 1],
+ [1, 4, 4, 4, 0, 1, 0, "🐶", 1],
+ [1, 1, 1, 1, 3, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [0, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [4, 8],
+ "error_html": "You didn't reach the end of the maze."
+ },
+ {
+ "property": "collectedEmojis",
+ "value": { "🐈": 1, "🐶": 2 },
+ "error_html": "You didn't report the collected emojis correctly. We expected you to report:
{\"🐈\": 1, \"🐶\": 2 }
"
+ }
+ ]
+ },
+ {
+ "slug": "only-once",
+ "name": "Only once!",
+ "description_html": "Make sure you only collect things once!",
+ "setup_functions": [
+ ["enableEmojiMode"],
+ ["enableOOP"],
+ [
+ "setupGrid",
+ [
+ [
+ [3, 1, 0, 0, 2, 1, 1, 1, 1],
+ [0, 1, "🎀", 1, "🩷", 1, 1, 1, 1],
+ ["👑", 1, 0, 1, 0, 0, 0, "🩷", 1],
+ ["👑", 0, 0, 1, 0, 1, 4, 1, 1],
+ [0, 1, 4, 1, 0, 1, 4, 1, 1],
+ [5, 0, 0, 1, 0, 1, 4, 1, 1],
+ [1, 4, 1, 1, "🩷", 4, 4, 1, 1],
+ [1, 4, 4, 4, 0, 1, 1, 1, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["down"]],
+ ["setupPosition", [4, 0]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [0, 0],
+ "error_html": "You didn't reach the end of the maze."
+ },
+ {
+ "property": "collectedEmojis",
+ "value": { "🩷": 3, "🎀": 1, "👑": 2 },
+ "error_html": "You didn't report the collected emojis correctly. We expected you to report:
{ \"🩷\": 3, \"🎀\": 1, \"👑\": 2 }
"
+ }
+ ]
+ },
+ {
+ "slug": "random-emojis",
+ "name": "Random Emojis!",
+ "description_html": "Different emojis every time!",
+ "setup_functions": [
+ ["enableEmojiMode"],
+ ["enableOOP"],
+ [
+ "setupGrid",
+ [
+ [
+ [1, 1, 0, 0, 0, 1, 1, 1, 1],
+ [3, 1, 6, 1, 6, 1, 1, 1, 1],
+ [6, 1, 0, 1, 0, 0, 0, 6, 1],
+ [6, 0, 0, 1, 1, 1, 4, 0, 1],
+ [0, 1, 0, 1, 1, 0, 4, 0, 1],
+ [0, 0, 6, 1, 1, 1, 4, 0, 1],
+ [6, 5, 6, 0, 6, 0, 4, 6, 1],
+ [1, 5, 5, 5, 0, 1, 1, 0, 2],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1]
+ ]
+ ]
+ ],
+ ["setupDirection", ["left"]],
+ ["setupPosition", [8, 7]]
+ ],
+ "checks": [
+ {
+ "property": "position",
+ "value": [0, 1],
+ "error_html": "You didn't reach the end of the maze."
+ },
+ {
+ "function": "randomEmojisAllCollected",
+ "matcher": "toBeTrue",
+ "error_html": "You didn't report the collected emojis correctly."
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/bootcamp_content/projects/maze/exercises/pacman/example.jiki b/bootcamp_content/projects/maze/exercises/pacman/example.jiki
new file mode 100644
index 0000000000..622b21b55b
--- /dev/null
+++ b/bootcamp_content/projects/maze/exercises/pacman/example.jiki
@@ -0,0 +1,222 @@
+function has_key with dict, key do
+ for each k,v in dict do
+ if k == key do
+ return true
+ end
+ end
+ return false
+end
+
+function calculate_starting_position with maze do
+ for each row in maze indexed by row_idx do
+ for each cell in row indexed by col_idx do
+ if cell.is_start do
+ return {"row": row_idx, "col": col_idx}
+ end
+ end
+ end
+end
+
+function calculate_starting_direction with maze, pos do
+ if space_free_below(maze, pos) do
+ return "down"
+ else if space_free_left(maze, pos) do
+ return "left"
+ else if space_free_right(maze, pos) do
+ return "right"
+ else if space_free_above(maze, pos) do
+ return "up"
+ end
+end
+
+function check_boundaries with maze, row, col do
+ if row < 1 or row > 9 or col < 1 or col > 9 do
+ return false
+ end
+ return true
+end
+
+function space_free with maze, row, col do
+ if not check_boundaries(maze, row, col) do
+ return false
+ end
+
+ set square to maze[row][col]
+
+ return !square.is_wall and square.in_maze and square.contents != "🔥" and square.contents != "💩"
+end
+
+function can_move with maze, pos do
+ if pos["direction"] == "down" do
+ return space_free_below(maze, pos)
+ else if pos["direction"] == "up" do
+ return space_free_above(maze, pos)
+ else if pos["direction"] == "left" do
+ return space_free_left(maze, pos)
+ else if pos["direction"] == "right" do
+ return space_free_right(maze, pos)
+ end
+end
+
+function can_turn_left with maze, pos do
+ if pos["direction"] == "up" do
+ return space_free_left(maze, pos)
+ else if pos["direction"] == "right" do
+ return space_free_above(maze, pos)
+ else if pos["direction"] == "down" do
+ return space_free_right(maze, pos)
+ else if pos["direction"] == "left" do
+ return space_free_below(maze, pos)
+ end
+end
+
+function can_turn_right with maze, pos do
+ if pos["direction"] == "up" do
+ return space_free_right(maze, pos)
+ else if pos["direction"] == "right" do
+ return space_free_below(maze, pos)
+ else if pos["direction"] == "down" do
+ return space_free_left(maze, pos)
+ else if pos["direction"] == "left" do
+ return space_free_above(maze, pos)
+ end
+end
+
+function space_free_above with maze, pos do
+ return space_free(maze, pos["row"] - 1, pos["col"])
+end
+
+function space_free_below with maze, pos do
+ return space_free(maze, pos["row"] + 1, pos["col"])
+end
+
+function space_free_left with maze, pos do
+ return space_free(maze, pos["row"], pos["col"] - 1)
+end
+
+function space_free_right with maze, pos do
+ return space_free(maze, pos["row"], pos["col"] + 1)
+end
+
+
+//----
+
+
+
+
+
+
+
+function check_direction with direction do
+ set space to look(direction)
+ return !space.is_wall and space.in_maze and space.contents != "🔥" and space.contents != "💩"
+end
+
+function current_square with maze, position do
+ return maze[pos["row"]][pos["col"]]
+end
+
+function handle_move with maze, pos do
+ move()
+
+ if(pos["direction"] == "up") do
+ change pos["row"] to pos["row"] - 1
+ else if(pos["direction"] == "down") do
+ change pos["row"] to pos["row"] + 1
+ else if(pos["direction"] == "left") do
+ change pos["col"] to pos["col"] - 1
+ else if(pos["direction"] == "right") do
+ change pos["col"] to pos["col"] + 1
+ end
+ change pos["square"] to maze[pos["row"]][pos["col"]]
+
+ return pos
+end
+
+function collect with current_square, emojis do
+ set emoji to current_square.contents
+ if emoji == "" do
+ return emojis
+ end
+
+ current_square.remove_emoji()
+
+ if has_key(emojis, emoji) do
+ change emojis[emoji] to emojis[emoji] + 1
+ else do
+ change emojis[emoji] to 1
+ end
+
+ return emojis
+end
+
+function turn_around do
+ turn_right()
+ turn_right()
+end
+
+function direction_string_to_num with direction do
+ if direction == "up" do
+ return 0
+ else if direction == "right" do
+ return 1
+ else if direction == "down" do
+ return 2
+ else if direction == "left" do
+ return 3
+ end
+end
+
+function direction_num_to_string with direction do
+ if direction == 0 do
+ return "up"
+ else if direction == 1 do
+ return "right"
+ else if direction == 2 do
+ return "down"
+ else if direction == 3 do
+ return "left"
+ end
+end
+
+function change_direction with direction, changer do
+ set num to direction_string_to_num(direction)
+ change num to (num + changer) % 4
+ return direction_num_to_string(num)
+end
+
+function turn_if_required with maze, position do
+ if can_turn_left(maze, position) do
+ turn_left()
+ change position["direction"] to change_direction(position["direction"], 3)
+ return position
+ else if can_move(maze, position) do
+ return position
+ else if can_turn_right(maze, position) do
+ turn_right()
+ change position["direction"] to change_direction(position["direction"], 1)
+ return position
+ else do
+ turn_around()
+ change position["direction"] to change_direction(position["direction"], 2)
+ return position
+ end
+end
+
+set maze to get_initial_maze()
+
+set pos to calculate_starting_position(maze)
+change pos["square"] to maze[pos["row"]][pos["col"]]
+change pos["direction"] to calculate_starting_direction(maze, pos)
+
+set emojis to {}
+
+repeat_until_game_over do
+ change pos to turn_if_required(maze, pos)
+ change pos to handle_move(maze, pos)
+ change emojis to collect(pos["square"], emojis)
+
+ if pos["square"].is_finish do
+ announce_emojis(emojis)
+ end
+end
\ No newline at end of file
diff --git a/bootcamp_content/projects/maze/exercises/pacman/introduction.md b/bootcamp_content/projects/maze/exercises/pacman/introduction.md
new file mode 100644
index 0000000000..48519237ae
--- /dev/null
+++ b/bootcamp_content/projects/maze/exercises/pacman/introduction.md
@@ -0,0 +1,74 @@
+# Omniscience
+
+So far in the maze exercises, you've gone from using a high-level `can_turn_right()` function, to using a slightly lower-level `look(direction)` function.
+In this exercise we take this one step further and leave navigation entirely in your hands!
+
+This is one of the biggest and most complex exercises you've done so far.
+It's **really** important to take it step by step.
+
+### How it works
+
+When you start the exercise you can use the new `get_initial_maze()` function to get all of the squares arranged in a list of lists.
+Each list is a row (so `squares[1]` is the first row, and `squares[1][1]` is the top-left square).
+
+Each square is an Instance of the Square, exactly the same as in the "Squares Not Strings" exercise.
+
+There is one change, and that's the addition of a new method `remove_emoji()`. Previously, `remove_emoji()` was a function you called, passing in a square as an input.
+Under the hood, that used the square's method.
+Now you should use the method directly.
+
+## Instructions
+
+Your job is to upgrade your code to deal without having the built-in `look` function.
+
+You should navigate around, keeping track of where you are, and working out where you can go next.
+Collect the emojis and announce them at the end.
+
+We've given you your "Squares not Strings" code as your starting point, and give you a variety of step-by-step scenarios to work through.
+I highly recommend working through them one-by-one!
+
+Some notes:
+
+- Remember to stick to the original algorithm you were given.
+- The easiest starting point is probably to implement your own `look` function.
+- You always start on the starting square
+- You always start looking into the maze (i.e. into a square that's not a wall or off the board). If there are multiple options, prioritise by downward, leftward, rightward, upward.
+- Take this one step at a time. Start by positioning your character correctly, then get their initial direction right, then solve each scenario one-by-one!
+
+## Recap
+
+### The Square class
+
+As a reminder, instances of the square class have a few properties you can use:
+
+- `is_start`: A boolean representing whether this is the start square.
+- `is_finish`: A boolean representing whether this is the finishing square.
+- `is_wall`: A boolean representing whether this is the all square.
+- `contents`: A string containing an emoji, or an empty string.
+
+It also now has the method:
+
+- `remove_emoji()`: Removes the emoji from the square.
+
+### Emojis
+
+Special emojis. Avoid these:
+
+- `"🔥"` (Careful!)
+- `"💩"` (Ewww)
+
+Pick up the rest!
+
+### Library Functions
+
+This exercise will probably need your [`my#has_key`](/bootcamp/custom_functions/has_key/edit) library function!
+
+### Functions
+
+You have following game functions:
+
+- `move()`
+- `turn_left()`
+- `turn_right()`
+- `announce_emojis(dict)`
+- `get_initial_maze()`
diff --git a/bootcamp_content/projects/maze/exercises/pacman/stub.jiki b/bootcamp_content/projects/maze/exercises/pacman/stub.jiki
new file mode 100644
index 0000000000..ab32a3cb84
--- /dev/null
+++ b/bootcamp_content/projects/maze/exercises/pacman/stub.jiki
@@ -0,0 +1 @@
+{{EXERCISE:maze/squares-not-strings}}
\ No newline at end of file
diff --git a/bootcamp_content/projects/maze/exercises/pacman/task-1.md b/bootcamp_content/projects/maze/exercises/pacman/task-1.md
new file mode 100644
index 0000000000..0aa2d70289
--- /dev/null
+++ b/bootcamp_content/projects/maze/exercises/pacman/task-1.md
@@ -0,0 +1,3 @@
+# Task 1
+
+Use the new objects to solve the mazes.