p3-puzzle-variations
EECS 498 APSD Project 3: Puzzle Extensions
Feature Demo: In Lab Fri Feb 20 (No specific deliverables required, but we will meet briefly with each team to check in and answer any questions you have.)
Project Deliverables: Due Fri Feb 27 at 11:59pm.
Changelog
We’ll record updates and fixes to the project specification here.
Thu, Feb 19 1:00pm - Spelling Bee Themes
Added the remaining spelling bee themes to the specification.
Sun, Feb 22 11:00am - Various Clarifications
Added the following clarifications:
- Use “_hint” rather than “hint” for the Spelling Bee hint action.
- Corrected an implementation note for the Mineseweeper chord action. The action is allowed if flags match the number of neighboring hidden mines, not total number of neighboring hidden items.
- Clarified the precedence order for the Minesweeper cell effects to include empty cells. If a chord action reveals an empty cell and a smoke bomb, the empty cell’s flood-fill reveal happens first and the smoke bomb may re-hide some of those empty cells.
- Added an optional suggestion for background colors in minesweeper.
Introduction
In this project, your group will add new actions and variations to the existing puzzles from your project 2 codebase:
- New Actions: Implement a new action for each puzzle.
- Game Variations: Implement new variations/customizations for each puzzle.
In each of these categories, you only need to implement the new features for two of the three puzzles for the initial deliverables deadline. You can choose which ones to implement first. For the revisions deadline, you will need to implement the remaining features as well.
Prerequisites
This project continues from your existing group project codebase. Continue working in your same group repository. From previous projects, you should already have:
- All three puzzles working, with core game logic decoupled from specific file, CLA, or user-interface implementations.
- A text-based user interface (TUI) that allows player login, selecting puzzles to play, and autosave/resume.
- Database integration for storing player info, sudoku puzzles, and autosave data.
If you’re missing any of these, refer back to the Project 2 Specification.
Setup
No additional setup is required beyond what you already have from previous projects, except for the installation of any new third-party libraries you choose to use for the new features. See the “Third-Party Libraries” section below for instructions on how to add dependencies to your project.
Part 1: Additional Actions
Implement a new action for each puzzle. Consider this a “stress test” for your project design - if adding this feels cumbersome, there may be ways to improve.
IMPORTANT: For the initial deliverables deadline, you only need to implement the new actions for two of the three puzzles (your choice). For the revisions deadline, you will need to implement the remaining action as well.
Minesweeper: Chord
If a player believes they have correctly flagged all mines neighboring a cell, they can take the chord action on that cell to reveal its remaining hidden, non-flagged neighbors all at once.
Usage: chord x y
Behavior:
- May only be applied to an already-revealed, non-empty cell at coordinates (x, y) where the number of neighboring flags is precisely equal to the number of neighboring hidden mines (not items). If this is not true, the action is rejected (in the same way that e.g. attempting to flag a hidden cell is rejected).
- If the move is valid, all hidden, non-flagged neighbor cells are revealed. The effects of revealing those cells are applied, including the flood-fill reveal for empty cells and effects from any items in the cells.
Example:
Before chord - the cell at (E, 7) shows “2” and has exactly 2 flagged neighbors:
A B C D E F G H I J K L M N O
+-------------------------------+
9 | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
8 | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
7 | _ _ 1 1 2 F 3 1 2 _ _ _ _ _ _ |
6 | _ _ 1 2 F 2 1 _ _ _ _ _ _ |
5 | _ _ 1 1 1 1 1 1 1 1 2 _ _ |
4 | _ _ 2 1 _ _ |
3 | _ _ 1 1 1 1 1 1 2 _ _ |
2 | 2 2 1 1 F 1 1 2 3 _ _ _ _ |
1 | 1 1 1 1 _ _ _ _ _ _ |
0 | 1 _ _ _ _ _ _ |
+-------------------------------+
A B C D E F G H I J K L M N O
After chord E 7 - the hidden, non-flagged neighbors of (E, 7) are revealed:
A B C D E F G H I J K L M N O
+-------------------------------+
9 | _ _ _ _ 1 1 _ _ _ _ _ _ _ _ |
8 | _ _ _ 2 2 1 _ _ _ _ _ _ _ _ |
7 | _ _ 1 1 2 F 3 1 2 _ _ _ _ _ _ |
6 | _ _ 1 2 F 2 1 _ _ _ _ _ _ |
5 | _ _ 1 1 1 1 1 1 1 1 2 _ _ |
4 | _ _ 2 1 _ _ |
3 | _ _ 1 1 1 1 1 1 2 _ _ |
2 | 2 2 1 1 F 1 1 2 3 _ _ _ _ |
1 | 1 1 1 1 _ _ _ _ _ _ |
0 | 1 _ _ _ _ _ _ |
+-------------------------------+
A B C D E F G H I J K L M N O
Implementation Notes
- See the section below on additional items beyond mines. If multiple items are revealed via a single chord, they are processed in the precedence order described in the section below.
- The number of neighboring hidden mines is not necessarily the cell number, because the cell number counts non-mine items, and also because play may continue after a mine has been revealed if the player has a shield.
- This action is not “safe”. It is allowed as long as the number of flags matches the number of neighboring hidden mines, such that the move is plausibly safe. However, if the player misplaced the flags, a chord can reveal a mine.
Spelling Bee: Hint
The hint action requests a hint about one of the remaining valid words in the puzzle, which is provided by partially revealing the word with random letters hidden.
Usage: _hint
Behavior:
- Selects a random word from the remaining valid words.
- Displays the word with half (round down) of its letters randomly replaced with underscores (
_). - Successive hints will likely reveal different words and/or different letters on each attempt.
Example:
If the word is "PUZZLE", the hint might show: "P_Z__E" or "__Z_LE"
Note: We use “_hint” to avoid conflicting with “hint” as a possible guessed word.
Sudoku: Fill
The fill action provides an auto-complete feature for cells that can be logically deduced.
Usage: fill x y
Behavior:
- May only be applied to a cell at coordinates (x, y) if the cell belongs to a row, column, or 3x3 subgrid where the other 8 cells are correctly filled. If this is not true, the action is rejected (in the same way that e.g. attempting to overwrite a starter cell is rejected).
- If the move is valid, the cell is automatically filled with the only remaining number for that row, column, or subgrid (i.e. the correct solution number).
Example:
A row contains: 1 2 3 4 _ 6 7 8 9
Using fill on the empty cell places "5" automatically.
Note: The fill action only works when there is exactly one missing number. It does not apply more complex logic that might be able to deduce the correct number by other means.
Part 2: Game Variations
Implement new variations/customizations for each puzzle. You’ll want to consider the appropriate use of polymorphism and composition here.
IMPORTANT: For the initial deliverables deadline, you only need to implement the additional variations for two of the three puzzles (your choice). For the revisions deadline, you will need to implement the remaining variation as well.
Minesweeper: Special Items
In addition to mines, the grid now contains special item cells that interact with gameplay in unique ways.
New Cell Types
| Item | Effect When Revealed |
|---|---|
| Shield | Grants the player protection from the next mine hit. The mine is revealed but the game does not end. Shields do not stack-revealing multiple shields still only protects from one mine. |
| Smoke Bomb | Returns all revealed non-item cells within Manhattan distance <= 4 to a hidden state. Previously placed flags are not removed. Cells containing mines or items (including the smoke bomb itself) are not re-hidden, since that would allow replaying their effects. |
| Scanner | Automatically flags all mines within Manhattan distance <= 4 from the scanner cell. |
Precedence Order: When multiple cells are revealed at once (e.g., via a chord action), their effects are processed in the following order: Empty → Shield → Mines → Smoke Bomb → Scanner. This means a shield will protect against a mine revealed in the same action, and a smoke bomb will re-hide hidden cells, including those that are flood-filled as a result of revealing an empty cell (though it will not re-hide mines or items).
Manhattan Distance: The sum of the absolute differences of coordinates. For cell (x₁, y₁) and (x₂, y₂): |x₁ - x₂| + |y₁ - y₂|.
Visual Distinction
Special item cells contribute to the neighbor count the same way mines do. However, cells adjacent to at least one actual mine should be visually distinguished from cells that are only adjacent to items.
Display Options (choose one or implement your own):
- Use different text colors.
- Use different background colors.
- Use a special indicator character or symbol.
For example, you could display cells with a these background colors:
- No neighboring items: no background color
- Neighboring mines (but no items): red background
- Neighboring items (but no mines): green background
- Neighboring both mines and items: yellow background
Win Condition
The game is won when one of the following is true:
- All remaining hidden mines are flagged (and no extra flags are placed on non-mine cells), OR
- All non-mine cells (including special items) are revealed.
Configuration
When starting a Minesweeper game, players should be able to configure:
- Grid dimensions (as before)
- Number of mines (as before)
- Number of each special item type (shields, smoke bombs, scanners)
Or, if you prefer, you can define preset configurations (e.g., “Easy”, “Medium”, “Hard”, “Scanner Bonanza”, etc.) that specify these parameters for the player to choose from.
Spelling Bee: Variable Letter Count
The classic Spelling Bee uses 7 letters in a honeycomb pattern. This variation allows the letter count to be customized, with each count having its own visual theme.
Supported Letter Counts
In each of the display formats below, the numbers represent letter positions (not actual letters). 0 represents the “center” letter that must be included in every word, while 1, 2, etc. represent the other letters that can be used. On a shuffle, the 0th letter remains in the same position while the others can change positions.
4 Letters
Theme Name: Shelling Pea
ASCII Art: A pea pod with a leaf.
__ / ___ words
__ / ___ points ___
_______________________/__/
\/ 0 \/ 1 \/ 2 \/ 3 \ /
\___/\___/\___/\___//
5 Letters
Theme Name: Swelling Knee
ASCII Art: An injured knee.
~ ~
------- !! ~ __ / ___ words
1 2 0 \ ~ __ / ___ points
‾‾‾‾\ 3 \
\ 4 \
\___\__
|______]
6 Letters
Theme Name: Smelling Tea
ASCII Art: A cup of aromatic tea.
( )
) ) ( (
( ( ) ) __ / ___ words
_____________ __ / ___ points
_ (_____________)
/_\| [1] - [2] - |
||_||] - [0] - [3]|
\_/| [5] - [4] - |
\___________/
7 Letters
Theme Name: Spelling Bee
ASCII Art: A honeycomb.
___
___/ 2 \___ __ / ___ words
/ 1 \___/ 3 \ __ / ___ points
\___/ 0 \___/
/ 6 \___/ 4 \
\___/ 5 \___/
\___/
8 Letters
Theme Name: Stelling Free
ASCII Art: A cow escaping an enclosure.
_ / __ / ___ words
| |// __ / ___ points
|/|// )__)
_ _ _ /|/|/ _________o(O O)o
| |___| |___| |//|/| --- _/\/ (_°°_)
| |---| |---| |//| | --- | 01234567 |‾‾
| |---| |---| |/ --- \__________//
| |---| |---| | / / | \
\ \ / /
Configuration
When starting a Spelling Bee game, players should be able to:
- Choose the number of letters (4-8)
- The corresponding theme/display is automatically selected
Sudoku: Emoji Themes
Instead of numbers 1-9, players can choose to play with any characters, including emoji.
Note: Because emoji will not display as nicely with colored text, consider switching to use colored backgrounds to distinguish incorrectly placed symbols instead of colored text.
Predefined Themes
| Theme | Emoji Set |
|---|---|
| Classic | 1 2 3 4 5 6 7 8 9 (default numeric) |
| Vacation | 🏄🌴🌊🍹🧳🐚🦀🚢🌅 |
| Food | 🍕🍔🌮🍣🍩🍪🍰🧁🍦 |
| Space | 🚀🌙⭐🌕👽🛸💫🌌🔭 |
Custom Themes
Players can also provide their own set of 9 characters or emoji:
- Input as a string containing exactly 9 distinct characters, with no spaces.
- Symbols can be typed directly or pasted.
Gameplay and Example
The Sudoku board is displayed in a similar way to before, but you will need to account for the different display widths of the emoji symbols. Additionally, to the right of the board, print a legend showing the symbols, their corresponding numbers, and the emoji name. See below for implementation details and suggestions for 3rd party libraries to help work with emoji.
Here is an example of the display for a space-themed Sudoku puzzle:

Configuration
When starting a Sudoku game, players should be able to:
- Select a predefined theme (Classic, Vacation, Food, Space)
- Enter a custom theme string
Example: The user is prompted to select a theme and selects “Vacation”: ```Select theme:
- Classic 1 2 3 4 5 6 7 8 9 (default numeric)
- Vacation 🏄🌴🌊🍹🧳🐚🦀🚢🌅
- Food 🍕🍔🌮🍣🍩🍪🍰🧁🍦
- Space 🚀🌙⭐🌕👽🛸💫🌌🔭
- Custom Enter choice: 2 ```
Or, the user selects option 5 above for a custom theme and is prompted to enter their own characters:
...
Enter choice: 5
Enter custom theme (9 chars, no spaces): 🐶🐱🐭🐹🐰🦊🐻🐼🐨
Implementation Notes
Working with emoji is a bit tricky.
Most emoji are encoded with multiple characters. For example, "🚀".length is 2. Because various combinations of symbols may be used, each with a different number of characters, it’s best to just represent your symbols as an array of 9 strings.
The good news is that Array.from() will correctly split a string into its user-perceived symbols, even if they are made up of multiple characters. For example, Array.from("🚀🌙🌟🌕👽🛸💫🌌🔭") will return ["🚀","🌙","🌟","🌕","👽","🛸","💫","🌌","🔭"]. Additionally, if the user specifies a custom set of emoji at the prompt, you can read it in as a string and then immediately pass to Array.from().
Many emoji print out at the terminal with a display width of 2 characters. You’re welcome to assume a display width of 2, or you can use the string-width package https://www.npmjs.com/package/string-width (install with pnpm to the appropriate package, for example pnpm add string-width --filter local-cli) to determine the display width of each symbol. You’ll want to find the maximum display width among the symbols, then add trailing spaces to the others as needed so that all are printed with a consistent width. Empty cells should be displayed with the same width as the symbols. You will also need to adjust the way the grid itself is printed.
Finally, when the user enters a symbol to place on the Sudoku board, you need to support them entering any of the following:
- The symbol itself (e.g. paste in “🚀”)
- The corresponding number (e.g. “1” for the first symbol in your theme array)
- The name of the emoji (e.g. “rocket” for “🚀”) or any prefix of the name (e.g. “r” or “ro” for “🚀”). If a prefix could match multiple emoji names, go with the first one matched.
You can use the node-emoji package https://www.npmjs.com/package/node-emoji to help with this (install with pnpm to the appropriate package, for example pnpm add node-emoji --filter local-cli).
Testing
You are welcome to add additional tests for your new features, but there are no specific testing requirements for this project. Focus on implementing the new features and variations, and ensure that you test them manually to confirm they work as expected.
Third-Party Libraries
You’re welcome to use third-party libraries in your project, as long as:
- They are generally compatible with the given project environment and structure (e.g. TypeScript,
node, SQLite, etc.). - They do not implement large portions of the project’s application for you (e.g. don’t import a 3rd-party Sudoku implementation or a user management library)
- They do not require significant changes to the project structure or build process.
- They do not involve esoteric or complex paradigms or coding practices. We need to be able to read and understand your code with a minimal learning curve.
- They do not dramatically alter the learning objectives of the project.
Along these lines, please do not introduce additional “frameworks” that differ substantially from the given project structure. e.g. Don’t switch to a different test runner, database ORM, or UI framework.
If you’re not sure, please reach out and ask us!
You should add dependencies only to the package that needs them. For example, to add a dependency to the local-cli package, run the following command from the root of the repository (where <dependency-name> is the name of the dependency you want to add):
$ pnpm add <dependency-name> --filter local-cli
If you want to remove a dependency, likewise use:
$ pnpm remove <dependency-name> --filter local-cli
Finally, make sure to think about whether a dependency should be added to a particular package. For example, if you’re considering a library like node-emoji, it should probably go in the local-cli app rather than the puzzle package, since the puzzles shouldn’t depend on terminal-specific functionality. (This aligns with moving I/O code out of the core puzzle implementations.)
Feature Demo
During lab on Friday, Feb 20, we will have a brief check-in with each team to answer any questions you have and/or provide feedback. Considering the short turnaround time, there are no specific features required to be complete. Teams will earn 100% after the check-in regardless of how much is completed.
Initial Deliverables Submission
Before submitting, update the README.md file in your repository with the following:
- Run instructions: Provide clear instructions for how to run your code.
- Project description: A brief description (no more than a paragraph) of your project organization and any significant updates since the last submission. We’re not grading the description directly, but it can help us more quickly navigate and understand your codebase.
- Third-party libraries: List any notable third-party libraries you used, other than those provided with the project distribution.
- AI disclosure: Document how your group used (or didn’t use) AI coding tools. A sentence or short paragraph is fine. For example: “We didn’t use any AI tools”, “We used AI tools for brainstorming but not coding”, “We used Copilot suggestions throughout the codebase”, or “We used Claude Opus 4.5 in VS Code Chat to help refactor the puzzle classes and generate test cases”. Remember that using AI tools is not prohibited, and we won’t grade your code differently based on AI usage. However, it’s helpful for us to understand how students are using these tools.
Your group will submit your project via a GitHub release. This allows you to tag a specific commit as your final submission.
- Ensure all your code is committed and pushed to your repository.
- Go to your repository on GitHub.
- Click on “Releases” in the right sidebar (or navigate to
https://github.com/eecs498-software-design/<your-repo>/releases). - Click “Draft a new release”.
- Create a new tag for the release named
p3-initial-deliverables. - Set the release title to “Project 3: Initial Deliverables”.
- You don’t need to put anything specific in the release description.
- Click “Publish release”.
Make sure to create your release before 11:59pm on the deadline.
Revisions Submission
After receiving feedback on your initial submission, your group will have the opportunity to make revisions and improvements. We’ll provide specific instructions on how to submit your revised project once the revision period begins. (It will involve creating another GitHub release similar to the initial submission process.)