_**Editor's note**: My style of prompting Claude Code is with long Markdown prompts that are comprehensive and ideally give the LLM no wiggle room to interpret intent incorrectly. They are invoked by tagging the file, and then giving the command `implement`. After each prompt, the code is manually reviewed, manually tested to ensure the implementation matches the input prompt, then manually committed to `git`._

_This list of prompts is not 100% comprehensive: quick in-line followups are not recorded. Prompts made after public release are not recorded._

# 001.md

Create a terminal application using the Rust programming language which creates a physics simulation of thousands of balls, leveraging the unique aspects of the terminal to create a unique experience for a terminal application.

Due to terminal display constraints, it cannot visually display thousands of balls, which is intentional. Instead, use clever and unique visual tricks to emulate it. You MUST use Braille unicode characters to simulate up to eight (8) subballs per character location. For example, with the character ⢗, there is spatially five (5) balls at the same spot, with one bell in the top-left-most area of the character, two below it, one ball below that on the left, and one ball in the bottom-right-most area of the character. If there are a large amount of balls spatially in a given character position, additionally color the background to visually simulate the density.

The terminal application MUST include ALL of the FOLLOWING features and constraints:

- The entire terminal window is the canvas except the lowest two rows of the terminal which displays the application metadata and can expose menus for the users to interact with.
  - e.g. add displays showing the number of balls active, a button to indicate an options expansion, a button to reset the canvas.
- Use the `rapier` crate for the physics simulation. Only include 2D functions.
  - The physics must be extremely realistic, including gravity and momentum
  - Maximize physics parallelization with computation
- Use the window `resize` events in `crossterm` as physics: the faster the user resizes the window, the faster and farther the balls are pushed
- Include mouse interactivity with the application
  - Allow user to click menu items
  - If the user clicks the top 1/4th of the canvas, it adds more balls at the location the user clicked, which fall down due to gravity
  - Create a repulsing "burst" effect at the location the user clicks
- Each ball entity must account for velocity (`x` and `y`), along with other relevant properties.
- Include an options menu which can be toggled that contains user adjusted features, including:
  - Target FPS
  - Visual FPS toggle on the status bar (to two significant figures). Default OFF
  - The number of balls. Default: 1024
  - Gravity
  - The friction coefficient of the balls
- By default, the FPS of the application is 60 FPS (which the physics ticks updating each frame), but allow users to specify the FPS.

ALL Rust crates installed MUST use the most up-to-date version possible: check each package to confirm.

---

# 002.md

Update the `rapier2d` crate to the latest version (0.32.0) and `rayon` crate to the latest version (1.11.0) and ensure all tests pass.

---

# 003.md

There are a number of bugs related to collisions which you MUST fix:

- Balls can get permanently stuck in the four corners of the canvas. Add an invisible collider proportionate to the ball size to prevent it from getting stuck in the corners.
- Reduce the repulsing "burst" effect force caused by mouse clicking the canvas by about 25%.
- Make it such that if the user holds down the mouse click, it continues to repel the balls until the user lets go of the hold.
- The force applied to the balls when resizing the window is WAY too great. The burst force applied should be equivalent to around half of the mouse click after the previous adjustment per character moved.

- When the user adds balls by clicking the top 1/4 of the screen, the balls are immediately repulsed. Prevent the repulsing effect when clicking at this area.
- The user MUST be able to click-and-hold the top 1/4 of the screen to generate balls repeatedly, with the number of balls increasing significantly over time while the user holds.

Additionally, add another row at the top of the bottom UI rows (i.e. 3 rows total): the new row has roughly-equally spaced numeric digits corresponding to the keyboard position up to 6 digits total in the terminal colors red, green, yellow, blue, magenta, cyan. Make such that when the user presses the keyboard, it creates a repulsing "burst" effect directly **upward** at that spot. In small terminal windows, you may reduce the quantity of digits but the repulsing "burst" effect MUST still occur at the specified digit the user presses. The user should be able to click the number to cause the same burst.

