Skip to content

feat: add High Speed Memory game plugin#8

Merged
acrosman merged 15 commits intomainfrom
copilot/create-high-speed-memory-game-plan
Mar 19, 2026
Merged

feat: add High Speed Memory game plugin#8
acrosman merged 15 commits intomainfrom
copilot/create-high-speed-memory-game-plan

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 17, 2026

Adds a second game — High Speed Memory — following the existing plugin architecture. Players briefly see a square grid of cards revealed, then must locate the three Primary.jpg cards hidden among Distractor images from memory. Grids grow as unbounded squares and reveal time shrinks each level.

Game logic (game.js)

  • Unbounded square grids: 3×3 at level 0, growing by 1 each level (4×4, 5×5, …)
  • Reveal duration: 1500ms at level 0, −25ms/level, floored at 20ms
  • Each round places exactly 3 copies of Primary.jpg at random positions; remaining cells are filled with a random mix of Distractor1.jpg and Distractor2.jpg
  • Level advancement: players must complete 3 consecutive correct rounds to advance to the next level (ROUNDS_TO_LEVEL_UP = 3); a wrong guess resets the streak and immediately restarts the current round
  • Pure functions: generateGrid, isPrimary, addCorrectGroup, completeRound, resetConsecutiveRounds, getConsecutiveCorrectRounds, getGridSize, getDisplayDurationMs

Plugin lifecycle (index.js)

  • startRound() — generates grid, renders all cards face-up using image files, hides after display duration
  • handleCardClick() — clicking a Primary card marks it as found (green); clicking a Distractor resets the level-up streak, plays a Web Audio buzzer, and restarts the round after a 900ms pause; finding all 3 Primary cards triggers onRoundComplete
  • onRoundComplete() — calls completeRound(); announces streak progress ("2 of 3 in a row — 1 more to level up!") or a level-up message; starts the next round after a brief pause
  • Grid fills available display space via 70vmin sizing (reliable square across all viewport sizes)
  • "Return to Menu" button in end panel dispatches bsx:return-to-main-menu to restore the game selector
  • Named exports for direct unit testing; window.api progress save loads existing data first then saves with { playerId: 'default', data: {...} } format — errors are swallowed

UI (interface.html / style.css)

  • WCAG 2.2 AA: aria-live regions for score/feedback, keyboard nav (Tab + Enter/Space), visible focus indicators, all contrast ratios ≥ 4.5:1; aria-labels updated per card state (face down / revealed / matched)
  • Instructions panel shows a preview of Primary.jpg (with green border) so players know what image to find before starting
  • Stats bar shows Level, Score, Found (x/3), and Streak (x/3) so players can track progress toward the next level
  • Instructions explain the 3-in-a-row requirement and that a wrong guess restarts the round; instructions → game area → end panel flow
  • End panel offers both Play Again and Return to Menu actions
  • Grid sized to 70vmin for a reliable square layout; the reveal-phase countdown banner has been removed to prevent the grid from shifting vertically

App shell (interface.js)

  • Added injectGameStylesheet(gameId) — injects <link id="active-game-stylesheet" rel="stylesheet"> into <head> when a game is loaded, so game-specific CSS Grid layout and card styles apply correctly
  • Added removeGameStylesheet() — removes the active stylesheet when returning to the main menu
  • Added loadAndInitGame() helper — centralizes HTML injection, CSS injection, and plugin init() call; used by all game:select handlers and the bsx:return-to-main-menu return path
  • This fix also applies to all other games (e.g. fast-piggie) whose stylesheets were also never loaded

Images

  • Uses Primary.jpg, Distractor1.jpg, Distractor2.jpg, and thumbnail.jpg — replace with final artwork when ready

Tests

  • tests/game.test.js — unit tests with 100% function coverage on game.js, including ROUNDS_TO_LEVEL_UP, resetConsecutiveRounds, and getConsecutiveCorrectRounds
  • tests/index.test.js — integration tests covering full lifecycle, timer clearing, keyboard events, Audio API, return-to-menu event dispatch, streak reset on Distractor click, round restart on wrong guess, streak display update, and window.api resolve/reject paths
