feat(packages): ludic.session - a party's roster (slot 0 a port, the others as reported), the roles and who owns the world, the shared night, votes and a world-changing act asking the party; joins, leaves, roles, votes and the night as facts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
12172d7b75
commit
79ed7a335b
12 changed files with 707 additions and 0 deletions
60
packages/ludic.session/README.md
Normal file
60
packages/ludic.session/README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# ludic.session
|
||||
|
||||
Who is in a party and who runs the world, whatever carries its messages: the roster, the roles,
|
||||
the shared night, votes, and "a world-changing act asks the party". It sends nothing - what the
|
||||
other machines have to hear comes out as facts, and the game puts them on its wire. Uses
|
||||
[`ludic.base`](../ludic.base/README.md) and nothing else.
|
||||
|
||||
```ludic
|
||||
import "ludic.session"
|
||||
```
|
||||
|
||||
## The roster
|
||||
|
||||
Slot 0 is this machine's player, read live through the `SessionLocal` port; slots 1 to
|
||||
`PLY_MAX - 1` are remote players, holding what their own machines reported (where they stand,
|
||||
their heading and speed, how much their rest speeds the clock, whether they have turned in, their
|
||||
name). World code asks the roster, never "the player": `for p in 0 .. PLY_MAX { if ply_on(p) ...
|
||||
ply_x(p) ... }`, or `ply_near(x, z)` and `ply_near_i()`.
|
||||
|
||||
```ludic
|
||||
port SessionLocal {
|
||||
x, y, z: fn() -> float # required
|
||||
yaw, speed: fn() -> float (0), rest: fn() -> float (1), name: fn() -> string ("")
|
||||
}
|
||||
```
|
||||
|
||||
## Roles
|
||||
|
||||
`SES_SOLO` owns the world and has no company; `SES_HOST` owns it and has company; `SES_GUEST`
|
||||
owns only its own player. `ses_owns_world()`, `ses_live()`, `ses_night_passes()` (alone, lying
|
||||
down ends the night). The transport says what this machine became (`ses_set_role`).
|
||||
|
||||
## API
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `ply_init()`, `ply_join(pid) -> slot`, `ply_leave(p)`, `ply_leave_all()` | the roster (-1: full, or pid 0) |
|
||||
| `ply_report(p, x, y, z, yaw, speed)`, `ply_report_rest(p, rest, sleeping)`, `ply_report_name(p, name)` | what a remote machine said |
|
||||
| `ply_on`, `ply_is_local`, `ply_slot_of(pid)`, `ply_count`, `ply_pid`, `ply_name`, `ply_x/y/z/yaw/speed/rest(p)`, `ply_sleeping(p)` | who and where |
|
||||
| `ply_near(x, z)`, `ply_near_d2`, `ply_near_i()`, `ply_dist(p, x, z)` | the nearest player |
|
||||
| `ses_role()`, `ses_set_role(r)`, `ses_owns_world()`, `ses_live()`, `ses_hosting()`, `ses_guest()`, `ses_night_passes()` | roles |
|
||||
| `ses_set_party(max, open)`, `ses_set_open(b)`, `ses_max()`, `ses_open()`, `ses_room_for_one()` | the party a host allows |
|
||||
| `ses_sleep(on) -> bool`, `ses_sleeping()`, `ses_sleep_ready(p, on)`, `ses_night_check()`, `ses_night_passed()`, `ses_sleep_waiting()` | the shared night: false alone; the host counts |
|
||||
| `ses_may(kind, param, text) -> SES_MAY_GO / _ASKED / _BUSY / _HOSTS` | a world-changing act |
|
||||
| `ses_vote_open`, `ses_vote_cast`, `ses_vote_heard(id, yes)`, `ses_vote_told(id, kind, text)`, `ses_vote_ended(id, passed)`, `ses_vote_tick(dt)` | a majority of the players, the host included, within thirty seconds |
|
||||
| `ses_vote_live/id/kind/text/left/yes/no/mine/passed()` | the vote as it stands |
|
||||
| `ses_reset()` | everyone else gone, alone, nothing asked, nobody asleep |
|
||||
| `ses_facts() -> Queue<SessionFact>` | `SES_JOINED` / `SES_LEFT` (slot, pid), `SES_ROLE` (role), `SES_VOTE_OPENED`, `SES_VOTE_CAST` (a guest's answer to send), `SES_VOTE_RESOLVED` (yes: passed), `SES_NIGHT` (the host: everyone is in), `SES_SLEEP` (this player turned in or got up) |
|
||||
|
||||
It is not a `System`: a party exists before any world does (a join from the title), so the game
|
||||
calls `ses_vote_tick` and drains `ses_facts()` in its own frame.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
ludic test packages/ludic.session
|
||||
```
|
||||
|
||||
A fake local player: the roster filling and emptying, the nearest player, roles, the party's size,
|
||||
the night, votes passing, failing and timing out, and a guest's side of each.
|
||||
Loading…
Add table
Add a link
Reference in a new issue