Furthermore:

- allow the user to manually type numeric values (such as the number of balls) in the Options menu
- Add a feature to the Options menu to set the force of actions (affecting mouse click, resize, and the numeric burst.). This should be a percentage of the default, starting at 100%
- Change both the gravity and friction options setting to be a percentage of the default, starting at 100%
- Set the FPS indicator ON by default
- Set the default number of balls to `2000`. Add a CLI command to set the default number of balls on app run.
- Set the new maximum ball limit to `32768` balls as a constant. Prevent the user from adding balls via the click-and-hold method when at this limit, and force the value to the maximum ball limit if the user inputs a value over it.

---

# 004.md

Fix ALL the following changes from the previous plan:

- Implement a sanity cap on ball velocity so the ball cannot achieve infinite speed.
- Objects continue getting stuck in the corners. Increase the size of the collider.
- For the numeric geysers, the colors and geysers should encompass the entire row, not just the numeric background. The geysers should launch with the appropriate width of the true geyser.
- For the values in options, starting the edit should replace the existing value, and reverting if the edit is cancelled.
- If the number of balls in the options menu is changed and commited, automatically perform a Reset upon closing the option menu.

See the attached image screenshot of the current application to view the objects getting stuck in corners, and the too small numeric geysers.

---

# 004a.md

Although the app no longer crashes on load with 10,000 balls, even with 5,000 balls there are still crashes when manipulating the large amounts of balls with lots of physics actions. See attached log.

---

# 004b.md

There is a crash when too many physics operations are happening. It is less likely at low balls but still occurs. The root cause may be a new physics engine tweak in `rapier` 0.32.0. Downgrade to `rapier` 0.31.0 and make appropriate code changes to verify.

---

# 005.md

When resizing the terminal, it applies the force to ALL the balls which is VERY INCORRECT.

The intended behavior is that if a window resizing pushes the boundaries against the balls. it applies the force against the balls that are "hit" by it, e.g. if the window shrinks, it will hit balls directly adjacent to it depending on the rate of shrinkage.

---

# 006.md

- Set the Up/Down/Left/Right keys to nudge all the balls Up/Down/Left/Right, akin to a pinball table.
- Set up the Shift+1/2/3/4/5/6 hotkeys to spawn balls from the top of the spawn area across the width of the corresponding sections
- Set up the Space bar key as a shortcut to spawn balls from the top of the spawn area across the width of the entire spawn. Include holding behavior.
- Add padding asterisks to the geyser number when the geyser is activated to make it more visible that a geyser launched
- Change the color of the geyser numeric text to terminal black
- Remove the `Target FPS` option and ALL corresponding logic from the code. The application MUST run as fast as possible by default.
- Add a `60 FPS Cap` toggle option that caps the logical frame rate at 60 FPS. Default OFF

---

# 006b.md

The behaviors for spawning balls are not correct and MUST be fixed:

- For the mouse-click-and-hold behavior, it only spawns balls on the first click, then rapidly spawns balls after holding for a few seconds. It must spawn balls on click, continue spawning balls while holding, then the quantity ramps up while continuing to hold.
- For the `Space` behavior, it does spawn while holding `Space`, but after holding space for a few seconds, it starts rapidly spawning balls with no control. Logic MUST be similar to the click-and-hold behavior.
- Change the shortcuts for Shift+1/2/3/4/5/6 to the corresponding alphanumeric character (!/@/#/$/%/^)

---

# 006c.md

Two more remaining issues:

- After pressing `Space` once, the balls still continue to spawn infinitely after a delay.
- The new keyboard shortcuts currently do not ramp up spawn production like clicking-and-holding. it should also ramp up.

---

# 007.md

Add comprehensive support to add shape objects to the level and interactivity with those shapes, with both keyboard and mouse. These shapes are polygonal colliders which interact with the balls.

- The shapes are invoked with a new `[S]hapes` button.
- Also add a `[C]lear` button to delete all shapes in the world
- Add the ability to select a shape via clicking it, with some mechanism to identify a highlighted shape
- The following shapes are available, displayed in a 3x3 grid when the `[S]hapes` button is activated:
  - Circle
  - Triangle
  - Square
  - Diamond
  - Star
  - Straight Line
  - 20 degree line
  - 30 degree line
  - 40 degree line
- When the shape is selected from the `[S]hapes` menu, it is randomly placed but it MUST not be placed in the spawn zone or overlap an edge, or not overlap another shape if possible.
- Shapes should retain their absolute positions if the window is resized.
- The shapes are rendered using the complete ASCII table of characters. Do NOT use `.`, `:`. or `;`, or any characters that could be interpreted as a ball/Braille character.
- The shapes ALL MUST be sized between 4-6 character height and 4-7 character width.
- The shapes are by-default terminal green. This will be modifyable in a future implementation, so implement abstractly.
- Add `z` and `x` keyboard shortcut to rotate a selected shape clockwise/counterclockwise 45 degrees.
- Upon app load, automatically place 2-4 shape objects on the canvas. They MUST not be placed in the spawn zone or overlap an edge. Each successive object must be placed at minimum 4 characters away from all other placed chracters.
  - Add a CLI command to disable this behavior and not place any shapes

---

# 007a.md

Integrate more interactivity with the shape objects and fix ALL bugs related to them:

- All shapes should be fully filled with ASCII characters if possible.
- Ensure the shapes are a fully contigious polygonal collider and NO balls can pass through them, despite the ASCII appearence. The size of the collider should roughly match the ASCII area
  - For example, line shapes placed consecuitively adjacent should form a completely impassible barrier for the balls.
- Ensure the polygonal shape of the collider matches the visible shape itself. Currently, a Triangle shape has a rectangular collider that extends outside of it (see attached image)
- Allow dragging-and-dropping a selected shape using the mouse.
- While dragging a shape, the collider should still persist and cause collisions with the balls.
- If a shape is selected, the user should be able to move it using the arrow keys or WASD. In this instance, it supercedes the keyboard shortcuts assigned to those buttons.
- In the `[S]hapes` menu, allow the user to click the desired shape
- There is a bug where the inserted shape from the `[S]hapes` menu is not the correct shape. Double check the logic and ensure it is correct.
- Adjust the shape rotating behavior to be 90 degress each step instead of 45 degrees. You MUST ensure the shape design is completely unchanged during the rotation step.
- Allow deleting a selected shape by double-clicking it or by pressing the `Delete` key.
- Ensure the star is a polygon with 5 points and 10 sides, instead of a stick figure.
- Make the circle look more like a circle instead of a rectangle. You have permission to go beyond the normal character limits to accomplish this.

---

# 007b.md

Two more follow up bugs:

- The Star cannot be rotated
- The trigangle still has rectangular colliders (see attached image)

---

# 007d.md

Now it is time to allow the shapes to be in differnet colors.

- Add support for the shapes to be in terminal red, green, yellow, blue, magenta, cyan. The colors cycle in that same order.
- When a shape is inserted (by any means, such as the shape menu and loading the app), it is a random color.
- Add a keyboard shortcut `c` and `v` to cycle the the colors of the selected shape forwards/backwards.
- Add a right-click event to cycle the colors of the selected shape forwards.

Additionally, it is possible for balls to fall through lines at an angle. Ensure it is solid. See attached image.

---

# 008.md

Implement a `Color Mode`, where activating the geysers converts the balls the burst **directly** impacts into the geyser's corresponding color.

- Add an appropriate color property to the balls
- The colors can only be the same 6 colors as the geysers, plus the default white.
- The character colors of the Braille glyphs now display the most common ball color within its glyph
- `Color Mode` is a setting in the Options menu, default OFF.
- Add a CLI option to start in `Color Mode`.

Additionally, fix the bug where the asterisk indicators on pressing the geyser only appear one at a time. They should be able to appear on multiple geysers simultaneously.

---

# 008a.md

Make the following changes to Color Mode:

- Set the default for `Color Mode` to ON.
- When a ball spawns in `Color Mode`, each individual ball has a chance to spawn as a random color other than White. Create an Option in the options menu to specify this probability, with a default of 50%.
- Change the CLI option to disable color mode instead.

---

# 009.md

Add a Save and Load functionality, which saves the level configuration (including shapes and their positions and rotations and colors) and the options settings within a single portable file. The file is saved as a JSON file. You must include `serde` (version 1.0.228)

Ensure an `open` CLI argument exists where the user provides a JSON and it will automatically be added on load (this supercedes the default shapes on load and default settings on load)

Ensure the app does not crash if the opening JSON is malformed.

---

# 009a.md

Implement a simple interactive file explorer such that can find the specified level JSON to load, which may not be named `level.json`.

Add `Save` and `Load` buttons to the default UI that can be clicked.

---

# 010.md

Make ALL the following changes to the menu at the bottom of the screen:

- Add a `Colors` button, where each letter is colored in the order of terminal red, green, yellow, blue, magenta, cyan. Clicking this button or pressing `c` toggles Color Mode. Remove the Color Mode option from the Options menu.
- Remove the `c` shortcut from `[C]lear` and rename it to `Clear`.
- Remove the green backgrounds from the `Clear` and `Shapes` button.
- Replace the Friction % with Force % in the bottom menu. Do not display Friction % in the bottom menu. Reorder the Options in the Options Menu accordingly.

Additionally, make it such that when a ball is spawned, it is assigned a color, although that color is not displayed if Color Mode is OFF. That way, when the user toggles Color Mode mode, the existing balls will immediately turn into colors without having to spawn new balls.

---

# 011.md

Make ALL the following changes:

- Add a 500ms delay between each individual Up/Down/Left/Right keyboard press to prevent performance issues from spamming the same button. (they should still be able to press different buttons simultaneously)
- Reduce the shape selections to the following shapes, displayed as a 3x2 grid in the Shapes menu.
  - Circle
  - Triangle
  - Square
  - Star
  - Straight Line
  - Vertical Line (internally implemented as a Straight Line rotated 90 degrees)
- Implement the Straight Line as a 5x2 character line. Implement the vertical line as a 2x5 character line.
- When inserting a Shape from the Shape menu, ignore all restrictions on shape placement IF there are no valid places to place a shape.
- Ensure the app does not crash if the user loads an invalid shape via Load.

---

# 012.md

It is possible for balls to become stuck in between a completely sealed area delineated by multiple line shapes. (see attached image)

Verify the shape and collider logic to ensure no balls can enter a completely-sealed area.

---

# 013.md

Add a `[?]` bottom menu option that can be invoked via the `?` key which shows a scrollable help menu that contains ALL possible keyboard shortcuts for the terminal application. Ensure this menu can be scrolled by both keyboard and mouse.

---

# 014.md

The project is near completion, so do an optimized pass for the entire project which makes ALL the FOLLOWING changes:

- The crate name is now officially called `ballin`. Edit the crate name where appropriate in `Cargo.toml` and code.
- Ensure ALL tautological code comments and ALL self-demonstrating code comments are removed
- Set the default number of balls to `5000` and set the max number of balls to `15000`
- Rename the `60 FPS Cap` option to `Frame Cap`
- Remove ALL code and comments that indicate legacy/deprecated code: the project has not been released yet so there is no legacy/deprecated code paths to handle.

During your pass, you MUST ensure that ALL Rust code follows DRY principles as much as possible, and ensure all algorithms are big-O optimal. You have permission to refactor code to improve DRY and code optimization if necessary.