Original prompt

/plan-highSpeedMemory

[Chronological Review: The conversation began with the user requesting the creation of a new high-speed memory game. The user outlined the game mechanics, including grid size, image matching, and scoring. The user then requested to create a file for this plan, which was followed by a command to reference the plan in a specific format.]

[Intent Mapping: The user explicitly requested to create a second game focused on high-speed memory, detailing the mechanics and requirements. The user also requested to create a file for further refinement of this plan.]

[Technical Inventory: The conversation involved the creation of a game plan, including specifications for grid size, image matching, and scoring mechanics. The user mentioned using a grid layout that increases in size over time and specified timing for image display.]

[Code Archaeology: The user requested to create a file named untitled:plan-${camelCaseName}.prompt.md to store the game plan without frontmatter. The current file being worked on is /Users/acrosman/Documents/PersonalRepos/BrainSpeedExercises/.github/prompts/plan-highSpeedMemory.prompt.md.]

[Progress Assessment: The user has successfully outlined the game mechanics and requested the creation of a file for the plan. The next step involves refining this plan.]

[Context Validation: All critical information regarding the game mechanics and file creation is captured for continuation.]

[Recent Commands Analysis: The last agent command executed was a request to create a file for the game plan. The user specified the format for the file name. The immediate pre-summarization state involved the user working on the game plan in the specified markdown file.]

1. Conversation Overview: - Primary Objectives: The user requested, "Time to create a second game. This one is a high speed game of memory..." detailing the mechanics and requirements for the game. - Session Context: The conversation flowed from outlining the game mechanics to requesting the creation of a file for the game plan. - User Intent Evolution: The user's needs remained focused on developing a high-speed memory game, culminating in a request to create a file for further refinement.
  1. Technical Foundation:
  • Game Mechanics: The game involves identifying matching images in a grid that increases in size over time, with specific timing for image display and scoring rules.
  1. Codebase Status:
  • File Name: /Users/acrosman/Documents/PersonalRepos/BrainSpeedExercises/.github/prompts/plan-highSpeedMemory.prompt.md
  • Purpose: To outline the plan for the high-speed memory game.
  • Current State: The user has requested to create a new file for this plan.
  • Key Code Segments: Not applicable yet as the plan is still being formed.
  • Dependencies: The plan will guide future development of the game.
  1. Problem Resolution:
  • Issues Encountered: None reported yet.
  • Solutions Implemented: The user has clearly outlined the game mechanics.
  • Debugging Context: No ongoing troubleshooting efforts noted.
  • Lessons Learned: The importance of clear specifications for game mechanics.
  1. Progress Tracking:
  • Completed Tasks: The game mechanics have been outlined.
  • Partially Complete Work: The creation of the plan file is in progress.
  • Validated Outcomes: None yet, as the game is still in the planning phase.
  1. Active Work State:
  • Current Focus: The user was focused on creating a file for the game plan.
  • Recent Context: The user requested to create a file named untitled:plan-${camelCaseName}.prompt.md for the game plan.
  • Working Code: Not applicable yet as the plan is still being formed.
  • Immediate Context: The user was actively working on the game plan when the token budget was exceeded.
  1. Recent Operations:
  • Last Agent Commands: The user executed a command to create a file for the game plan.
  • Tool Results Summary: The command to create a file was acknowledged, but the file creation process is pending.
  • Pre-Summary State: The user was actively working on the game plan in the specified markdown file.
  • Operation Context: These commands were executed to facilitate the development of the high-speed memory game as per the user's specifications.
  1. Continuation Plan:
  • Pending Task 1: Further refine the game plan in the newly created file.
  • Pending Task 2: Implement the game mechanics as outlined in the plan.
  • Priority Information: Refining the game plan is the most urgent next step.
  • Next Action: The immediate next step is to create the file for the game plan as specified by the user.

