Implement reputation decay system — configurable rate toward neutral per game day, stops at ±5 #217

Open
opened 2026-03-16 01:38:00 +00:00 by freemo · 0 comments
Owner

Metadata

Field Value
Epic #202 — Reputation Mechanics
Legendary #199 — Reputation & Social Standing
Type Feature
Priority High
Points 5
MoSCoW Must Have
Branch feature/m4-reputation-decay-system
Commit Message Implement reputation decay system — configurable rate toward neutral per game day, stops at ±5 (#217)

Background and Context

In a dynamic MUD world, reputation should not be permanent from a single action. The decay system ensures that reputation scores gradually drift toward neutral over time, encouraging players to maintain their standing through ongoing engagement rather than resting on past achievements or suffering permanently from past mistakes.

The decay system runs on each game-day tick. Every reputation score that is outside the ±5 "near-neutral" range decays by a configurable amount (default: 1 point per game day) toward 0. Once a score enters the ±5 range, decay stops — this prevents scores from oscillating around zero and provides a stable neutral zone.

The decay rate is configurable in config.yaml to allow server operators to tune the system. A higher decay rate creates a more dynamic reputation environment, while a lower rate rewards long-term commitment.

Expected Behavior

  1. On each game-day tick event, the decay system processes all players' reputation scores.
  2. For each score > +5, subtract the decay rate (default: 1), minimum result is +5.
  3. For each score < -5, add the decay rate (default: 1), maximum result is -5.
  4. Scores in the range -5..+5 are not modified.
  5. The decay rate is read from config.yaml under reputation.decay_rate.
  6. Decay triggers :reputation_changed events but tagged as source: :decay.
  7. Decay does NOT trigger propagation (to avoid cascading decay).
  8. The decay system can be disabled by setting reputation.decay_enabled: false in config.yaml.

Acceptance Criteria

  • Decay system subscribes to game-day tick events.
  • Positive scores > +5 decay toward +5 at the configured rate.
  • Negative scores < -5 decay toward -5 at the configured rate.
  • Scores in the ±5 range are not affected by decay.
  • Decay rate is configurable via config.yaml at reputation.decay_rate.
  • Decay can be disabled via reputation.decay_enabled: false.
  • Decay fires :reputation_changed events tagged with source: :decay.
  • Decay does not trigger reputation propagation.
  • Default decay rate is 1 point per game day.

Subtasks

  • Create lib/aethyr/core/reputation/reputation_decay.rb with the decay engine.
  • Implement game-day tick subscription.
  • Implement decay logic for positive scores (toward +5).
  • Implement decay logic for negative scores (toward -5).
  • Implement neutral zone (±5) exemption.
  • Add reputation.decay_rate and reputation.decay_enabled config options.
  • Tag decay events with source: :decay.
  • Ensure decay events do not trigger propagation.
  • Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable.
  • Tests (Cucumber): Add tests/unit/reputation_decay.feature covering positive decay, negative decay, neutral zone exemption, configurable rate, disable toggle, event tagging, and no-propagation guard.
  • Tests (Cucumber Integration): Add integration feature in tests/integration/ for decay system running across multiple game-day ticks with various reputation scores.
  • Tests (Profiling): Run bundle exec rake unit_profile and verify no performance regressions.
  • Quality: Verify coverage >=97% via bundle exec rake unit. If coverage is <97% then review the current unit test coverage report at build/tests/unit/coverage/ and use it to write new Cucumber based unit tests to improve code coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun bundle exec rake unit to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%.
  • Quality: Run bundle exec rake (default task: unit tests with coverage) and bundle exec rake integration, fix any errors if needed ensuring both pass across entire code base, do not ignore any failure even if it seems unrelated to this commit, fix it.

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
## Metadata | Field | Value | |-------|-------| | **Epic** | #202 — Reputation Mechanics | | **Legendary** | #199 — Reputation & Social Standing | | **Type** | Feature | | **Priority** | High | | **Points** | 5 | | **MoSCoW** | Must Have | | **Branch** | `feature/m4-reputation-decay-system` | | **Commit Message** | `Implement reputation decay system — configurable rate toward neutral per game day, stops at ±5 (#217)` | ## Background and Context In a dynamic MUD world, reputation should not be permanent from a single action. The decay system ensures that reputation scores gradually drift toward neutral over time, encouraging players to maintain their standing through ongoing engagement rather than resting on past achievements or suffering permanently from past mistakes. The decay system runs on each game-day tick. Every reputation score that is outside the ±5 "near-neutral" range decays by a configurable amount (default: 1 point per game day) toward 0. Once a score enters the ±5 range, decay stops — this prevents scores from oscillating around zero and provides a stable neutral zone. The decay rate is configurable in `config.yaml` to allow server operators to tune the system. A higher decay rate creates a more dynamic reputation environment, while a lower rate rewards long-term commitment. ## Expected Behavior 1. On each game-day tick event, the decay system processes all players' reputation scores. 2. For each score > +5, subtract the decay rate (default: 1), minimum result is +5. 3. For each score < -5, add the decay rate (default: 1), maximum result is -5. 4. Scores in the range -5..+5 are not modified. 5. The decay rate is read from `config.yaml` under `reputation.decay_rate`. 6. Decay triggers `:reputation_changed` events but tagged as `source: :decay`. 7. Decay does NOT trigger propagation (to avoid cascading decay). 8. The decay system can be disabled by setting `reputation.decay_enabled: false` in `config.yaml`. ## Acceptance Criteria - [ ] Decay system subscribes to game-day tick events. - [ ] Positive scores > +5 decay toward +5 at the configured rate. - [ ] Negative scores < -5 decay toward -5 at the configured rate. - [ ] Scores in the ±5 range are not affected by decay. - [ ] Decay rate is configurable via `config.yaml` at `reputation.decay_rate`. - [ ] Decay can be disabled via `reputation.decay_enabled: false`. - [ ] Decay fires `:reputation_changed` events tagged with `source: :decay`. - [ ] Decay does not trigger reputation propagation. - [ ] Default decay rate is 1 point per game day. ## Subtasks - [ ] Create `lib/aethyr/core/reputation/reputation_decay.rb` with the decay engine. - [ ] Implement game-day tick subscription. - [ ] Implement decay logic for positive scores (toward +5). - [ ] Implement decay logic for negative scores (toward -5). - [ ] Implement neutral zone (±5) exemption. - [ ] Add `reputation.decay_rate` and `reputation.decay_enabled` config options. - [ ] Tag decay events with `source: :decay`. - [ ] Ensure decay events do not trigger propagation. - [ ] Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable. - [ ] Tests (Cucumber): Add `tests/unit/reputation_decay.feature` covering positive decay, negative decay, neutral zone exemption, configurable rate, disable toggle, event tagging, and no-propagation guard. - [ ] Tests (Cucumber Integration): Add integration feature in `tests/integration/` for decay system running across multiple game-day ticks with various reputation scores. - [ ] Tests (Profiling): Run `bundle exec rake unit_profile` and verify no performance regressions. - [ ] Quality: Verify coverage >=97% via `bundle exec rake unit`. If coverage is <97% then review the current unit test coverage report at `build/tests/unit/coverage/` and use it to write new Cucumber based unit tests to improve code coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun `bundle exec rake unit` to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%. - [ ] Quality: Run `bundle exec rake` (default task: unit tests with coverage) and `bundle exec rake integration`, fix any errors if needed ensuring both pass across **entire** code base, do not ignore any failure even if it seems unrelated to this commit, fix it. ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
freemo added this to the v1.3.0 milestone 2026-03-16 01:38:00 +00:00
freemo self-assigned this 2026-03-16 01:38:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference: aethyr/Aethyr#217
No description provided.