@plasius/learning 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/dist/chunk-2UIOBMJZ.js +44 -0
- package/dist/chunk-2UIOBMJZ.js.map +1 -0
- package/dist/chunk-OXWMIHYI.js +6076 -0
- package/dist/chunk-OXWMIHYI.js.map +1 -0
- package/dist/course-authoring-DImvrK5r.d.cts +514 -0
- package/dist/course-authoring-DImvrK5r.d.ts +514 -0
- package/dist/courses/meteor-shield.cjs +369 -0
- package/dist/courses/meteor-shield.cjs.map +1 -0
- package/dist/courses/meteor-shield.d.cts +6 -0
- package/dist/courses/meteor-shield.d.ts +6 -0
- package/dist/courses/meteor-shield.js +175 -0
- package/dist/courses/meteor-shield.js.map +1 -0
- package/dist/courses/pixel-trail-challenge.cjs +366 -0
- package/dist/courses/pixel-trail-challenge.cjs.map +1 -0
- package/dist/courses/pixel-trail-challenge.d.cts +6 -0
- package/dist/courses/pixel-trail-challenge.d.ts +6 -0
- package/dist/courses/pixel-trail-challenge.js +172 -0
- package/dist/courses/pixel-trail-challenge.js.map +1 -0
- package/dist/courses/rescue-crew-commander.cjs +369 -0
- package/dist/courses/rescue-crew-commander.cjs.map +1 -0
- package/dist/courses/rescue-crew-commander.d.cts +6 -0
- package/dist/courses/rescue-crew-commander.d.ts +6 -0
- package/dist/courses/rescue-crew-commander.js +175 -0
- package/dist/courses/rescue-crew-commander.js.map +1 -0
- package/dist/courses/robot-maze-dash.cjs +355 -0
- package/dist/courses/robot-maze-dash.cjs.map +1 -0
- package/dist/courses/robot-maze-dash.d.cts +6 -0
- package/dist/courses/robot-maze-dash.d.ts +6 -0
- package/dist/courses/robot-maze-dash.js +161 -0
- package/dist/courses/robot-maze-dash.js.map +1 -0
- package/dist/courses/skywing-sprint.cjs +367 -0
- package/dist/courses/skywing-sprint.cjs.map +1 -0
- package/dist/courses/skywing-sprint.d.cts +6 -0
- package/dist/courses/skywing-sprint.d.ts +6 -0
- package/dist/courses/skywing-sprint.js +173 -0
- package/dist/courses/skywing-sprint.js.map +1 -0
- package/dist/courses/star-defender-squadron.cjs +369 -0
- package/dist/courses/star-defender-squadron.cjs.map +1 -0
- package/dist/courses/star-defender-squadron.d.cts +6 -0
- package/dist/courses/star-defender-squadron.d.ts +6 -0
- package/dist/courses/star-defender-squadron.js +175 -0
- package/dist/courses/star-defender-squadron.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -504
- package/dist/index.d.ts +3 -504
- package/dist/index.js +44 -6048
- package/dist/index.js.map +1 -1
- package/package.json +31 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {
|
|
2
|
+
authorCourse
|
|
3
|
+
} from "../chunk-2UIOBMJZ.js";
|
|
4
|
+
import "../chunk-OXWMIHYI.js";
|
|
5
|
+
|
|
6
|
+
// src/courses/pixel-trail-challenge.ts
|
|
7
|
+
var { course, practice } = authorCourse({
|
|
8
|
+
slug: "pixel-trail-challenge",
|
|
9
|
+
title: "Pixel Trail Challenge",
|
|
10
|
+
category: "game",
|
|
11
|
+
summary: "Create a grid game in which a growing trail collects orbs. Build deliberate movement, an ordered body, reproducible food placement and precise collision rules. Finish with a keyboard and touch playable challenge that handles both crowded boards and clean restarts.",
|
|
12
|
+
projectFiles: [{ path: "game.js", language: "javascript", maximumCharacters: 32e3 }],
|
|
13
|
+
starterProject: { files: [{ path: "game.js", source: `function initialState() {
|
|
14
|
+
return {
|
|
15
|
+
body: [{ x: 5, y: 8 }, { x: 4, y: 8 }, { x: 3, y: 8 }],
|
|
16
|
+
heading: "east", queuedDirection: null,
|
|
17
|
+
food: { x: 14, y: 8 }, score: 0, steps: 0, status: "ready"
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function update(state, input) {
|
|
22
|
+
return state;
|
|
23
|
+
}
|
|
24
|
+
` }] },
|
|
25
|
+
reference: [
|
|
26
|
+
{ name: "initialState", signature: "initialState() -> state", description: "Create a fresh trail on a 20-column by 16-row board. Coordinates are integers, with (0,0) at the top-left. body[0] is the head and the last element is the tail.", example: "const head = state.body[0]; const tail = state.body[state.body.length - 1];" },
|
|
27
|
+
{ name: "update", signature: "update(state, input) -> state", description: "Handle start, turn, step or restart. A turn supplies direction. A step advances one square while playing; the host normally supplies five steps per simulated second and can pause or step manually.", example: 'if (input.action === "restart") return initialState();' },
|
|
28
|
+
{ name: "heading", signature: '"north" | "east" | "south" | "west"', description: "North changes y by -1, east changes x by 1, south changes y by 1 and west changes x by -1. One accepted turn is queued for the next step; opposite and same-direction inputs do not consume that slot.", example: 'const opposite = { north: "south", south: "north", east: "west", west: "east" };' },
|
|
29
|
+
{ name: "body", signature: "Array<{ x: integer, y: integer }>", description: "Build a new body from the new head followed by the old body. Remove the last element for an ordinary move; keep it when collecting food. Body cells must remain unique and inside the board.", example: "const nextBody = [nextHead, ...state.body]; if (!growing) nextBody.pop();" },
|
|
30
|
+
{ name: "input.foodCandidates", signature: "Array<{ x, y }>", description: "Each step can supply up to eight seeded candidate cells. After growth choose the first valid empty candidate. If none is usable, scan rows from (0,0) for the first empty cell; at most 320 checks are needed.", example: "const occupied = state.body.some(cell => cell.x === candidate.x && cell.y === candidate.y);" },
|
|
31
|
+
{ name: "collision", signature: "next head versus retained body", description: "Walls and retained body cells end the game. On a non-growing step the old tail vacates, so that cell is excluded from collision checks. On a growing step the tail stays and remains an obstacle.", example: "const retained = growing ? state.body : state.body.slice(0, -1);" },
|
|
32
|
+
{ name: "status", signature: '"ready" | "playing" | "over" | "won"', description: "A collision ends the attempt without adding an invalid head. Filling all 320 cells wins and sets food to null. Over and won ignore turns and steps until restart creates a fresh ready state.", example: 'if (state.body.length === 320) { state.food = null; state.status = "won"; }' }
|
|
33
|
+
]
|
|
34
|
+
}, [
|
|
35
|
+
{
|
|
36
|
+
title: "One square at a time",
|
|
37
|
+
concepts: ["Grid coordinates", "Input buffering", "Direction"],
|
|
38
|
+
goals: ["Advance the head by exactly one integer grid square on each step.", "Queue one legal turn without allowing an immediate reverse through rapid inputs."],
|
|
39
|
+
extension: "Draw a rectangular route and predict the head coordinates after each step. Compare the same route using keyboard and onscreen direction buttons.",
|
|
40
|
+
activities: {
|
|
41
|
+
learn: ["Grid movement uses whole cells rather than pixel velocity. East adds one to x and north subtracts one from y. A turn requests the direction for the next step; it does not move immediately. Queue at most one legal change between steps so rapid inputs cannot reverse the trail.", "Compare a proposed direction with the current heading. Ignore opposite and same-direction requests, then accept the first perpendicular turn."],
|
|
42
|
+
predict: ["From head (5,8) facing east, queue north and then west before one step arrives. Predict the next position under the one-turn rule. Decide whether a repeated east input should prevent a later north turn.", "The first legal turn occupies the pending slot. A same-direction input is ignored and does not occupy it."],
|
|
43
|
+
build: ["Handle start and restart, then add turn buffering in queuedDirection. On a playing step apply the pending direction, clear it and calculate the next integer head position. Keep the remaining starter fields while you develop the movement model.", "Use an explicit direction-to-offset table so spelling mistakes cannot silently create an invalid coordinate."],
|
|
44
|
+
run: ["Start the preview, pause automatic steps and issue individual turns and steps. Try east-to-west, east-to-north and two quick perpendicular inputs. Compare the selected heading and pending direction with the head's next cell.", "Separate pressing a direction from stepping. This makes the input buffer visible and helps explain a seemingly ignored second turn."],
|
|
45
|
+
assess: ["Check movement in all four directions, unchanged ready state, immediate reverse rejection and two turns before a step. The checks require one-square integer movement rather than merely a trail that looks responsive.", "A direction input should not also count as a step. Several inputs between ticks must not create extra movement."],
|
|
46
|
+
inspect: ["If north moves down, inspect the coordinate convention. If rapid inputs reverse the head, inspect whether a second request overwrites the pending turn. If holding a direction blocks another turn, check same-direction handling.", "Write current heading and queued direction separately; they represent different moments in the update cycle."],
|
|
47
|
+
fix: ["Repair the direction or buffering branch and rerun a square route. Verify that a pending turn clears after its step, permitting the next turn, and that restart clears any unfinished input from the old attempt.", "A buffer that never clears is as incorrect as one that allows unlimited changes per step."],
|
|
48
|
+
explain: ["Choose why a game can accept only one direction change between movement steps. Use the two-quick-input example to explain the difference between responsive controls and an impossible instant reverse.", "The rule should be consistent across a physical keyboard and touch buttons because both produce the same turn action."],
|
|
49
|
+
reward: ["Save Grid movement. Your head now follows deliberate, reproducible steps. Next you will make an ordered body follow the exact path of that head instead of moving every segment independently.", "Keep the short rectangular route as a useful check when adding body movement."]
|
|
50
|
+
},
|
|
51
|
+
questions: {
|
|
52
|
+
learn: { question: "What does a north step do to a grid coordinate?", choices: ["Add one to x", "Subtract one from y", "Add one to y"], correctChoice: 1, feedback: "The origin is at the top-left, so moving north reduces the row coordinate by one." },
|
|
53
|
+
predict: { question: "East-facing head (5,8) queues north then west before one step; where does it go?", choices: ["(4,8)", "(5,9)", "(5,7)"], correctChoice: 2, feedback: "North is the first accepted perpendicular turn. West cannot overwrite it before the next step." },
|
|
54
|
+
explain: { question: "Why keep one pending direction instead of applying every rapid turn immediately?", choices: ["To prevent an impossible reversal between grid steps", "To move several cells at once", "To remove all keyboard controls"], correctChoice: 0, feedback: "One queued turn keeps each grid step consistent even when multiple input events arrive before it." }
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
title: "A trail that follows",
|
|
59
|
+
concepts: ["Ordered arrays", "Growth", "State snapshots"],
|
|
60
|
+
goals: ["Move the body by inserting a new head and removing the old tail.", "Grow by one segment when the head reaches food without moving existing segments twice."],
|
|
61
|
+
extension: "Trace a five-cell body through a corner on paper. Label array indices before and after each step to explain why the corner moves down the trail.",
|
|
62
|
+
activities: {
|
|
63
|
+
learn: ["The body array is the trail's history, ordered from head to tail. Insert the new head before the old body. For an ordinary move remove the final cell; when growing keep it. Existing cells do not each need a direction or their own movement calculation.", "Think of taking one new footprint and forgetting the oldest. Growth keeps that oldest footprint for one extra step."],
|
|
64
|
+
predict: ["The starter body is [(5,8),(4,8),(3,8)]. Predict the array after an ordinary east step, then after the same step if food is at (6,8). Compare both length and the last cell.", "The next head is (6,8) in both cases. The difference is whether the old tail at (3,8) remains."],
|
|
65
|
+
build: ["Use the next head from your movement code to construct a new body array. Compare that cell with food before removing the tail. Keep the tail on collection and otherwise pop it; do not also shift each old segment by the heading offset.", "Compute growing from the proposed head position, not the old head. The food is collected by arriving at its cell."],
|
|
66
|
+
run: ["Step straight, turn a corner and observe the head-to-tail list. Place the route toward the starter orb and pause before collection. Compare one normal step with the growth step and verify the length increases by exactly one.", "The text body list exposes duplicated or skipped cells that can be difficult to notice in a quick animation."],
|
|
67
|
+
assess: ["Check straight following, corner following, ordinary length preservation and one-cell growth. The returned body must keep its order and contain finite integer cells. Collection must not duplicate the new head.", "Moving every segment in the new heading makes the entire body slide sideways instead of following its previous path."],
|
|
68
|
+
inspect: ["If the body jumps sideways at corners, look for a loop moving all cells by the head's offset. If it grows every step, inspect the tail removal condition. If it never grows, check when the food comparison occurs.", "Compare expected and actual arrays index by index, beginning with the head and then the previous head's new position."],
|
|
69
|
+
fix: ["Repair the array construction and replay both a corner and a collection. Ensure the new head is inserted once, the old cells retain order, and normal moves preserve length. Recheck input buffering after the change.", "Use separate names for old body and next body so a mutation does not change the data you are still reading."],
|
|
70
|
+
explain: ["Choose why body order can replace a separate movement direction for every segment. Explain how keeping or discarding one tail cell controls growth without changing the head's step size.", "Each segment takes the previous position of the segment ahead through array order, not through its own steering logic."],
|
|
71
|
+
reward: ["Save Following trail. Your game has an ordered moving body and meaningful growth. The next mission places new orbs in empty cells so that collection can continue safely as the board fills.", "Preserve the corner example as a regression test before adding collision rules."]
|
|
72
|
+
},
|
|
73
|
+
questions: {
|
|
74
|
+
learn: { question: "How should an ordinary body move be constructed?", choices: ["Insert the new head and remove the old tail", "Move every cell in the new heading", "Remove the head and duplicate the tail"], correctChoice: 0, feedback: "The ordered old body already records the path. Adding one head and dropping one tail advances that path." },
|
|
75
|
+
predict: { question: "A three-cell trail collects food on its next step; what is its new length?", choices: ["Three", "Four", "Six"], correctChoice: 1, feedback: "The new head is added and the old tail is retained, increasing the length by exactly one." },
|
|
76
|
+
explain: { question: "Why should old body cells not also be moved by the new head's direction?", choices: ["They are only decorative", "Arrays cannot contain coordinates", "Their saved positions already describe the path to follow"], correctChoice: 2, feedback: "The previous positions are the trail history. Moving them all again destroys the path around corners." }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: "An orb in an empty square",
|
|
81
|
+
concepts: ["Search", "Determinism", "Bounded fallback"],
|
|
82
|
+
goals: ["Choose new food only from valid unoccupied cells after growth.", "Handle exhausted candidates and a full board without an unbounded random loop."],
|
|
83
|
+
extension: "Construct a nearly full small board on paper. Compare trying random cells repeatedly with a bounded scan of every cell once.",
|
|
84
|
+
activities: {
|
|
85
|
+
learn: ["Food placement must consider the grown body, including its new head. Try the supplied seeded candidates in order and use the first valid empty cell. If all fail, scan rows from (0,0). The 20\xD716 board contains 320 cells, so a full scan has a definite end.", "Repeated random guessing can take arbitrarily long on a crowded board. A bounded fallback guarantees a result or proves no empty cell remains."],
|
|
86
|
+
predict: ["Candidates are a body cell, an out-of-range cell and a free cell at (2,3). Predict which is chosen. Then imagine all candidates are occupied and only (0,1) is empty; follow the documented row scan.", "Check x from 0 through 19 within each row, then advance y. Validate integer coordinates before testing occupancy."],
|
|
87
|
+
build: ["After growth, find a valid unoccupied food candidate. If there is none, scan at most 320 board cells in row order. When the body fills every cell, set food=null and status=won rather than searching forever or placing food under the trail.", "Do the full-board check before searching. Use the new body, not the snapshot from before collection."],
|
|
88
|
+
run: ["Collect an orb and inspect the new food position relative to the grown body. Step through the candidate trace and try a crowded-board scenario. Repeat the same seed and route to confirm that placement is reproducible.", "A candidate may be rejected for being outside the board or occupied; those are different useful explanations."],
|
|
89
|
+
assess: ["Check valid candidates, occupied and malformed cells, fallback with one free square and a completely full board. The checks require termination within the board bound and food that never overlaps the body.", "A returned coordinate that looks reasonable is still invalid if it matches a body segment."],
|
|
90
|
+
inspect: ["If food appears inside the trail, inspect which body snapshot the occupancy check reads. If a crowded scenario stalls, look for an unbounded retry loop. If repeated runs differ, inspect the candidate order and fallback scan.", "Keep validation, occupancy and selection separate so each rejection has a clear reason."],
|
|
91
|
+
fix: ["Repair placement and rerun the one-free-cell and full-board cases. Confirm that the first valid supplied candidate still wins over the fallback, and that winning leaves no active food marker.", "The fallback should run only after candidates fail; scanning first would discard the supplied seeded layout."],
|
|
92
|
+
explain: ["Choose why a finite scan is more reliable than endlessly choosing random positions on a crowded grid. Describe how fixed candidate order makes a placement bug repeatable.", "Deterministic selection helps debugging while bounded work keeps the game responsive in its hardest state."],
|
|
93
|
+
reward: ["Save Reliable orbs. Your game can continue placing collectables without overlap and can recognise a filled board. Next you will distinguish actual body collisions from moving into a tail cell that is about to vacate.", "Keep a crowded-board example to revisit when modifying growth or scoring."]
|
|
94
|
+
},
|
|
95
|
+
questions: {
|
|
96
|
+
learn: { question: "Which body should food placement use after a collection?", choices: ["The old body before its new head was added", "An empty array", "The grown next body"], correctChoice: 2, feedback: "The newly occupied head cell and retained tail both belong to the current body and must be excluded." },
|
|
97
|
+
predict: { question: "The first two candidates are invalid or occupied and the third is empty; which is used?", choices: ["The third candidate", "The occupied first candidate", "A random cell regardless of candidates"], correctChoice: 0, feedback: "Candidate order is respected while invalid and occupied cells are skipped before selecting the first usable cell." },
|
|
98
|
+
explain: { question: "Why cap a fallback scan at the board's 320 cells?", choices: ["To prevent the trail from turning", "To guarantee termination even when no empty cell exists", "To ignore the current body"], correctChoice: 1, feedback: "A complete finite scan can establish that the board is full without relying on repeated guesses eventually succeeding." }
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
title: "Edges and moving tails",
|
|
103
|
+
concepts: ["Collision order", "Retained state", "Boundary cases"],
|
|
104
|
+
goals: ["End an attempt on wall or retained-body contact without inserting an invalid cell.", "Allow movement into the old tail cell only when that tail vacates on the same step."],
|
|
105
|
+
extension: "Draw a four-cell loop shape and test a move into its tail with and without growth. Explain why the exact same proposed head can have different outcomes.",
|
|
106
|
+
activities: {
|
|
107
|
+
learn: ["Compute the next head and whether it grows before checking collision. An ordinary move removes the old tail, so compare against body without its last cell. Growth retains the tail, so compare against the full body. Reject out-of-board cells before constructing the next body.", "Collision is about the cells retained after this step, not simply every cell visible before it."],
|
|
108
|
+
predict: ["A curved trail proposes moving into the square occupied by its old tail. Predict the result on an ordinary move and on a growing move. Separately consider a head at x=19 attempting one east step.", "The ordinary tail vacates; the growing tail stays. A column of 20 is outside the valid zero-to-19 range."],
|
|
109
|
+
build: ["Add wall and retained-body collision checks before applying movement, growth or score. On collision set over and preserve the last valid body. On a safe step commit the new body and clear the queued direction.", "Keep terminal states stable: later turn and step actions should not move an over or won trail."],
|
|
110
|
+
run: ["Try all four wall edges and a route that bends into an interior segment. Then inspect a non-growing move into a vacating tail. Pause on the last safe step and compare the proposed next head with the retained cell list.", "The text board can identify the exact occupied coordinate even if several segments look alike."],
|
|
111
|
+
assess: ["Check edge coordinates, interior self-contact, vacating-tail passage, retained-tail contact and actions after loss. The checks reject an invalid head appearing in the final body even if the project correctly sets over afterwards.", "Detecting a collision after committing an out-of-range cell leaves invalid state behind. Validate before applying it."],
|
|
112
|
+
inspect: ["If the tail case is rejected incorrectly, inspect whether the last cell is excluded for non-growth. If genuine self-contact passes, inspect the retained array and both x/y comparisons. If a wall leaves a cell offscreen, inspect commit order.", "Equality needs both coordinates to match one cell; sharing only a row or column is not a body collision."],
|
|
113
|
+
fix: ["Repair collision selection and ordering, then rerun the safe tail case as well as an interior hit. Confirm that food, score and body remain unchanged on a losing step and that restart restores a playable ready state.", "A fix that rejects every turn would hide collisions by removing gameplay. Preserve valid movement while rejecting invalid transitions."],
|
|
114
|
+
explain: ["Choose why the tail cannot be treated as permanently occupied during every step. Explain how computing growth first determines which old cells belong to the next collision test.", "Movement and growth change the set of occupied cells together; the collision rule must use that same model."],
|
|
115
|
+
reward: ["Save Precise collisions. Your trail now obeys explicit edge and body rules, including the moving-tail exception. Next you will make score, terminal outcomes and restart agree with those rules.", "Keep the vacating-tail example because it catches a subtle regression that ordinary straight play misses."]
|
|
116
|
+
},
|
|
117
|
+
questions: {
|
|
118
|
+
learn: { question: "Which old cells are obstacles during a non-growing step?", choices: ["Every old cell except the vacating tail", "Only the tail", "Every cell in the same row"], correctChoice: 0, feedback: "The old tail disappears during an ordinary move, while the remaining body cells are retained." },
|
|
119
|
+
predict: { question: "From x=19, what happens when the next east step proposes x=20?", choices: ["Wrap automatically without a rule", "Lose without adding the invalid head", "Grow by one cell"], correctChoice: 1, feedback: "The board's valid columns are 0 through 19. A wall collision ends the attempt while preserving its last valid body." },
|
|
120
|
+
explain: { question: "Why check whether the next move grows before choosing collision cells?", choices: ["Growth changes the world width", "Growth removes the head", "Growth determines whether the tail vacates or remains occupied"], correctChoice: 2, feedback: "The collision set depends on whether the tail is removed, and that depends on whether this move collects food." }
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
title: "A fair score and a fresh start",
|
|
125
|
+
concepts: ["Atomic updates", "Counters", "Replay"],
|
|
126
|
+
goals: ["Award one point per valid collection while counting only committed movement steps.", "Restart from both loss and victory with fresh state and no queued input from the previous attempt."],
|
|
127
|
+
extension: "Compare two routes to the same number of orbs using committed step counts. Explain why a shorter route is not always safer as the body grows.",
|
|
128
|
+
activities: {
|
|
129
|
+
learn: ["A safe collection is one coherent state change: add the new head, retain the tail, increment score once and select new food. Count one step only when a valid move commits. A rejected collision must not also award points or increase the body.", "Update related values from the same decision. Scoring before collision checks can reward an impossible move."],
|
|
130
|
+
predict: ["An orb is collected on one step, then five ordinary steps follow. Predict the score and length changes. Next imagine a losing step aimed at an occupied food cell in malformed state: should it award a point before ending?", "Valid collections change score and length together. Invalid movement must not receive the collection effects."],
|
|
131
|
+
build: ["Integrate score and steps into the safe-move commit. Add one score only on growth and one steps only on a committed move. Ensure restart returns fresh body, food, heading, empty queuedDirection, zero counters and ready status.", "Do not reset only the visible counters. Old food or pending input can still make the next attempt behave differently."],
|
|
132
|
+
run: ["Collect once and step without food several times while watching score and length. Lose, restart and repeat the starter route. Compare the state with a fresh page start, including the pending turn and original orb.", "Identical route inputs should reproduce the same score and body when the seed and starting state match."],
|
|
133
|
+
assess: ["Check one-time scoring, score unchanged on ordinary or losing steps, committed step counts and complete restart after over or won. Tests also continue sending actions after a terminal result to verify it remains stable.", "The displayed score should come from simulated collections, not from a separate counter incremented by any button press."],
|
|
134
|
+
inspect: ["If score increases while the head stays still, inspect event branches outside step. If a collection scores twice, inspect whether old food remains for another update. If replay diverges after restart, compare all initial fields.", "Follow one collection through its entire update instead of treating score and body as unrelated features."],
|
|
135
|
+
fix: ["Repair the safe-move commit and repeat collection, ordinary movement and collision as separate cases. Then check fresh restart from both terminal states. Keep food placement bounded and avoid changing its candidate order while repairing score.", "Use your previous reliable-orbs save to compare if a score fix accidentally changes where the next food appears."],
|
|
136
|
+
explain: ["Choose why collection effects should be applied together only after the move is known to be safe. Explain how a clean restart makes both play and debugging easier to repeat.", "A result is easier to trust when each score increment corresponds to one valid transition in the trace."],
|
|
137
|
+
reward: ["Save Honest trail. Your game now has a consistent score and a complete new-attempt journey. The capstone combines the rules and checks crowded, rapid-input and restart cases together.", "Keep a stable named save before adjusting pace or board size for an extension."]
|
|
138
|
+
},
|
|
139
|
+
questions: {
|
|
140
|
+
learn: { question: "When should the score increase for food collection?", choices: ["Whenever a direction button is pressed", "Once when a safe growth step commits", "Before checking whether the move is legal"], correctChoice: 1, feedback: "A collection reward belongs to one valid movement transition after collision checks have passed." },
|
|
141
|
+
predict: { question: "One collection followed by five normal moves changes score and length by what amount?", choices: ["Score six and length six", "Score zero and length one", "Score one and length one"], correctChoice: 2, feedback: "Only the collection grows and scores. Ordinary committed moves keep the body length and score unchanged." },
|
|
142
|
+
explain: { question: "Why clear queuedDirection on restart?", choices: ["To prevent a previous attempt's pending turn affecting the new one", "To remove all future controls", "To keep the old final heading"], correctChoice: 0, feedback: "Pending input is part of state. A new attempt should begin without an action left over from the previous race." }
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
title: "The winding trail",
|
|
147
|
+
concepts: ["Integration", "Edge-case design", "Accessible controls"],
|
|
148
|
+
goals: ["Complete a reproducible growing-trail game with bounded placement and precise collisions.", "Support keyboard and touch turns, pausing, restart and stable account saves through the full journey."],
|
|
149
|
+
extension: "Design a calmer practice pace in a separate save. Keep one-square movement and collision rules unchanged, then explain which changes affect timing and which affect game logic.",
|
|
150
|
+
activities: {
|
|
151
|
+
learn: ["The finished trail combines input buffering, ordered history, growth, food search and safe commits. Its most useful tests include crowded boards and rapid turns, not only a long straight route. Keep the text board and controls usable when animation is paused or reduced.", "The host owns drawing and accessibility controls; the project's returned state must remain understandable one step at a time."],
|
|
152
|
+
predict: ["Predict a short scenario that queues two turns, grows near its own tail, rejects an occupied food candidate and then restarts. Identify which decisions depend on old state and which must use the newly grown body.", "Current heading validates input, the proposed head determines growth, retained cells determine collision, and the new body determines food placement."],
|
|
153
|
+
build: ["Combine the passing mission code into a clear update pipeline. Calculate a proposed move, determine growth and retained cells, reject collision, then commit body, counters and food. Keep each helper's inputs explicit rather than relying on hidden global arrays.", "A helper that receives the new body cannot accidentally use an old global body for occupancy if its data boundary is clear."],
|
|
154
|
+
run: ["Play a full attempt using keyboard directions and another using touch buttons. Pause, step around a corner and inspect a crowded case. Restart after loss, load a named save and check that the saved project recreates its rules without preserving a stale live game.", "Project saves preserve your code and course progress. Restarting the live game is a different action from resetting your project source."],
|
|
155
|
+
assess: ["Check the final saved project across rapid inputs, growth, candidate exhaustion, full-board victory, tail passage and collision. The final assessment combines these cases and binds its result to the current source.", "A project must handle both valid play and awkward boundary states. One good hand-played attempt cannot establish all those rules."],
|
|
156
|
+
inspect: ["Find the earliest wrong state in a failing integrated case. Trace its data dependency through heading, next head, growth, retained cells and committed body. Identify which previous mission supplies the rule that was broken.", "A misplaced orb can be caused by an earlier body error. Repair the first disagreement rather than hiding its later symptom."],
|
|
157
|
+
fix: ["Repair the defect, rerun its focused case and repeat the existing straight, corner, growth and restart checks. Save and assess the new source before completing the course; earlier passing evidence describes the old version only.", "Keep the maximum 320-cell search bound even when changing placement. A capstone fix must not introduce an unbounded loop."],
|
|
158
|
+
explain: ["Choose what makes the final trail reliable and name one additional scenario you would test after changing its rules. Explain why a simplified game can still teach careful input, state and boundary reasoning.", "Give examples from your trace rather than claiming the project can never fail. Testing supports specific conclusions."],
|
|
159
|
+
reward: ["Save Winding trail and finish the final assessment. You have created a complete growing-grid game with reproducible play and explicit edge cases. Replay any mission or experiment in another named slot while retaining your earned completion.", "Preserve the finished version before making a new mode so that you can compare behaviour and recover easily."]
|
|
160
|
+
},
|
|
161
|
+
questions: {
|
|
162
|
+
learn: { question: "Which test is especially useful beyond ordinary straight movement?", choices: ["Only changing the background colour", "Only reading the final title", "A crowded board with a vacating-tail move"], correctChoice: 2, feedback: "Crowded and tail-boundary cases exercise the occupancy, growth and collision rules that simple straight play may never reach." },
|
|
163
|
+
predict: { question: "Which state must be used to place food after a safe growth step?", choices: ["The newly committed grown body", "The body from the previous attempt", "Only the current heading"], correctChoice: 0, feedback: "Food placement needs the complete occupied-cell set after growth, including the new head and retained tail." },
|
|
164
|
+
explain: { question: "What distinguishes restarting play from resetting the project?", choices: ["They must both erase every save", "Restart creates fresh game state; project reset changes the editable source", "Restart awards the course badge"], correctChoice: 1, feedback: "The live game's state and the learner's saved source serve different purposes; restarting a game must not erase their programming work." }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
]);
|
|
168
|
+
export {
|
|
169
|
+
course,
|
|
170
|
+
practice
|
|
171
|
+
};
|
|
172
|
+
//# sourceMappingURL=pixel-trail-challenge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/courses/pixel-trail-challenge.ts"],"sourcesContent":["import { authorCourse } from \"./course-authoring.js\";\n\nexport const { course, practice } = authorCourse({\n slug: \"pixel-trail-challenge\", title: \"Pixel Trail Challenge\", category: \"game\",\n summary: \"Create a grid game in which a growing trail collects orbs. Build deliberate movement, an ordered body, reproducible food placement and precise collision rules. Finish with a keyboard and touch playable challenge that handles both crowded boards and clean restarts.\",\n projectFiles: [{ path: \"game.js\", language: \"javascript\", maximumCharacters: 32000 }],\n starterProject: { files: [{ path: \"game.js\", source: `function initialState() {\n return {\n body: [{ x: 5, y: 8 }, { x: 4, y: 8 }, { x: 3, y: 8 }],\n heading: \"east\", queuedDirection: null,\n food: { x: 14, y: 8 }, score: 0, steps: 0, status: \"ready\"\n };\n}\n\nfunction update(state, input) {\n return state;\n}\n` }] },\n reference: [\n { name: \"initialState\", signature: \"initialState() -> state\", description: \"Create a fresh trail on a 20-column by 16-row board. Coordinates are integers, with (0,0) at the top-left. body[0] is the head and the last element is the tail.\", example: \"const head = state.body[0]; const tail = state.body[state.body.length - 1];\" },\n { name: \"update\", signature: \"update(state, input) -> state\", description: \"Handle start, turn, step or restart. A turn supplies direction. A step advances one square while playing; the host normally supplies five steps per simulated second and can pause or step manually.\", example: 'if (input.action === \"restart\") return initialState();' },\n { name: \"heading\", signature: '\"north\" | \"east\" | \"south\" | \"west\"', description: \"North changes y by -1, east changes x by 1, south changes y by 1 and west changes x by -1. One accepted turn is queued for the next step; opposite and same-direction inputs do not consume that slot.\", example: 'const opposite = { north: \"south\", south: \"north\", east: \"west\", west: \"east\" };' },\n { name: \"body\", signature: \"Array<{ x: integer, y: integer }>\", description: \"Build a new body from the new head followed by the old body. Remove the last element for an ordinary move; keep it when collecting food. Body cells must remain unique and inside the board.\", example: \"const nextBody = [nextHead, ...state.body]; if (!growing) nextBody.pop();\" },\n { name: \"input.foodCandidates\", signature: \"Array<{ x, y }>\", description: \"Each step can supply up to eight seeded candidate cells. After growth choose the first valid empty candidate. If none is usable, scan rows from (0,0) for the first empty cell; at most 320 checks are needed.\", example: \"const occupied = state.body.some(cell => cell.x === candidate.x && cell.y === candidate.y);\" },\n { name: \"collision\", signature: \"next head versus retained body\", description: \"Walls and retained body cells end the game. On a non-growing step the old tail vacates, so that cell is excluded from collision checks. On a growing step the tail stays and remains an obstacle.\", example: \"const retained = growing ? state.body : state.body.slice(0, -1);\" },\n { name: \"status\", signature: '\"ready\" | \"playing\" | \"over\" | \"won\"', description: \"A collision ends the attempt without adding an invalid head. Filling all 320 cells wins and sets food to null. Over and won ignore turns and steps until restart creates a fresh ready state.\", example: 'if (state.body.length === 320) { state.food = null; state.status = \"won\"; }' },\n ],\n}, [\n {\n title: \"One square at a time\", concepts: [\"Grid coordinates\", \"Input buffering\", \"Direction\"],\n goals: [\"Advance the head by exactly one integer grid square on each step.\", \"Queue one legal turn without allowing an immediate reverse through rapid inputs.\"],\n extension: \"Draw a rectangular route and predict the head coordinates after each step. Compare the same route using keyboard and onscreen direction buttons.\",\n activities: {\n learn: [\"Grid movement uses whole cells rather than pixel velocity. East adds one to x and north subtracts one from y. A turn requests the direction for the next step; it does not move immediately. Queue at most one legal change between steps so rapid inputs cannot reverse the trail.\", \"Compare a proposed direction with the current heading. Ignore opposite and same-direction requests, then accept the first perpendicular turn.\"],\n predict: [\"From head (5,8) facing east, queue north and then west before one step arrives. Predict the next position under the one-turn rule. Decide whether a repeated east input should prevent a later north turn.\", \"The first legal turn occupies the pending slot. A same-direction input is ignored and does not occupy it.\"],\n build: [\"Handle start and restart, then add turn buffering in queuedDirection. On a playing step apply the pending direction, clear it and calculate the next integer head position. Keep the remaining starter fields while you develop the movement model.\", \"Use an explicit direction-to-offset table so spelling mistakes cannot silently create an invalid coordinate.\"],\n run: [\"Start the preview, pause automatic steps and issue individual turns and steps. Try east-to-west, east-to-north and two quick perpendicular inputs. Compare the selected heading and pending direction with the head's next cell.\", \"Separate pressing a direction from stepping. This makes the input buffer visible and helps explain a seemingly ignored second turn.\"],\n assess: [\"Check movement in all four directions, unchanged ready state, immediate reverse rejection and two turns before a step. The checks require one-square integer movement rather than merely a trail that looks responsive.\", \"A direction input should not also count as a step. Several inputs between ticks must not create extra movement.\"],\n inspect: [\"If north moves down, inspect the coordinate convention. If rapid inputs reverse the head, inspect whether a second request overwrites the pending turn. If holding a direction blocks another turn, check same-direction handling.\", \"Write current heading and queued direction separately; they represent different moments in the update cycle.\"],\n fix: [\"Repair the direction or buffering branch and rerun a square route. Verify that a pending turn clears after its step, permitting the next turn, and that restart clears any unfinished input from the old attempt.\", \"A buffer that never clears is as incorrect as one that allows unlimited changes per step.\"],\n explain: [\"Choose why a game can accept only one direction change between movement steps. Use the two-quick-input example to explain the difference between responsive controls and an impossible instant reverse.\", \"The rule should be consistent across a physical keyboard and touch buttons because both produce the same turn action.\"],\n reward: [\"Save Grid movement. Your head now follows deliberate, reproducible steps. Next you will make an ordered body follow the exact path of that head instead of moving every segment independently.\", \"Keep the short rectangular route as a useful check when adding body movement.\"],\n },\n questions: {\n learn: { question: \"What does a north step do to a grid coordinate?\", choices: [\"Add one to x\", \"Subtract one from y\", \"Add one to y\"], correctChoice: 1, feedback: \"The origin is at the top-left, so moving north reduces the row coordinate by one.\" },\n predict: { question: \"East-facing head (5,8) queues north then west before one step; where does it go?\", choices: [\"(4,8)\", \"(5,9)\", \"(5,7)\"], correctChoice: 2, feedback: \"North is the first accepted perpendicular turn. West cannot overwrite it before the next step.\" },\n explain: { question: \"Why keep one pending direction instead of applying every rapid turn immediately?\", choices: [\"To prevent an impossible reversal between grid steps\", \"To move several cells at once\", \"To remove all keyboard controls\"], correctChoice: 0, feedback: \"One queued turn keeps each grid step consistent even when multiple input events arrive before it.\" },\n },\n },\n {\n title: \"A trail that follows\", concepts: [\"Ordered arrays\", \"Growth\", \"State snapshots\"],\n goals: [\"Move the body by inserting a new head and removing the old tail.\", \"Grow by one segment when the head reaches food without moving existing segments twice.\"],\n extension: \"Trace a five-cell body through a corner on paper. Label array indices before and after each step to explain why the corner moves down the trail.\",\n activities: {\n learn: [\"The body array is the trail's history, ordered from head to tail. Insert the new head before the old body. For an ordinary move remove the final cell; when growing keep it. Existing cells do not each need a direction or their own movement calculation.\", \"Think of taking one new footprint and forgetting the oldest. Growth keeps that oldest footprint for one extra step.\"],\n predict: [\"The starter body is [(5,8),(4,8),(3,8)]. Predict the array after an ordinary east step, then after the same step if food is at (6,8). Compare both length and the last cell.\", \"The next head is (6,8) in both cases. The difference is whether the old tail at (3,8) remains.\"],\n build: [\"Use the next head from your movement code to construct a new body array. Compare that cell with food before removing the tail. Keep the tail on collection and otherwise pop it; do not also shift each old segment by the heading offset.\", \"Compute growing from the proposed head position, not the old head. The food is collected by arriving at its cell.\"],\n run: [\"Step straight, turn a corner and observe the head-to-tail list. Place the route toward the starter orb and pause before collection. Compare one normal step with the growth step and verify the length increases by exactly one.\", \"The text body list exposes duplicated or skipped cells that can be difficult to notice in a quick animation.\"],\n assess: [\"Check straight following, corner following, ordinary length preservation and one-cell growth. The returned body must keep its order and contain finite integer cells. Collection must not duplicate the new head.\", \"Moving every segment in the new heading makes the entire body slide sideways instead of following its previous path.\"],\n inspect: [\"If the body jumps sideways at corners, look for a loop moving all cells by the head's offset. If it grows every step, inspect the tail removal condition. If it never grows, check when the food comparison occurs.\", \"Compare expected and actual arrays index by index, beginning with the head and then the previous head's new position.\"],\n fix: [\"Repair the array construction and replay both a corner and a collection. Ensure the new head is inserted once, the old cells retain order, and normal moves preserve length. Recheck input buffering after the change.\", \"Use separate names for old body and next body so a mutation does not change the data you are still reading.\"],\n explain: [\"Choose why body order can replace a separate movement direction for every segment. Explain how keeping or discarding one tail cell controls growth without changing the head's step size.\", \"Each segment takes the previous position of the segment ahead through array order, not through its own steering logic.\"],\n reward: [\"Save Following trail. Your game has an ordered moving body and meaningful growth. The next mission places new orbs in empty cells so that collection can continue safely as the board fills.\", \"Preserve the corner example as a regression test before adding collision rules.\"],\n },\n questions: {\n learn: { question: \"How should an ordinary body move be constructed?\", choices: [\"Insert the new head and remove the old tail\", \"Move every cell in the new heading\", \"Remove the head and duplicate the tail\"], correctChoice: 0, feedback: \"The ordered old body already records the path. Adding one head and dropping one tail advances that path.\" },\n predict: { question: \"A three-cell trail collects food on its next step; what is its new length?\", choices: [\"Three\", \"Four\", \"Six\"], correctChoice: 1, feedback: \"The new head is added and the old tail is retained, increasing the length by exactly one.\" },\n explain: { question: \"Why should old body cells not also be moved by the new head's direction?\", choices: [\"They are only decorative\", \"Arrays cannot contain coordinates\", \"Their saved positions already describe the path to follow\"], correctChoice: 2, feedback: \"The previous positions are the trail history. Moving them all again destroys the path around corners.\" },\n },\n },\n {\n title: \"An orb in an empty square\", concepts: [\"Search\", \"Determinism\", \"Bounded fallback\"],\n goals: [\"Choose new food only from valid unoccupied cells after growth.\", \"Handle exhausted candidates and a full board without an unbounded random loop.\"],\n extension: \"Construct a nearly full small board on paper. Compare trying random cells repeatedly with a bounded scan of every cell once.\",\n activities: {\n learn: [\"Food placement must consider the grown body, including its new head. Try the supplied seeded candidates in order and use the first valid empty cell. If all fail, scan rows from (0,0). The 20×16 board contains 320 cells, so a full scan has a definite end.\", \"Repeated random guessing can take arbitrarily long on a crowded board. A bounded fallback guarantees a result or proves no empty cell remains.\"],\n predict: [\"Candidates are a body cell, an out-of-range cell and a free cell at (2,3). Predict which is chosen. Then imagine all candidates are occupied and only (0,1) is empty; follow the documented row scan.\", \"Check x from 0 through 19 within each row, then advance y. Validate integer coordinates before testing occupancy.\"],\n build: [\"After growth, find a valid unoccupied food candidate. If there is none, scan at most 320 board cells in row order. When the body fills every cell, set food=null and status=won rather than searching forever or placing food under the trail.\", \"Do the full-board check before searching. Use the new body, not the snapshot from before collection.\"],\n run: [\"Collect an orb and inspect the new food position relative to the grown body. Step through the candidate trace and try a crowded-board scenario. Repeat the same seed and route to confirm that placement is reproducible.\", \"A candidate may be rejected for being outside the board or occupied; those are different useful explanations.\"],\n assess: [\"Check valid candidates, occupied and malformed cells, fallback with one free square and a completely full board. The checks require termination within the board bound and food that never overlaps the body.\", \"A returned coordinate that looks reasonable is still invalid if it matches a body segment.\"],\n inspect: [\"If food appears inside the trail, inspect which body snapshot the occupancy check reads. If a crowded scenario stalls, look for an unbounded retry loop. If repeated runs differ, inspect the candidate order and fallback scan.\", \"Keep validation, occupancy and selection separate so each rejection has a clear reason.\"],\n fix: [\"Repair placement and rerun the one-free-cell and full-board cases. Confirm that the first valid supplied candidate still wins over the fallback, and that winning leaves no active food marker.\", \"The fallback should run only after candidates fail; scanning first would discard the supplied seeded layout.\"],\n explain: [\"Choose why a finite scan is more reliable than endlessly choosing random positions on a crowded grid. Describe how fixed candidate order makes a placement bug repeatable.\", \"Deterministic selection helps debugging while bounded work keeps the game responsive in its hardest state.\"],\n reward: [\"Save Reliable orbs. Your game can continue placing collectables without overlap and can recognise a filled board. Next you will distinguish actual body collisions from moving into a tail cell that is about to vacate.\", \"Keep a crowded-board example to revisit when modifying growth or scoring.\"],\n },\n questions: {\n learn: { question: \"Which body should food placement use after a collection?\", choices: [\"The old body before its new head was added\", \"An empty array\", \"The grown next body\"], correctChoice: 2, feedback: \"The newly occupied head cell and retained tail both belong to the current body and must be excluded.\" },\n predict: { question: \"The first two candidates are invalid or occupied and the third is empty; which is used?\", choices: [\"The third candidate\", \"The occupied first candidate\", \"A random cell regardless of candidates\"], correctChoice: 0, feedback: \"Candidate order is respected while invalid and occupied cells are skipped before selecting the first usable cell.\" },\n explain: { question: \"Why cap a fallback scan at the board's 320 cells?\", choices: [\"To prevent the trail from turning\", \"To guarantee termination even when no empty cell exists\", \"To ignore the current body\"], correctChoice: 1, feedback: \"A complete finite scan can establish that the board is full without relying on repeated guesses eventually succeeding.\" },\n },\n },\n {\n title: \"Edges and moving tails\", concepts: [\"Collision order\", \"Retained state\", \"Boundary cases\"],\n goals: [\"End an attempt on wall or retained-body contact without inserting an invalid cell.\", \"Allow movement into the old tail cell only when that tail vacates on the same step.\"],\n extension: \"Draw a four-cell loop shape and test a move into its tail with and without growth. Explain why the exact same proposed head can have different outcomes.\",\n activities: {\n learn: [\"Compute the next head and whether it grows before checking collision. An ordinary move removes the old tail, so compare against body without its last cell. Growth retains the tail, so compare against the full body. Reject out-of-board cells before constructing the next body.\", \"Collision is about the cells retained after this step, not simply every cell visible before it.\"],\n predict: [\"A curved trail proposes moving into the square occupied by its old tail. Predict the result on an ordinary move and on a growing move. Separately consider a head at x=19 attempting one east step.\", \"The ordinary tail vacates; the growing tail stays. A column of 20 is outside the valid zero-to-19 range.\"],\n build: [\"Add wall and retained-body collision checks before applying movement, growth or score. On collision set over and preserve the last valid body. On a safe step commit the new body and clear the queued direction.\", \"Keep terminal states stable: later turn and step actions should not move an over or won trail.\"],\n run: [\"Try all four wall edges and a route that bends into an interior segment. Then inspect a non-growing move into a vacating tail. Pause on the last safe step and compare the proposed next head with the retained cell list.\", \"The text board can identify the exact occupied coordinate even if several segments look alike.\"],\n assess: [\"Check edge coordinates, interior self-contact, vacating-tail passage, retained-tail contact and actions after loss. The checks reject an invalid head appearing in the final body even if the project correctly sets over afterwards.\", \"Detecting a collision after committing an out-of-range cell leaves invalid state behind. Validate before applying it.\"],\n inspect: [\"If the tail case is rejected incorrectly, inspect whether the last cell is excluded for non-growth. If genuine self-contact passes, inspect the retained array and both x/y comparisons. If a wall leaves a cell offscreen, inspect commit order.\", \"Equality needs both coordinates to match one cell; sharing only a row or column is not a body collision.\"],\n fix: [\"Repair collision selection and ordering, then rerun the safe tail case as well as an interior hit. Confirm that food, score and body remain unchanged on a losing step and that restart restores a playable ready state.\", \"A fix that rejects every turn would hide collisions by removing gameplay. Preserve valid movement while rejecting invalid transitions.\"],\n explain: [\"Choose why the tail cannot be treated as permanently occupied during every step. Explain how computing growth first determines which old cells belong to the next collision test.\", \"Movement and growth change the set of occupied cells together; the collision rule must use that same model.\"],\n reward: [\"Save Precise collisions. Your trail now obeys explicit edge and body rules, including the moving-tail exception. Next you will make score, terminal outcomes and restart agree with those rules.\", \"Keep the vacating-tail example because it catches a subtle regression that ordinary straight play misses.\"],\n },\n questions: {\n learn: { question: \"Which old cells are obstacles during a non-growing step?\", choices: [\"Every old cell except the vacating tail\", \"Only the tail\", \"Every cell in the same row\"], correctChoice: 0, feedback: \"The old tail disappears during an ordinary move, while the remaining body cells are retained.\" },\n predict: { question: \"From x=19, what happens when the next east step proposes x=20?\", choices: [\"Wrap automatically without a rule\", \"Lose without adding the invalid head\", \"Grow by one cell\"], correctChoice: 1, feedback: \"The board's valid columns are 0 through 19. A wall collision ends the attempt while preserving its last valid body.\" },\n explain: { question: \"Why check whether the next move grows before choosing collision cells?\", choices: [\"Growth changes the world width\", \"Growth removes the head\", \"Growth determines whether the tail vacates or remains occupied\"], correctChoice: 2, feedback: \"The collision set depends on whether the tail is removed, and that depends on whether this move collects food.\" },\n },\n },\n {\n title: \"A fair score and a fresh start\", concepts: [\"Atomic updates\", \"Counters\", \"Replay\"],\n goals: [\"Award one point per valid collection while counting only committed movement steps.\", \"Restart from both loss and victory with fresh state and no queued input from the previous attempt.\"],\n extension: \"Compare two routes to the same number of orbs using committed step counts. Explain why a shorter route is not always safer as the body grows.\",\n activities: {\n learn: [\"A safe collection is one coherent state change: add the new head, retain the tail, increment score once and select new food. Count one step only when a valid move commits. A rejected collision must not also award points or increase the body.\", \"Update related values from the same decision. Scoring before collision checks can reward an impossible move.\"],\n predict: [\"An orb is collected on one step, then five ordinary steps follow. Predict the score and length changes. Next imagine a losing step aimed at an occupied food cell in malformed state: should it award a point before ending?\", \"Valid collections change score and length together. Invalid movement must not receive the collection effects.\"],\n build: [\"Integrate score and steps into the safe-move commit. Add one score only on growth and one steps only on a committed move. Ensure restart returns fresh body, food, heading, empty queuedDirection, zero counters and ready status.\", \"Do not reset only the visible counters. Old food or pending input can still make the next attempt behave differently.\"],\n run: [\"Collect once and step without food several times while watching score and length. Lose, restart and repeat the starter route. Compare the state with a fresh page start, including the pending turn and original orb.\", \"Identical route inputs should reproduce the same score and body when the seed and starting state match.\"],\n assess: [\"Check one-time scoring, score unchanged on ordinary or losing steps, committed step counts and complete restart after over or won. Tests also continue sending actions after a terminal result to verify it remains stable.\", \"The displayed score should come from simulated collections, not from a separate counter incremented by any button press.\"],\n inspect: [\"If score increases while the head stays still, inspect event branches outside step. If a collection scores twice, inspect whether old food remains for another update. If replay diverges after restart, compare all initial fields.\", \"Follow one collection through its entire update instead of treating score and body as unrelated features.\"],\n fix: [\"Repair the safe-move commit and repeat collection, ordinary movement and collision as separate cases. Then check fresh restart from both terminal states. Keep food placement bounded and avoid changing its candidate order while repairing score.\", \"Use your previous reliable-orbs save to compare if a score fix accidentally changes where the next food appears.\"],\n explain: [\"Choose why collection effects should be applied together only after the move is known to be safe. Explain how a clean restart makes both play and debugging easier to repeat.\", \"A result is easier to trust when each score increment corresponds to one valid transition in the trace.\"],\n reward: [\"Save Honest trail. Your game now has a consistent score and a complete new-attempt journey. The capstone combines the rules and checks crowded, rapid-input and restart cases together.\", \"Keep a stable named save before adjusting pace or board size for an extension.\"],\n },\n questions: {\n learn: { question: \"When should the score increase for food collection?\", choices: [\"Whenever a direction button is pressed\", \"Once when a safe growth step commits\", \"Before checking whether the move is legal\"], correctChoice: 1, feedback: \"A collection reward belongs to one valid movement transition after collision checks have passed.\" },\n predict: { question: \"One collection followed by five normal moves changes score and length by what amount?\", choices: [\"Score six and length six\", \"Score zero and length one\", \"Score one and length one\"], correctChoice: 2, feedback: \"Only the collection grows and scores. Ordinary committed moves keep the body length and score unchanged.\" },\n explain: { question: \"Why clear queuedDirection on restart?\", choices: [\"To prevent a previous attempt's pending turn affecting the new one\", \"To remove all future controls\", \"To keep the old final heading\"], correctChoice: 0, feedback: \"Pending input is part of state. A new attempt should begin without an action left over from the previous race.\" },\n },\n },\n {\n title: \"The winding trail\", concepts: [\"Integration\", \"Edge-case design\", \"Accessible controls\"],\n goals: [\"Complete a reproducible growing-trail game with bounded placement and precise collisions.\", \"Support keyboard and touch turns, pausing, restart and stable account saves through the full journey.\"],\n extension: \"Design a calmer practice pace in a separate save. Keep one-square movement and collision rules unchanged, then explain which changes affect timing and which affect game logic.\",\n activities: {\n learn: [\"The finished trail combines input buffering, ordered history, growth, food search and safe commits. Its most useful tests include crowded boards and rapid turns, not only a long straight route. Keep the text board and controls usable when animation is paused or reduced.\", \"The host owns drawing and accessibility controls; the project's returned state must remain understandable one step at a time.\"],\n predict: [\"Predict a short scenario that queues two turns, grows near its own tail, rejects an occupied food candidate and then restarts. Identify which decisions depend on old state and which must use the newly grown body.\", \"Current heading validates input, the proposed head determines growth, retained cells determine collision, and the new body determines food placement.\"],\n build: [\"Combine the passing mission code into a clear update pipeline. Calculate a proposed move, determine growth and retained cells, reject collision, then commit body, counters and food. Keep each helper's inputs explicit rather than relying on hidden global arrays.\", \"A helper that receives the new body cannot accidentally use an old global body for occupancy if its data boundary is clear.\"],\n run: [\"Play a full attempt using keyboard directions and another using touch buttons. Pause, step around a corner and inspect a crowded case. Restart after loss, load a named save and check that the saved project recreates its rules without preserving a stale live game.\", \"Project saves preserve your code and course progress. Restarting the live game is a different action from resetting your project source.\"],\n assess: [\"Check the final saved project across rapid inputs, growth, candidate exhaustion, full-board victory, tail passage and collision. The final assessment combines these cases and binds its result to the current source.\", \"A project must handle both valid play and awkward boundary states. One good hand-played attempt cannot establish all those rules.\"],\n inspect: [\"Find the earliest wrong state in a failing integrated case. Trace its data dependency through heading, next head, growth, retained cells and committed body. Identify which previous mission supplies the rule that was broken.\", \"A misplaced orb can be caused by an earlier body error. Repair the first disagreement rather than hiding its later symptom.\"],\n fix: [\"Repair the defect, rerun its focused case and repeat the existing straight, corner, growth and restart checks. Save and assess the new source before completing the course; earlier passing evidence describes the old version only.\", \"Keep the maximum 320-cell search bound even when changing placement. A capstone fix must not introduce an unbounded loop.\"],\n explain: [\"Choose what makes the final trail reliable and name one additional scenario you would test after changing its rules. Explain why a simplified game can still teach careful input, state and boundary reasoning.\", \"Give examples from your trace rather than claiming the project can never fail. Testing supports specific conclusions.\"],\n reward: [\"Save Winding trail and finish the final assessment. You have created a complete growing-grid game with reproducible play and explicit edge cases. Replay any mission or experiment in another named slot while retaining your earned completion.\", \"Preserve the finished version before making a new mode so that you can compare behaviour and recover easily.\"],\n },\n questions: {\n learn: { question: \"Which test is especially useful beyond ordinary straight movement?\", choices: [\"Only changing the background colour\", \"Only reading the final title\", \"A crowded board with a vacating-tail move\"], correctChoice: 2, feedback: \"Crowded and tail-boundary cases exercise the occupancy, growth and collision rules that simple straight play may never reach.\" },\n predict: { question: \"Which state must be used to place food after a safe growth step?\", choices: [\"The newly committed grown body\", \"The body from the previous attempt\", \"Only the current heading\"], correctChoice: 0, feedback: \"Food placement needs the complete occupied-cell set after growth, including the new head and retained tail.\" },\n explain: { question: \"What distinguishes restarting play from resetting the project?\", choices: [\"They must both erase every save\", \"Restart creates fresh game state; project reset changes the editable source\", \"Restart awards the course badge\"], correctChoice: 1, feedback: \"The live game's state and the learner's saved source serve different purposes; restarting a game must not erase their programming work.\" },\n },\n },\n]);\n"],"mappings":";;;;;;AAEO,IAAM,EAAE,QAAQ,SAAS,IAAI,aAAa;AAAA,EAC/C,MAAM;AAAA,EAAyB,OAAO;AAAA,EAAyB,UAAU;AAAA,EACzE,SAAS;AAAA,EACT,cAAc,CAAC,EAAE,MAAM,WAAW,UAAU,cAAc,mBAAmB,KAAM,CAAC;AAAA,EACpF,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWrD,CAAC,EAAE;AAAA,EACH,WAAW;AAAA,IACT,EAAE,MAAM,gBAAgB,WAAW,2BAA2B,aAAa,oKAAoK,SAAS,8EAA8E;AAAA,IACtU,EAAE,MAAM,UAAU,WAAW,iCAAiC,aAAa,wMAAwM,SAAS,yDAAyD;AAAA,IACrV,EAAE,MAAM,WAAW,WAAW,uCAAuC,aAAa,0MAA0M,SAAS,mFAAmF;AAAA,IACxX,EAAE,MAAM,QAAQ,WAAW,qCAAqC,aAAa,gMAAgM,SAAS,4EAA4E;AAAA,IAClW,EAAE,MAAM,wBAAwB,WAAW,mBAAmB,aAAa,kNAAkN,SAAS,8FAA8F;AAAA,IACpY,EAAE,MAAM,aAAa,WAAW,kCAAkC,aAAa,qMAAqM,SAAS,mEAAmE;AAAA,IAChW,EAAE,MAAM,UAAU,WAAW,wCAAwC,aAAa,iMAAiM,SAAS,8EAA8E;AAAA,EAC5W;AACF,GAAG;AAAA,EACD;AAAA,IACE,OAAO;AAAA,IAAwB,UAAU,CAAC,oBAAoB,mBAAmB,WAAW;AAAA,IAC5F,OAAO,CAAC,qEAAqE,kFAAkF;AAAA,IAC/J,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,uRAAuR,+IAA+I;AAAA,MAC9a,SAAS,CAAC,8MAA8M,2GAA2G;AAAA,MACnU,OAAO,CAAC,uPAAuP,8GAA8G;AAAA,MAC7W,KAAK,CAAC,oOAAoO,qIAAqI;AAAA,MAC/W,QAAQ,CAAC,2NAA2N,iHAAiH;AAAA,MACrV,SAAS,CAAC,sOAAsO,8GAA8G;AAAA,MAC9V,KAAK,CAAC,qNAAqN,2FAA2F;AAAA,MACtT,SAAS,CAAC,2MAA2M,uHAAuH;AAAA,MAC5U,QAAQ,CAAC,kMAAkM,+EAA+E;AAAA,IAC5R;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,mDAAmD,SAAS,CAAC,gBAAgB,uBAAuB,cAAc,GAAG,eAAe,GAAG,UAAU,oFAAoF;AAAA,MACxP,SAAS,EAAE,UAAU,oFAAoF,SAAS,CAAC,SAAS,SAAS,OAAO,GAAG,eAAe,GAAG,UAAU,iGAAiG;AAAA,MAC5Q,SAAS,EAAE,UAAU,oFAAoF,SAAS,CAAC,wDAAwD,iCAAiC,iCAAiC,GAAG,eAAe,GAAG,UAAU,oGAAoG;AAAA,IAClX;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAAwB,UAAU,CAAC,kBAAkB,UAAU,iBAAiB;AAAA,IACvF,OAAO,CAAC,oEAAoE,wFAAwF;AAAA,IACpK,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,+PAA+P,qHAAqH;AAAA,MAC5X,SAAS,CAAC,gLAAgL,gGAAgG;AAAA,MAC1R,OAAO,CAAC,8OAA8O,mHAAmH;AAAA,MACzW,KAAK,CAAC,oOAAoO,8GAA8G;AAAA,MACxV,QAAQ,CAAC,qNAAqN,sHAAsH;AAAA,MACpV,SAAS,CAAC,uNAAuN,uHAAuH;AAAA,MACxV,KAAK,CAAC,0NAA0N,6GAA6G;AAAA,MAC7U,SAAS,CAAC,6LAA6L,wHAAwH;AAAA,MAC/T,QAAQ,CAAC,gMAAgM,iFAAiF;AAAA,IAC5R;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,oDAAoD,SAAS,CAAC,+CAA+C,sCAAsC,wCAAwC,GAAG,eAAe,GAAG,UAAU,2GAA2G;AAAA,MACxV,SAAS,EAAE,UAAU,8EAA8E,SAAS,CAAC,SAAS,QAAQ,KAAK,GAAG,eAAe,GAAG,UAAU,4FAA4F;AAAA,MAC9P,SAAS,EAAE,UAAU,4EAA4E,SAAS,CAAC,4BAA4B,qCAAqC,2DAA2D,GAAG,eAAe,GAAG,UAAU,wGAAwG;AAAA,IAChX;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAA6B,UAAU,CAAC,UAAU,eAAe,kBAAkB;AAAA,IAC1F,OAAO,CAAC,kEAAkE,gFAAgF;AAAA,IAC1J,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,qQAAkQ,gJAAgJ;AAAA,MAC1Z,SAAS,CAAC,yMAAyM,mHAAmH;AAAA,MACtU,OAAO,CAAC,kPAAkP,sGAAsG;AAAA,MAChW,KAAK,CAAC,6NAA6N,+GAA+G;AAAA,MAClV,QAAQ,CAAC,iNAAiN,4FAA4F;AAAA,MACtT,SAAS,CAAC,oOAAoO,yFAAyF;AAAA,MACvU,KAAK,CAAC,mMAAmM,8GAA8G;AAAA,MACvT,SAAS,CAAC,8KAA8K,4GAA4G;AAAA,MACpS,QAAQ,CAAC,4NAA4N,2EAA2E;AAAA,IAClT;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,4DAA4D,SAAS,CAAC,8CAA8C,kBAAkB,qBAAqB,GAAG,eAAe,GAAG,UAAU,uGAAuG;AAAA,MACpT,SAAS,EAAE,UAAU,2FAA2F,SAAS,CAAC,uBAAuB,gCAAgC,wCAAwC,GAAG,eAAe,GAAG,UAAU,oHAAoH;AAAA,MAC5W,SAAS,EAAE,UAAU,qDAAqD,SAAS,CAAC,qCAAqC,2DAA2D,4BAA4B,GAAG,eAAe,GAAG,UAAU,yHAAyH;AAAA,IAC1W;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAA0B,UAAU,CAAC,mBAAmB,kBAAkB,gBAAgB;AAAA,IACjG,OAAO,CAAC,sFAAsF,qFAAqF;AAAA,IACnL,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,uRAAuR,iGAAiG;AAAA,MAChY,SAAS,CAAC,uMAAuM,0GAA0G;AAAA,MAC3T,OAAO,CAAC,qNAAqN,gGAAgG;AAAA,MAC7T,KAAK,CAAC,8NAA8N,gGAAgG;AAAA,MACpU,QAAQ,CAAC,yOAAyO,uHAAuH;AAAA,MACzW,SAAS,CAAC,qPAAqP,0GAA0G;AAAA,MACzW,KAAK,CAAC,4NAA4N,wIAAwI;AAAA,MAC1W,SAAS,CAAC,qLAAqL,6GAA6G;AAAA,MAC5S,QAAQ,CAAC,oMAAoM,2GAA2G;AAAA,IAC1T;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,4DAA4D,SAAS,CAAC,2CAA2C,iBAAiB,4BAA4B,GAAG,eAAe,GAAG,UAAU,gGAAgG;AAAA,MAChT,SAAS,EAAE,UAAU,kEAAkE,SAAS,CAAC,qCAAqC,wCAAwC,kBAAkB,GAAG,eAAe,GAAG,UAAU,sHAAsH;AAAA,MACrV,SAAS,EAAE,UAAU,0EAA0E,SAAS,CAAC,kCAAkC,2BAA2B,gEAAgE,GAAG,eAAe,GAAG,UAAU,iHAAiH;AAAA,IACxX;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAAkC,UAAU,CAAC,kBAAkB,YAAY,QAAQ;AAAA,IAC1F,OAAO,CAAC,sFAAsF,oGAAoG;AAAA,IAClM,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,qPAAqP,8GAA8G;AAAA,MAC3W,SAAS,CAAC,gOAAgO,+GAA+G;AAAA,MACzV,OAAO,CAAC,sOAAsO,uHAAuH;AAAA,MACrW,KAAK,CAAC,yNAAyN,yGAAyG;AAAA,MACxU,QAAQ,CAAC,+NAA+N,0HAA0H;AAAA,MAClW,SAAS,CAAC,wOAAwO,2GAA2G;AAAA,MAC7V,KAAK,CAAC,uPAAuP,kHAAkH;AAAA,MAC/W,SAAS,CAAC,iLAAiL,yGAAyG;AAAA,MACpS,QAAQ,CAAC,2LAA2L,gFAAgF;AAAA,IACtR;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,uDAAuD,SAAS,CAAC,0CAA0C,wCAAwC,2CAA2C,GAAG,eAAe,GAAG,UAAU,mGAAmG;AAAA,MACnV,SAAS,EAAE,UAAU,yFAAyF,SAAS,CAAC,4BAA4B,6BAA6B,0BAA0B,GAAG,eAAe,GAAG,UAAU,2GAA2G;AAAA,MACrV,SAAS,EAAE,UAAU,yCAAyC,SAAS,CAAC,sEAAsE,iCAAiC,+BAA+B,GAAG,eAAe,GAAG,UAAU,iHAAiH;AAAA,IAChW;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAAqB,UAAU,CAAC,eAAe,oBAAoB,qBAAqB;AAAA,IAC/F,OAAO,CAAC,6FAA6F,uGAAuG;AAAA,IAC5M,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,kRAAkR,+HAA+H;AAAA,MACzZ,SAAS,CAAC,wNAAwN,uJAAuJ;AAAA,MACzX,OAAO,CAAC,yQAAyQ,6HAA6H;AAAA,MAC9Y,KAAK,CAAC,2QAA2Q,0IAA0I;AAAA,MAC3Z,QAAQ,CAAC,0NAA0N,mIAAmI;AAAA,MACtW,SAAS,CAAC,mOAAmO,6HAA6H;AAAA,MAC1W,KAAK,CAAC,wOAAwO,2HAA2H;AAAA,MACzW,SAAS,CAAC,mNAAmN,uHAAuH;AAAA,MACpV,QAAQ,CAAC,oPAAoP,8GAA8G;AAAA,IAC7W;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,sEAAsE,SAAS,CAAC,uCAAuC,gCAAgC,2CAA2C,GAAG,eAAe,GAAG,UAAU,gIAAgI;AAAA,MACpX,SAAS,EAAE,UAAU,oEAAoE,SAAS,CAAC,kCAAkC,sCAAsC,0BAA0B,GAAG,eAAe,GAAG,UAAU,8GAA8G;AAAA,MAClV,SAAS,EAAE,UAAU,kEAAkE,SAAS,CAAC,mCAAmC,+EAA+E,iCAAiC,GAAG,eAAe,GAAG,UAAU,0IAA0I;AAAA,IAC/Z;AAAA,EACF;AACF,CAAC;","names":[]}
|