Created from VS Code.


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

Copilot AI and others added 2 commits March 17, 2026 22:32
Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copilot AI changed the title [WIP] Add plan for high-speed memory game feat: add High Speed Memory game plugin Mar 17, 2026
Copilot AI requested a review from acrosman March 17, 2026 22:35
@acrosman
Copy link
Copy Markdown
Owner

@copilot The game needs several adjustments:

  1. The grid should be a square not a rectangle, starting at 3x3. It should continue to get larger with each level. No upper bound.
  2. It should use files not unicode code points for the images. Images will be provided later.
  3. The display peroid is supposed to range from 500ms - 20ms.
  4. The game should use all avialable display space.
  5. Wrong guesses should play a sound, not shake.
  6. There should be three images that match in each round, not two.
  7. There is an error when the user quits the game: Error occurred in handler for 'progress:save': Error: playerId must be a non-empty string. at validatePlayerId (file:///Users/acrosman/Documents/PersonalRepos/BrainSpeedExercises/app/progress/progressManager.js:16:11)

Copilot AI and others added 2 commits March 18, 2026 01:18
…images, sound, display range, progress fix)

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
…ling blank lines

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot The game needs several adjustments:

  1. The grid should be a square not a rectangle, starting at 3x3. It should continue to get larger with each level. No upper bound.
  2. It should use files n...

All 8 items addressed in commit ce975ba:

  1. Square grid, no upper bound — Level n now produces an (n+3)×(n+3) grid (3×3 → 4×4 → 5×5 …). getGridSize is unbounded.
  2. Image files — Cards use <img> elements. 48 placeholder SVGs (card-01.svgcard-48.svg) plus card-back.svg are in images/. Swap the files when real artwork is ready.
  3. Display range 500ms → 20msBASE_DISPLAY_MS = 500, MIN_DISPLAY_MS = 20, decrement 24ms/level.
  4. All available display space — Grid is sized to min(90vw, calc(100vh - 260px)), making it square and viewport-filling.
  5. Sound on wrong guess (not shake) — Shake animation removed; a short Web Audio API sawtooth buzzer plays instead.
  6. Three matching images per roundMATCH_SIZE = 3; handleCardClick waits for 3 flips before evaluating a group.
  7. Progress save error fixedstop() now calls progress:load first then progress:save with { playerId: 'default', data: { ... } }.

Game UI showing 4×4 square grid with coloured image cards, "Groups: 1 / 5" stat, and a 380ms countdown banner

@acrosman
Copy link
Copy Markdown
Owner

@copilot Again, there are several adjustments to make:

  1. I've removed the generated images infavor of a smaller number of jpg. thumbnail.jpg should replace thumbnail.svg. The card-*.svg files have all been deleted - remove any reference to them. For each round, Primary.jpg should appear 3 times, the other images should be a random mix of the Distractor images.
  2. The grid does not display as a grid in my testing. It was a line of dots that were impossible to tell apart.
  3. The end game button still does not return the player to the main screen with the list of games they can play.

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot Again, there are several adjustments to make:

  1. I've removed the generated images infavor of a smaller number of jpg. thumbnail.jpg should replace thumbnail.svg. The card-*.svg files have al...

All three items addressed in commit 234a203:

  1. Images: All card-*.svg references removed. game.js now places exactly 3 copies of Primary.jpg at random positions in the grid and fills remaining cells with random picks from Distractor1.jpg / Distractor2.jpg. manifest.json updated to thumbnail.jpg. The game mechanic is now single-click: clicking a Primary card marks it as found (green outline); clicking a Distractor plays the buzzer and flips it back.

  2. Grid display: Replaced the unreliable min(90vw, calc(100vh - 260px)) sizing with 70vmin (= min(70vw, 70vh)), which always renders a square grid that fits the viewport. Cards no longer need a card-back image — face-down cards simply hide the <img> via style.display: none while keeping the dark card background.

  3. End Game / Return to Menu: Added a "Return to Menu" button alongside "Play Again" in the end panel. Clicking it dispatches bsx:return-to-main-menu, the same event interface.js listens for to restore the game selector with refreshed high scores.

