Merge origin/dev into feature/cities-and-knights
Brings in open trade offers and counter-offers. Cities & Knights gets the same flow for goods: OfferGoods may be open to the table, CounterGoods answers an offer, and AcceptCounter / DismissCounters are shared with the base game. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_016eTor2tpxKb4dXbd8RqnvZ
This commit is contained in:
@@ -197,8 +197,10 @@ checked after every move and when a turn arrives.
|
||||
- **A knight that cannot find a refuge is lost**, as the almanac says of an intrigue.
|
||||
- **A claim on a metropolis with no city to carry it waits** and is made when a city is
|
||||
built.
|
||||
- **Domestic trade** may include commodities; the one-offer-at-a-time rules of the base
|
||||
game apply.
|
||||
- **Domestic trade** works as in the base game — an offer to one seat or to the whole
|
||||
table, asked in seat order, each seat accepting, declining or countering — and may
|
||||
include commodities (`OfferGoods`, `CounterGoods`; accepting and dismissing counters
|
||||
reuse the base game's `AcceptCounter` and `DismissCounters`).
|
||||
- **No Seafarers, no 5–6 player extension**, no scenario or variant of any kind.
|
||||
|
||||
## The computer opponent
|
||||
|
||||
+23
-12
@@ -135,17 +135,32 @@ is the same code path.
|
||||
|
||||
### Domestic
|
||||
|
||||
An offer names **one** addressee and two card multisets: what the offerer gives,
|
||||
what they want. There are no counter-offers and no open auctions in v1.
|
||||
An offer is addressed to **one** seat or, with `to = null`, to **everyone**, and
|
||||
names two card multisets: what the offerer gives, what they want.
|
||||
|
||||
Seats are asked **one at a time**, in seat order after the offerer (seats holding
|
||||
no cards are skipped; an addressed offer asks only its addressee). The seat being
|
||||
asked may:
|
||||
|
||||
- **accept** — the trade happens at once and the offer closes (first accept wins);
|
||||
- **decline** — the offer moves on to the next seat;
|
||||
- **counter** (`CounterTrade`) — propose different terms: what they would give and
|
||||
what they want from the offerer. A counter must differ from the offer as made
|
||||
(that is an accept), and both sides must hold the cards. The offer moves on.
|
||||
|
||||
When every seat has answered and nobody accepted: with no counters the offer
|
||||
simply lapses; with counters the phase becomes `TRADE_COUNTERS` and the offerer
|
||||
either **takes one** (`AcceptCounter(seat)`, still checked for affordability) or
|
||||
**turns them all down** (`DismissCounters`).
|
||||
|
||||
An offer is legal only when the offerer's turn is in PLAYING, the addressee is
|
||||
another seat, both legs are non-empty, the two legs are not the same multiset
|
||||
(`countOf(give) != countOf(get)` — like-for-like is not a trade), and the
|
||||
offerer actually holds the cards being offered.
|
||||
|
||||
The addressee may **accept** only if they hold what was asked and the offerer
|
||||
still holds what was promised; otherwise only **decline** is offered. A decline
|
||||
clears the table and leaves every card where it was.
|
||||
A seat may **accept** only if it holds what was asked and the offerer still holds
|
||||
what was promised; otherwise only decline (or counter) is offered. A refusal
|
||||
leaves every card where it was.
|
||||
|
||||
Offers are free-form intents rather than enumerated moves (the space of card
|
||||
multisets is combinatorial), so they are validated structurally by
|
||||
@@ -305,7 +320,7 @@ timing rules; Longest Road and Largest Army worth five; victory at ten.
|
||||
- **Year of Plenty two-of-a-kind needs the bank to hold both cards**, not one.
|
||||
- **The robber must move.** Some printings allow staying put; this engine always
|
||||
requires a different hex.
|
||||
- **Offers are one-to-one, no auctions or counter-offers** in v1.
|
||||
- **Offers may be open to the whole table** and can be countered; the first accept wins (see Trading).
|
||||
|
||||
## Known gaps
|
||||
|
||||
@@ -315,12 +330,8 @@ timing rules; Longest Road and Largest Army worth five; victory at ten.
|
||||
the base game so far; it is a one-constant change in `publicVictoryPoints`.
|
||||
- **A bank short of a resource pays nobody that roll**, even when only one player is owed
|
||||
it. The published ruling lets a lone claimant take what is left; Cities & Knights does.
|
||||
|
||||
- **No domestic auction or counter-offer.** An offer is addressed to a single
|
||||
seat. Open trading to the whole table, and counter-offers, are the obvious next
|
||||
step and are not implemented.
|
||||
- **No player-to-player trade over the wire beyond accept/decline.** The engine
|
||||
supports it; whether the UI surfaces it is the screen task's concern.
|
||||
- **No timer or cancel on offers.** An offer waits for each asked seat in turn; the offerer cannot withdraw it mid-round, and a player who never answers stalls the table.
|
||||
- **The AI never counters.** It accepts, declines, and picks among counters it is sent, but does not propose them.
|
||||
- **No trading away a development card.** Not part of the base game.
|
||||
- **The screen is built, not yet verified on two devices.** The Katan screen and
|
||||
setup options exist (see [UI-catan.md](UI-catan.md)); the catalogue entry is a
|
||||
|
||||
+3
-2
@@ -89,7 +89,8 @@ screen's UI state. The legal-move list stays the gate.
|
||||
| Seven | **Discard** dialog (forced); then taps a hex to move the robber; a victim dialog appears only if more than one player can be robbed |
|
||||
| Main turn | arms **Road / Settlement / City** and taps a highlighted spot; **Buy card**; **Play card**; **Trade**; **End turn** |
|
||||
| Road Building | taps highlighted edges, or **Done with roads** |
|
||||
| Offered a trade | **Accept / Decline** dialog (forced) |
|
||||
| Offered a trade | **Accept / Decline / Counter…** dialog (forced); *Counter…* opens a picker pre-filled with the mirror of the offer |
|
||||
| Counter-offers received | **Counter-offers** dialog: *Accept* beside the one to take, or *No deal* |
|
||||
| Game over | result dialog |
|
||||
|
||||
Trade offers are free-form (two card multisets), so they are validated with
|
||||
@@ -165,6 +166,6 @@ Not done yet, in rough priority order:
|
||||
it does not say which hexes paid out, so that needs either a diff of two states
|
||||
or an engine addition.
|
||||
3. Art: terrain textures, resource and harbour icons, a real robber pawn.
|
||||
4. Open trade to the whole table and counter-offers (an engine limitation too).
|
||||
4. A timer or cancel button on offers (the engine has neither).
|
||||
5. A board that shows the *last* move (a faint highlight of what just changed).
|
||||
6. Landscape polish on large tablets; the right-hand panel scrolls but is plain.
|
||||
|
||||
Reference in New Issue
Block a user