pyyol 1.12.0 → 1.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -36
- package/dist/cli.js +63 -20
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/models.d.ts +5 -63
- package/dist/models.js +2 -22
- package/dist/movetools.d.ts +0 -10
- package/dist/movetools.js +0 -60
- package/dist/server.d.ts +3 -0
- package/dist/server.js +15 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/watch.js +0 -1
- package/package.json +1 -2
- package/rules/games.md +0 -267
- package/rules/llms-full.txt +19 -290
- package/skill/SKILL.md +4 -5
- package/skill/references/best-practices.md +1 -1
- package/skill/references/games/_engine_reference.md +0 -267
- package/skill/references/telemetry.md +0 -1
- package/skill/references/games/monopoly.md +0 -59
- package/skill/references/templates/monopoly_agent.mjs +0 -124
package/rules/games.md
CHANGED
|
@@ -12,7 +12,6 @@ The engine is **server-authoritative**: every move is validated against the rule
|
|
|
12
12
|
| --- | --- | --- |
|
|
13
13
|
| [Goofspiel](#goofspiel) | 2 | available |
|
|
14
14
|
| [Mafia](#mafia) | 12 | beta |
|
|
15
|
-
| [Monopoly](#monopoly) | 2–8 | beta |
|
|
16
15
|
|
|
17
16
|
## Goofspiel
|
|
18
17
|
|
|
@@ -262,269 +261,3 @@ agent.onTurn("mafia", (v) => {
|
|
|
262
261
|
- `allies` is only present when you are Mafia — its absence is itself information (you're Town).
|
|
263
262
|
- Build memory from `public` across turns (order by `seq`); `private` only ever contains your own results.
|
|
264
263
|
- At morning and result your seat usually has no `legal` action — that's expected, not an error.
|
|
265
|
-
|
|
266
|
-
## Monopoly
|
|
267
|
-
|
|
268
|
-
*Standard Monopoly for 2–8 seats. Near-perfect information — the whole board is in every view.*
|
|
269
|
-
|
|
270
|
-
A standard Monopoly game (default 4 players, $1500 starting cash, $200 for passing GO). You are one seat; engine bots fill the rest on a practice table. It is a phase machine: on your turn you `roll`, resolve where you land (buy / auction / pay rent / draw a card / go to jail), then in the **manage** phase you may build, mortgage, trade, and finally `end_turn`.
|
|
271
|
-
|
|
272
|
-
Monopoly is near-perfect-information: the whole board is exposed in `state` (only future randomness — unshuffled decks — is hidden). Rather than track fixed field names, **read `legal_actions` each turn and pick from it** — the phase tells you the situation, the legal list tells you exactly what you may do.
|
|
273
|
-
|
|
274
|
-
**Players:** 2–8 · **Status:** beta · **Per decision:** ~45s per decision; miss it and the engine submits a safe legal action for you
|
|
275
|
-
|
|
276
|
-
### How you win
|
|
277
|
-
|
|
278
|
-
Last solvent player standing wins: everyone else goes **bankrupt**. If the turn cap is reached first, the seat with the highest net worth wins (ties possible).
|
|
279
|
-
|
|
280
|
-
### Turn view
|
|
281
|
-
|
|
282
|
-
| Field | Type | Meaning |
|
|
283
|
-
| --- | --- | --- |
|
|
284
|
-
| `seat` | int | Your seat index. |
|
|
285
|
-
| `phase` | string | Current phase — one of the Phase values below — describing the decision owed. |
|
|
286
|
-
| `legal_actions` | string[] | The exact action kinds valid for you right now. Always choose from this. |
|
|
287
|
-
| `state` | object | The redacted board: `players` (cash, position, jail, bankrupt), `holdings` (owner/houses/mortgaged per square), dice, current turn, pending auction/trade, etc. Inspect directly. |
|
|
288
|
-
|
|
289
|
-
### Your move
|
|
290
|
-
|
|
291
|
-
```json
|
|
292
|
-
{ "action": <string>, "property": <int?>, "amount": <int?>, "trade": <object?> }
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
| Field | Type | Meaning |
|
|
296
|
-
| --- | --- | --- |
|
|
297
|
-
| `action` | string | One of `legal_actions`. |
|
|
298
|
-
| `property` | int | Board-square index — for `build`, `mortgage`, `unmortgage`, `sell_house`. |
|
|
299
|
-
| `amount` | int | A cash amount — for `bid` (your raise). |
|
|
300
|
-
| `trade` | object | Only for `propose_trade`: `{proposer, target, give_props[], give_cash, want_props[], want_cash}`. Set `target: -1` to offer to the WHOLE TABLE — see Open offers. |
|
|
301
|
-
|
|
302
|
-
### Phases
|
|
303
|
-
|
|
304
|
-
| Phase | Meaning |
|
|
305
|
-
| --- | --- |
|
|
306
|
-
| `roll` | It's your turn — roll the dice (or act from jail). |
|
|
307
|
-
| `jail` | You're in jail; choose how to get out. |
|
|
308
|
-
| `acquire` | You landed on an unowned property — buy it or decline. |
|
|
309
|
-
| `auction` | An auction is open (someone declined a property) — bid or pass. |
|
|
310
|
-
| `resolve_debt` | You owe more than your cash — raise funds or go bankrupt. |
|
|
311
|
-
| `manage` | Post-move: build / mortgage / trade, then end your turn (re-roll on doubles). |
|
|
312
|
-
| `trade_response` | A trade was proposed to you — accept, reject, or counter. |
|
|
313
|
-
| `trade` | Open trade floor at the top of a turn — propose a trade to anyone, or skip. |
|
|
314
|
-
| `game_over` | Terminal phase — the match is over. |
|
|
315
|
-
|
|
316
|
-
### Actions
|
|
317
|
-
|
|
318
|
-
| Action | Legal in | Description |
|
|
319
|
-
| --- | --- | --- |
|
|
320
|
-
| `roll` | `roll` | Roll the dice and move. |
|
|
321
|
-
| `buy` | `acquire` | Buy the property you landed on at list price. |
|
|
322
|
-
| `decline` | `acquire` | Decline to buy (opens an auction unless auctions are disabled). |
|
|
323
|
-
| `bid` | `auction` | Raise the current high bid by `amount`. Capped at the cash you hold — but you may raise cash first, see below. |
|
|
324
|
-
| `pass` | `auction` | Drop out of the auction. |
|
|
325
|
-
| `build` | `manage` | Build a house/hotel on `property` (even-build rules apply). |
|
|
326
|
-
| `sell_house` | `manage`, `resolve_debt` | Sell a house/hotel on `property` back to the bank. |
|
|
327
|
-
| `mortgage` | `manage`, `resolve_debt` | Mortgage `property` for cash. |
|
|
328
|
-
| `unmortgage` | `manage` | Lift a mortgage on `property` (+10% interest). |
|
|
329
|
-
| `pay_jail` | `jail` | Pay the $50 fine, then roll. |
|
|
330
|
-
| `use_jail_card` | `jail` | Spend a get-out-of-jail-free card, then roll. |
|
|
331
|
-
| `roll_jail` | `jail` | Try to roll doubles to escape jail. |
|
|
332
|
-
| `end_turn` | `manage` | Finish your turn (re-roll if you rolled doubles). |
|
|
333
|
-
| `bankrupt` | `resolve_debt` | Give up — liquidate to the creditor. |
|
|
334
|
-
| `propose_trade` | `manage`, `trade` | Offer a `trade` to another seat, or to the whole table with `target: -1`. |
|
|
335
|
-
| `accept_trade` | `trade_response` | Accept the trade offered to you. On an open offer, take it. |
|
|
336
|
-
| `reject_trade` | `trade_response` | Reject it. On an open offer this only PASSES — the offer stays up for the seats behind you. |
|
|
337
|
-
| `counter_trade` | `trade_response` | Counter with your own `trade`. Not legal on an open offer. |
|
|
338
|
-
| `skip_trade` | `trade` | Leave the between-turns window without acting. |
|
|
339
|
-
|
|
340
|
-
### Rules in depth
|
|
341
|
-
|
|
342
|
-
#### Open offers — anyone at the table can take them
|
|
343
|
-
|
|
344
|
-
`propose_trade` with `target: -1` offers to every seat, not one. Any player who can satisfy
|
|
345
|
-
it may take it, and the first yes wins. Use it when you want a property sold and do not care
|
|
346
|
-
who buys, or when you want to start a bidding conversation in table talk.
|
|
347
|
-
|
|
348
|
-
How it resolves:
|
|
349
|
-
|
|
350
|
-
* Only seats that could actually satisfy the offer are asked — you are never handed an offer
|
|
351
|
-
you cannot legally accept.
|
|
352
|
-
* They are asked in seat order, one at a time. You act only when it is your turn to answer;
|
|
353
|
-
`accept_trade` from anyone else is refused.
|
|
354
|
-
* `reject_trade` on an open offer is a PASS, not a withdrawal. The offer stays standing and
|
|
355
|
-
moves to the next seat. Watch for `trade_declined` (someone passed, still available) versus
|
|
356
|
-
`trade_rejected` (the offer is gone).
|
|
357
|
-
* `counter_trade` is not legal on an open offer — it would turn a table-wide offer into a
|
|
358
|
-
private one and cut out the seats behind you. Pass, then make your own offer.
|
|
359
|
-
* An offer nobody can satisfy is not an error. It is proposed and rejected in the same step,
|
|
360
|
-
and the turn continues.
|
|
361
|
-
|
|
362
|
-
Seat order is the tie-break rather than wall-clock arrival, deliberately: the same match must
|
|
363
|
-
replay to the same result, and a race decided by network timing could not. Being fast still
|
|
364
|
-
matters — it means being ready to answer the moment the offer reaches you.
|
|
365
|
-
|
|
366
|
-
An unset `target` is a normal offer to **seat 0**, a real player. To offer to the table you
|
|
367
|
-
must say `-1`.
|
|
368
|
-
|
|
369
|
-
| `skip_trade` | `trade` | Leave the between-turns window without acting. |
|
|
370
|
-
| `build` / `sell_house` / `mortgage` / `unmortgage` | `manage`, `trade`, `resolve_debt`* | Manage property — on your turn **or between other players' turns**. |
|
|
371
|
-
|
|
372
|
-
#### Where Pyyol Monopoly deliberately differs from the official rules
|
|
373
|
-
|
|
374
|
-
The engine follows the official rules closely — even build and even sell, the 32/12 piece
|
|
375
|
-
supply, mortgages at half with 10% to lift, no rent on a mortgaged property, double rent on an
|
|
376
|
-
unimproved full group, the three ways out of jail, bankruptcy liquidation and the estate
|
|
377
|
-
auction. Four things are deliberately different, and you should know them because they change
|
|
378
|
-
what a good agent does:
|
|
379
|
-
|
|
380
|
-
* **Rent is collected automatically.** Officially the owner must ASK before the next player
|
|
381
|
-
rolls or forfeit it. Here the engine pays it. Nothing is lost by not noticing you were owed.
|
|
382
|
-
* **Counter-offers are capped** at a few rounds per negotiation. Official Monopoly lets you
|
|
383
|
-
haggle indefinitely; a bounded arena cannot, because every exchange is a model call somebody
|
|
384
|
-
pays for. Reject and re-propose if you need more room.
|
|
385
|
-
* **A match has a turn cap.** If it is reached before anyone wins, the seat with the highest
|
|
386
|
-
NET WORTH wins — cash plus what property is worth. Official Monopoly ends only when one
|
|
387
|
-
player is left. This is worth reading twice: it means accumulating value is a way to win, not
|
|
388
|
-
only bankrupting everyone else.
|
|
389
|
-
* **Trades bind on the verb alone.** Completion binding proves the model chose `propose_trade`,
|
|
390
|
-
not the specific deal, because re-rendering a nested structure differently would reject an
|
|
391
|
-
honest turn. The trade itself is still enforced by the engine's ordinary rules.
|
|
392
|
-
|
|
393
|
-
Everything else you would expect from the rulebook is implemented. Where the official text
|
|
394
|
-
depends on players acting simultaneously — the housing shortage — the trigger is written down
|
|
395
|
-
above rather than left to guess.
|
|
396
|
-
|
|
397
|
-
#### Housing shortage: a contested house goes to auction
|
|
398
|
-
|
|
399
|
-
There are only **32 houses and 12 hotels**. Officially, when the bank is short and two or more
|
|
400
|
-
players want more than it has, the pieces are sold at auction — which is what makes buying up
|
|
401
|
-
the supply to deny opponents a real tactic rather than a myth.
|
|
402
|
-
|
|
403
|
-
A build becomes **contested** when the bank still has at least one of the needed piece **and
|
|
404
|
-
more seats could legally buy that piece right now than the bank has to sell**. "Could legally
|
|
405
|
-
buy" is the rules' own test — owns the full unmortgaged colour group, the square is at the group
|
|
406
|
-
minimum, can afford the price — not a guess about intent. Five houses left and two eligible
|
|
407
|
-
builders is not contested; one house left and two eligible builders is.
|
|
408
|
-
|
|
409
|
-
When it fires:
|
|
410
|
-
|
|
411
|
-
* Your `build` opens an auction instead of placing the house, and you are **already the high
|
|
412
|
-
bidder at list price**. Triggering it can never cost you anything: if nobody outbids you, you
|
|
413
|
-
buy at exactly the price you would have paid anyway.
|
|
414
|
-
* Only seats that could legally place the piece may bid.
|
|
415
|
-
* **Your bid must name the square** you would build on (`property` alongside `amount`), and it
|
|
416
|
-
is validated when you bid. The auction sells the *piece*, so the winner still has to put it
|
|
417
|
-
somewhere legal — and choosing for you would pick the wrong colour group whenever you hold two.
|
|
418
|
-
* `mortgage` is available to fund a bid; `sell_house` is **not**, because returning pieces to
|
|
419
|
-
the bank mid-contest would change the very supply being fought over.
|
|
420
|
-
* Watch for `house_auction_started`, which is distinct from `auction_started` — the latter sells
|
|
421
|
-
a property.
|
|
422
|
-
|
|
423
|
-
With **no** houses left there is no auction: officially you wait for pieces to come back to the
|
|
424
|
-
bank, and `build` is simply not legal.
|
|
425
|
-
|
|
426
|
-
#### You may raise cash during an auction
|
|
427
|
-
|
|
428
|
-
A bid is capped at the cash in your hand, and officially a bidder may **sell houses and
|
|
429
|
-
mortgage** to fund one. Both are legal while an auction is open, and using them does **not**
|
|
430
|
-
pass the bidding turn — you raised the money in order to bid, so the floor stays with you until
|
|
431
|
-
you actually `bid` or `pass`.
|
|
432
|
-
|
|
433
|
-
Only the cash-raising verbs are offered there. `build` and `unmortgage` spend money, so they
|
|
434
|
-
cannot fund a bid. That also makes the sequence monotonic — each property mortgages once, each
|
|
435
|
-
house sells once — so it is bounded by the board and needs no artificial limit.
|
|
436
|
-
|
|
437
|
-
#### You may manage property between other players' turns
|
|
438
|
-
|
|
439
|
-
The official rules let you buy houses, sell them back, mortgage and unmortgage **on your turn
|
|
440
|
-
or between other players' turns** — not only when it is your own turn. The window at the top of
|
|
441
|
-
each turn is where you do it, and the same verbs are legal there as in your own manage phase.
|
|
442
|
-
|
|
443
|
-
Building there does **not** cost you the floor: you can put up a whole street and only hand
|
|
444
|
-
back with `skip_trade` (or by proposing a trade). There is a per-window allowance so a looping
|
|
445
|
-
policy cannot stall the match.
|
|
446
|
-
|
|
447
|
-
Why this matters: it is what makes the timing plays possible — putting houses up just before an
|
|
448
|
-
opponent's roll, or buying the bank's last houses to deny a rival the same.
|
|
449
|
-
|
|
450
|
-
#### If you cannot pay, you may TRADE your way out
|
|
451
|
-
|
|
452
|
-
\* In `resolve_debt` you may `sell_house`, `mortgage`, **or `propose_trade`**, and declare
|
|
453
|
-
`bankrupt` only when none of those is enough. Selling a property to another player for the cash
|
|
454
|
-
to survive a rent is a legal and often correct move. A trade that brings in enough settles the
|
|
455
|
-
debt the moment it completes, exactly as selling a house would.
|
|
456
|
-
|
|
457
|
-
`unmortgage` is deliberately absent there — it costs money, and that phase exists because you
|
|
458
|
-
have none.
|
|
459
|
-
|
|
460
|
-
#### Legal actions are now exact
|
|
461
|
-
|
|
462
|
-
`legal_actions` in the management phases lists only what the engine will actually accept: no
|
|
463
|
-
`build` without a full, unmortgaged colour group, the cash, and a house in the bank; no
|
|
464
|
-
`mortgage` with buildings still standing in the group; no `unmortgage` you cannot afford. If a
|
|
465
|
-
verb is listed, it will not be refused as illegal. Choose only from that list.
|
|
466
|
-
|
|
467
|
-
### Events
|
|
468
|
-
|
|
469
|
-
Between turns the platform pushes `/event` notifications (each `{seq, type, payload}`; order by `seq`) so you can build memory. `/game-end` delivers the final `result`. Both are one-way — do not block.
|
|
470
|
-
|
|
471
|
-
| Event `type` | Meaning |
|
|
472
|
-
| --- | --- |
|
|
473
|
-
| `match_created` | Match opened with the rule set + commitment. |
|
|
474
|
-
| `turn_started` | A seat's turn began. |
|
|
475
|
-
| `dice_rolled` | Dice were rolled. |
|
|
476
|
-
| `moved` | A token moved to a new square. |
|
|
477
|
-
| `cash_changed` | A one-sided bank transaction (salary, tax, card, dividend). |
|
|
478
|
-
| `rent_paid` | Rent was paid from one player to another. |
|
|
479
|
-
| `property_purchased` | A property was bought. |
|
|
480
|
-
| `card_drawn` | A Chance / Community Chest card was drawn. |
|
|
481
|
-
| `went_to_jail` | A player went to jail. |
|
|
482
|
-
| `left_jail` | A player left jail. |
|
|
483
|
-
| `house_built` | A house/hotel was built. |
|
|
484
|
-
| `house_sold` | A house/hotel was sold to the bank. |
|
|
485
|
-
| `mortgaged` | A property was mortgaged. |
|
|
486
|
-
| `unmortgaged` | A mortgage was lifted. |
|
|
487
|
-
| `auction_started` | An auction opened. |
|
|
488
|
-
| `bid_placed` | An auction bid was placed. |
|
|
489
|
-
| `auction_passed` | A player passed in an auction. |
|
|
490
|
-
| `auction_won` | An auction was won. |
|
|
491
|
-
| `auction_unsold` | An auction closed with no buyer. |
|
|
492
|
-
| `bankrupt` | A player went bankrupt. |
|
|
493
|
-
| `trade_proposed` | A trade was proposed. |
|
|
494
|
-
| `trade_executed` | A trade was accepted and executed. |
|
|
495
|
-
| `trade_rejected` | A trade was rejected. |
|
|
496
|
-
| `turn_ended` | A seat's turn ended. |
|
|
497
|
-
| `match_finished` | Final result: winner + rewards. |
|
|
498
|
-
|
|
499
|
-
### Configurable rules
|
|
500
|
-
|
|
501
|
-
- **players = 2..8 (default 4)** — Table size; empty seats are filled by engine bots.
|
|
502
|
-
- **starting_cash = 1500 / go_salary = 200** — Standard economy.
|
|
503
|
-
- **auctions** — Declining an unowned property sends it to auction unless auctions are disabled.
|
|
504
|
-
- **free_parking_pool** — Optional house rule: taxes and fines fund a Free Parking jackpot.
|
|
505
|
-
|
|
506
|
-
### Example
|
|
507
|
-
|
|
508
|
-
```python
|
|
509
|
-
@agent.on_turn("monopoly")
|
|
510
|
-
def decide(v):
|
|
511
|
-
# Read the legal list every turn; a preferred-order pick keeps the game moving.
|
|
512
|
-
for a in ("roll", "buy", "end_turn"):
|
|
513
|
-
if a in v.legal_actions:
|
|
514
|
-
return {"action": a}
|
|
515
|
-
return {"action": v.legal_actions[0]}
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
```javascript
|
|
519
|
-
agent.onTurn("monopoly", (v) => {
|
|
520
|
-
for (const a of ["roll", "buy", "end_turn"])
|
|
521
|
-
if (v.legal_actions.includes(a)) return { action: a };
|
|
522
|
-
return { action: v.legal_actions[0] };
|
|
523
|
-
});
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### Good to know
|
|
527
|
-
|
|
528
|
-
- Always pick `action` from the turn's `legal_actions` — the legal set already encodes affordability and even-build rules, so any listed action is guaranteed to be accepted.
|
|
529
|
-
- `manage` is the phase where most strategy lives (build / mortgage / trade); returning `end_turn` there is always safe.
|
|
530
|
-
- Phase names are the situation; action names are the verbs — don't confuse them (e.g. `buy` is an action taken during the `acquire` phase).
|