diff --git a/PROMPT.md b/PROMPT.md index 9b057dc..1fd9acc 100644 --- a/PROMPT.md +++ b/PROMPT.md @@ -13,6 +13,12 @@ > - See CLAUDE.local.md "CRITICAL: Verify Both Git and GitHub CLI Credentials" section > - All changes need to be done via feature branch and merged via PR > - Work as `Contributor` implementing code changes and raising PR's. Do not review PR's unless explicitly prompted by the user - just monitor active PR and Issues for comment feedback. +> - **BLOCKING: Monitor ALL open PRs for feedback** +> - Check open PRs created by Contributor account for comments or "Changes requested" reviews +> - Implement requested fixes immediately using TDD approach +> - Self-verify fixes with `dotnet build --warnaserror && dotnet test` +> - Reply to review comments with: "Fixed. Changes verified - ready for re-review." +> - DO NOT proceed to new tasks while open PRs have unresolved feedback @@ -110,15 +116,17 @@ See **[docs/plans/rules-engine-design.md](docs/plans/rules-engine-design.md)** f 1. **FIRST: Verify credentials** - Run `./scripts/verify-credentials.sh contributor` before any work 2. Work as Contributor -3. Check for GitHub issue before any work -4. Create feature branch: `feature/-` -5. Write failing tests first -6. Implement to pass tests -7. Run `dotnet build --warnaserror && dotnet test` -8. **BEFORE COMMIT: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor` -9. Commit with: `: \n\nRefs #` -10. **BEFORE PR: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor` -11. Create PR and request review +3. **BLOCKING: Check for open PR feedback** - Run `gh pr list --author martincjarvis --state open` and check for review comments +4. **If PR has feedback**: Implement requested changes immediately (skip to new tasks only after all feedback resolved) +5. Check for GitHub issue before any work +6. Create feature branch: `feature/-` +7. Write failing tests first +8. Implement to pass tests +9. Run `dotnet build --warnaserror && dotnet test` +10. **BEFORE COMMIT: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor` +11. Commit with: `: + +Refs #`12. **BEFORE PR: Re-verify credentials** - Run`./scripts/verify-credentials.sh contributor` 13. Create PR and request review 14. **AFTER PR: Monitor for feedback** - Check PR regularly for review comments and respond immediately ### Commit Types @@ -139,10 +147,12 @@ Reference `docs/design/` for game mechanics specifications (gdd-core.md, gdd-cla 1. Read these files in order: - `CLAUDE.md` and `AGENTS.md` - Project rules and workflows - `docs/plans/rules-engine-design.md` - Architecture, design, and progress -2. Check Epic Status Overview for current progress and next tasks -3. For completed epics, examine Code Reference paths for implementation patterns -4. Reference `docs/design/gdd-*.md` for game mechanics details -5. Always reference the GitHub issue in commits -6. Use TDD - write failing tests before implementation -7. Run verification: `dotnet build --warnaserror && dotnet test` -8. Update progress tracking after completing tasks +2. **BLOCKING: Check for open PR feedback FIRST** - Run `gh pr list --author martincjarvis --state open` and prioritize addressing any review comments +3. Check Epic Status Overview for current progress and next tasks +4. For completed epics, examine Code Reference paths for implementation patterns +5. Reference `docs/design/gdd-*.md` for game mechanics details +6. Always reference the GitHub issue in commits +7. Use TDD - write failing tests before implementation +8. Run verification: `dotnet build --warnaserror && dotnet test` +9. Update progress tracking after completing tasks +10. After creating PR, monitor for feedback and respond immediately diff --git a/docs/plans/rules-engine-design.md b/docs/plans/rules-engine-design.md index 673a147..e8cba9a 100644 --- a/docs/plans/rules-engine-design.md +++ b/docs/plans/rules-engine-design.md @@ -24,7 +24,7 @@ Complete Epic 4 (Crafting and Class Progression) to enable full crafting mechani | 2 | Time and Simulation Loop | ✅ Complete | 6/6 | #4 | | 3 | NPC Decision Making | ✅ Complete | 6/6 | #5 | | 4 | Crafting and Class Progression | 🔄 In Progress | 7/8 | #6 | -| 5 | Economy and Inventory | ⏳ Planned | 0/6 | #7 | +| 5 | Economy and Inventory | 🔄 In Progress | 1/6 | #7 | | 6 | Contracts and Commitments | 🔄 Partial | 2/6 | #8 | | 7 | Settlement and Guild | ⏳ Planned | 0/6 | #9 | | 8 | Scenario Testing Framework | ⏳ Planned | 0/7 | #10 | @@ -32,10 +32,11 @@ Complete Epic 4 (Crafting and Class Progression) to enable full crafting mechani | 10 | Apprenticeship and Role Stacking | ⏳ Planned | 0/4 | #12 | | 11 | Full Progression Scenario | ⏳ Planned | 0/5 | #13 | -**Total Progress**: 26/58 tasks complete (45%) +**Total Progress**: 27/58 tasks complete (47%) ### Recent Completions +- ✅ **2026-01-19**: Epic 5.1 - Currency value object (#40, PR #137) - ✅ **2026-01-19**: Epic 4.7 - CraftingSystem (#38, PR #135) - ✅ **2026-01-19**: Epic 4.6 - CraftingOutcomeRule (#37, PR #134) - ✅ **2026-01-19**: Epic 4.5 - Define RecipeDefinition (#36, PR #127, commit 8148f26) @@ -48,7 +49,8 @@ Complete Epic 4 (Crafting and Class Progression) to enable full crafting mechani Priority order for remaining work: -1. **Epic 4.8** - #39: Implement Masterwork → Master rank trigger +1. **Epic 5.2** - #41: Implement InventoryComponent +2. **Epic 4.8** - #39: Implement Masterwork → Master rank trigger (PR #136 pending review) ## Key Design Decisions @@ -258,6 +260,50 @@ _For implementation patterns, examine referenced code paths._ --- +## Epic 5: Economy and Inventory + +**5.1 Implement Currency value object** ✅ _Issue #40, PR #137_ + +- ✅ FromSilver() and FromGold() conversion methods +- ✅ Silver and Gold properties for reading denominations +- ✅ FromMixed() for creating from multiple denominations +- ✅ ToBreakdown() for breaking into components +- ✅ Conversion rates: 1 silver = 10 copper, 1 gold = 100 copper +- **Verified**: 6 new tests pass, all 517 tests pass + +**5.2 Implement InventoryComponent** ⏳ _Issue #41_ + +- Track items by ItemId +- Add/remove operations +- Capacity limits +- **Verify**: Inventory operations work + +**5.3 Implement basic income and expense** ⏳ _Issue #42_ + +- Daily living costs +- Income from activities +- **Verify**: NPCs pay daily costs + +**5.4 Implement PriceCalculator rule** ⏳ _Issue #43_ + +- Base price calculation +- Quality modifiers +- **Verify**: Prices calculated correctly + +**5.5 Implement basic TradeAction** ⏳ _Issue #44_ + +- Buy/sell actions +- Currency exchange +- **Verify**: Trade works + +**5.6 Implement EconomySystem** ⏳ _Issue #45_ + +- Process income/expenses +- Update character currency +- **Verify**: Economy system processes transactions + +--- + ### Planned Epics | Epic | Title | Status | Issue | Key Components | diff --git a/src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs b/src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs index 68614f0..dd6a1d9 100644 --- a/src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs +++ b/src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs @@ -1,21 +1,62 @@ namespace FantasyRpgWorld.Core.Domain.ValueObjects; /// -/// Represents currency in copper pieces. -/// Simplified currency for Epic 6; detailed economy in Epic 5. +/// Represents currency with copper, silver, and gold denominations. +/// Conversion: 1 silver = 10 copper, 1 gold = 100 copper. /// public readonly record struct Currency(int Copper) { + private const int CopperPerSilver = 10; + private const int CopperPerGold = 100; + /// /// Creates currency from a copper amount. /// public static Currency FromCopper(int copper) => new(copper); + /// + /// Creates currency from a silver amount. + /// + public static Currency FromSilver(int silver) => new(silver * CopperPerSilver); + + /// + /// Creates currency from a gold amount. + /// + public static Currency FromGold(int gold) => new(gold * CopperPerGold); + + /// + /// Creates currency from mixed denominations. + /// + public static Currency FromMixed(int gold, int silver, int copper) => + new(gold * CopperPerGold + silver * CopperPerSilver + copper); + /// /// Returns zero currency. /// public static Currency Zero => new(0); + /// + /// Gets the silver value (whole silver pieces, not including copper remainder). + /// + public int Silver => Copper / CopperPerSilver; + + /// + /// Gets the gold value (whole gold pieces, not including copper/silver remainder). + /// + public int Gold => Copper / CopperPerGold; + + /// + /// Breaks down the currency into gold, silver, and copper components. + /// + public (int Gold, int Silver, int Copper) ToBreakdown() + { + int gold = Copper / CopperPerGold; + int remaining = Copper % CopperPerGold; + int silver = remaining / CopperPerSilver; + int copper = remaining % CopperPerSilver; + return (gold, silver, copper); + } + public static Currency operator +(Currency a, Currency b) => new(a.Copper + b.Copper); diff --git a/tests/FantasyRpgWorld.Core.Tests/Domain/ValueObjects/CurrencyTests.cs b/tests/FantasyRpgWorld.Core.Tests/Domain/ValueObjects/CurrencyTests.cs index 341c43c..84a49fe 100644 --- a/tests/FantasyRpgWorld.Core.Tests/Domain/ValueObjects/CurrencyTests.cs +++ b/tests/FantasyRpgWorld.Core.Tests/Domain/ValueObjects/CurrencyTests.cs @@ -92,4 +92,75 @@ public void Equality_WorksCorrectly() Assert.Equal(a, b); Assert.NotEqual(a, c); } + + [Fact] + public void FromSilver_ConvertsToCopperCorrectly() + { + // Act + var currency = Currency.FromSilver(5); + + // Assert + Assert.Equal(50, currency.Copper); + } + + [Fact] + public void FromGold_ConvertsToCopperCorrectly() + { + // Act + var currency = Currency.FromGold(3); + + // Assert + Assert.Equal(300, currency.Copper); + } + + [Fact] + public void Silver_Property_ReturnsCorrectValue() + { + // Arrange + var currency = Currency.FromCopper(75); + + // Act + int silver = currency.Silver; + + // Assert + Assert.Equal(7, silver); // 75 copper = 7 silver (with 5 copper remaining) + } + + [Fact] + public void Gold_Property_ReturnsCorrectValue() + { + // Arrange + var currency = Currency.FromCopper(350); + + // Act + int gold = currency.Gold; + + // Assert + Assert.Equal(3, gold); // 350 copper = 3 gold (with 50 copper remaining) + } + + [Fact] + public void FromMixed_CreatesCurrencyFromMultipleDenominations() + { + // Act + var currency = Currency.FromMixed(gold: 2, silver: 3, copper: 5); + + // Assert + Assert.Equal(235, currency.Copper); // 2*100 + 3*10 + 5 = 235 + } + + [Fact] + public void ToBreakdown_ReturnsCorrectDenominations() + { + // Arrange + var currency = Currency.FromCopper(347); + + // Act + var (gold, silver, copper) = currency.ToBreakdown(); + + // Assert + Assert.Equal(3, gold); // 300 copper + Assert.Equal(4, silver); // 40 copper + Assert.Equal(7, copper); // 7 copper remaining + } }