Grid showing correctly as 4×4 square — one matched Primary card (green outline), one revealed Primary (salmon), rest face-down (dark)

@acrosman
Copy link
Copy Markdown
Owner

@copilot I do not see what's in the generated image in the response.

The thumbnail is now right.

The game briefly flashed one image and then looked like this:
image

The images need to be scaled to the expected size. The grid should stay a grid. Check to make sure whatever you think is used to hold those spaces actually exists and is in the expected location.

…ectly

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot I do not see what's in the generated image in the response.

The thumbnail is now right.
...

Fixed in commit ecc95e3. The root cause was that interface.js injected the game's HTML fragment but never loaded its style.css — so the CSS Grid layout, card sizing, and button styles were never applied, leaving unstyled buttons in a line.

The fix adds three helpers to interface.js:

  • injectGameStylesheet(gameId) — creates a <link id="active-game-stylesheet"> in <head> pointing to games/{gameId}/style.css
  • removeGameStylesheet() — removes it when returning to the menu
  • loadAndInitGame() — centralizes the HTML injection + CSS injection + plugin init, used by both game:select handlers

This also benefits fast-piggie, which had the same issue (it happened to be functional without CSS since its game display is canvas-rendered).

3×3 grid showing correctly styled cards — matched Primary (green outline), revealed Primary (image visible), face-down Distractor cards (dark background)

@acrosman
Copy link
Copy Markdown
Owner

@copilot the player should only advance to the next level if they pick the right set of images three times in a row.

… Speed Memory

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot the player should only advance to the next level if they pick the right set of images three times in a row.

Done in commit bb449a1. A wrong guess in any round now resets a streak counter to zero. The level only advances once the streak reaches 3 — meaning the player must find all 3 Primary cards three rounds in a row without clicking a Distractor.

Changes:

  • game.jsROUNDS_TO_LEVEL_UP = 3 constant; completeRound() only increments level every 3rd consecutive correct round; new resetConsecutiveRounds() called by a wrong guess
  • index.js — Distractor click now calls resetConsecutiveRounds(); the round-complete message tells the player their current streak ("2 of 3 in a row — 1 more to level up!") or announces a level-up
  • interface.html — "Streak: X / 3" counter added to the stats bar; instructions updated to describe the 3-in-a-row requirement

Stats bar showing Level, Score, Found, and the new Streak counter

@acrosman
Copy link
Copy Markdown
Owner

@copilot That's better. Now we need to add the primary image to the instructions page so that players know what image to click on. Also when they click on the wrong image it should immediate re-run that level not let them finish. Finally, the grid moves vertically because of the message displayed at the top. That message isn't helpful, remove it.

…ve countdown banner

Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot That's better. Now we need to add the primary image to the instructions page so that players know what image to click on. Also when they click on the wrong image it should immediate re-run ...

Done in commit 05ed46e:

  1. Primary image on instructions — The instructions panel now shows Primary.jpg with a green border and a caption ("Find this card — it appears three times each round") so players know what to look for before starting.

  2. Wrong guess restarts the round — Clicking a Distractor now locks the board, plays the buzzer, resets the streak, and restarts the round after a 900ms pause (so the wrong card is briefly visible). The player can no longer finish the round after a wrong guess.

  3. Countdown banner removed — The "Memorize! Cards hide in Xms…" banner and all its show/hide code have been removed. The grid no longer jumps vertically. Screen-reader announcements are preserved via the hidden #hsm-feedback element.

@acrosman acrosman marked this pull request as ready for review March 19, 2026 02:50
Copy link
Copy Markdown
Owner

@acrosman acrosman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is acceptable

@acrosman acrosman merged commit 3ad4a90 into main Mar 19, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants