Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions PROMPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

</EXTREMELY-IMPORTANT>

Expand Down Expand Up @@ -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/<issue>-<description>`
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: `<type>: <description>\n\nRefs #<issue>`
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/<issue>-<description>`
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: `<type>: <description>

Refs #<issue>`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

Expand All @@ -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
52 changes: 49 additions & 3 deletions docs/plans/rules-engine-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ 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 |
| 9 | Persistence | ⏳ Planned | 0/4 | #11 |
| 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)
Expand All @@ -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

Expand Down Expand Up @@ -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 |
Expand Down
45 changes: 43 additions & 2 deletions src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,62 @@
namespace FantasyRpgWorld.Core.Domain.ValueObjects;

/// <summary>
/// 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.
/// </summary>
public readonly record struct Currency(int Copper)
{
private const int CopperPerSilver = 10;
private const int CopperPerGold = 100;

/// <summary>
/// Creates currency from a copper amount.
/// </summary>
public static Currency FromCopper(int copper) => new(copper);

/// <summary>
/// Creates currency from a silver amount.
/// </summary>
public static Currency FromSilver(int silver) => new(silver * CopperPerSilver);

/// <summary>
/// Creates currency from a gold amount.
/// </summary>
public static Currency FromGold(int gold) => new(gold * CopperPerGold);

/// <summary>
/// Creates currency from mixed denominations.
/// </summary>
public static Currency FromMixed(int gold, int silver, int copper) =>
new(gold * CopperPerGold + silver * CopperPerSilver + copper);

/// <summary>
/// Returns zero currency.
/// </summary>
public static Currency Zero => new(0);

/// <summary>
/// Gets the silver value (whole silver pieces, not including copper remainder).
/// </summary>
public int Silver => Copper / CopperPerSilver;

/// <summary>
/// Gets the gold value (whole gold pieces, not including copper/silver remainder).
/// </summary>
public int Gold => Copper / CopperPerGold;

/// <summary>
/// Breaks down the currency into gold, silver, and copper components.
/// </summary>
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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}