feat(ludic.effects): timed modifiers as a mechanic package; ludic.base's q_new is queue_new
ludic.effects: effects_add / effects_add_after / effects_clear / effects_run, effects_sum / effects_has / effects_at / effects_live, an EffectEnded queue (ran out, pushed out by the bonus cap, crowded out of a full ring) and a System with its own save section. Nine test blocks in tests/effects_test.ludic. ludic.base: q_new collided with render3d's quaternion q_new the moment a game imported both, so the queue constructor is queue_new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
70d05bd504
commit
d0ad364ad4
12 changed files with 419 additions and 9 deletions
44
packages/ludic.effects/README.md
Normal file
44
packages/ludic.effects/README.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# ludic.effects
|
||||
|
||||
Timed modifiers that run down in game time: a meal that holds the cold off for fifty minutes, a
|
||||
drink that is twenty minutes of legs and then a crash, a soaking that chills you for ten. The
|
||||
rules of the game ask one question - "what should I add for this kind right now?" - and the
|
||||
package answers it. Uses [`ludic.base`](../ludic.base/README.md) and nothing else.
|
||||
|
||||
```ludic
|
||||
import "ludic.effects"
|
||||
```
|
||||
|
||||
A kind is the game's own number (`EF_WARMTH_RATE`, `EF_CARRY`, ...); the package never knows what
|
||||
one means. A magnitude is in that kind's units. Time is game minutes.
|
||||
|
||||
## Rules
|
||||
|
||||
- **The same kind from the same label replaces itself.** A second soda extends the fizz, it does
|
||||
not double it.
|
||||
- **Bonuses are capped** (`effects_config(max, bonus_max)`, 8 and 3 by default): a bonus that would
|
||||
be one too many pushes out the bonus nearest its end. A menu is a choice.
|
||||
- **A full ring** drops whatever is nearest its end.
|
||||
- **A delayed effect** (`effects_add_after`) counts for nothing until it begins, then runs its time.
|
||||
|
||||
## API
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `effects_add(kind, mag, minutes, bonus, label)` | start one now |
|
||||
| `effects_add_after(after, kind, mag, minutes, bonus, label)` | start one `after` game minutes from now |
|
||||
| `effects_clear()` | stop everything, silently (a new trip, a night's sleep) |
|
||||
| `effects_run(minutes)` | run them down (the system's tick does this from `Tick.hours`) |
|
||||
| `effects_sum(kind)`, `effects_has(kind)`, `effects_bonus_count()` | what the rules ask |
|
||||
| `effects_count()`, `effects_at(i) -> Effect`, `effects_live() -> []int` | what a read-out draws (`effects_at` is a copy) |
|
||||
| `effects_config(max, bonus_max)`, `effects_capacity()`, `effects_bonus_capacity()` | the ring's size |
|
||||
| `effects_ended() -> Queue<EffectEnded>` | the facts: `{ kind, label, why, bonus }`, `why` one of `EFFECT_RAN_OUT`, `EFFECT_PUSHED_OUT`, `EFFECT_CROWDED_OUT` |
|
||||
| `effects_system() -> System` | `"effects"`, `PH_SIMULATE`: reset, tick, and its save section (`effects_save`, `effects_load`) |
|
||||
|
||||
No ports: the package asks the world nothing.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
ludic build packages/ludic.effects/tests/effects_test.ludic --headless -o /tmp/effects_test && /tmp/effects_test
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue