Initial commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* The intent vocabulary — every legal player choice, from docs/architecture/protocol.md §1.
|
||||
*
|
||||
* An intent is a PROPOSAL. It may be rejected. Contrast with an event (events.ts), which is a fact.
|
||||
*/
|
||||
|
||||
import type { CarType, Direction, OfficeTier } from './content.ts';
|
||||
import type { CardId, GridCoord, PlayerIndex, TrayId } from './state.ts';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Local Operations Phase (§6) — a three-way exclusive choice
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type LocalOpsOption = 'switch' | 'draw' | 'freightAgent';
|
||||
|
||||
export type Intent =
|
||||
| { type: 'localOps.choose'; option: LocalOpsOption }
|
||||
// -- switch (§6.1, Appendix A)
|
||||
| { type: 'switch.move'; trayId: TrayId; to: GridCoord; reverse: boolean }
|
||||
| { type: 'switch.dropCars'; trayId: TrayId; count: number }
|
||||
| { type: 'switch.end' }
|
||||
// -- draw (§6.2)
|
||||
| { type: 'draw.fromHomeOffice' }
|
||||
| { type: 'draw.fromDepartment'; slot: number }
|
||||
/** `variant` indexes `variantsFor(geometry)` — Gap 11: orientation is chosen on placement. */
|
||||
| { type: 'card.play'; cardId: CardId; placement?: GridCoord; variant?: number }
|
||||
| { type: 'card.discard'; cardId: CardId; toSlot: number }
|
||||
| { type: 'draw.end' }
|
||||
// -- freight agent (§6.3)
|
||||
| { type: 'freightAgent.stockOutbound'; at: GridCoord; carType: CarType }
|
||||
| { type: 'freightAgent.clearInbound'; at: GridCoord; index: number }
|
||||
| { type: 'freightAgent.unjam'; at: GridCoord; from: 'outbound' | 'inbound' | 'menAtWork'; index: number }
|
||||
// -- New Train Phase (§7)
|
||||
| { type: 'newTrain.placeCar'; trayId: TrayId; carType: CarType; loaded: boolean }
|
||||
| { type: 'newTrain.passCar'; trayId: TrayId }
|
||||
// -- Mainline Phase (§8.1) — the Superintendent's clearance ruling
|
||||
| { type: 'mainline.clearance'; allow: boolean }
|
||||
| { type: 'redFlag.play' }
|
||||
// -- Load/Unload Phase (§9)
|
||||
| { type: 'porter.board'; at: GridCoord }
|
||||
| { type: 'porter.detrain'; at: GridCoord }
|
||||
/** §9.3 — the first Laborer step: Green Loading Slot -> MEN. */
|
||||
| { type: 'laborer.startLoad'; at: GridCoord }
|
||||
| { type: 'laborer.advanceLoad'; at: GridCoord; box: number }
|
||||
| { type: 'laborer.beginUnload'; at: GridCoord; carIndex: number }
|
||||
| { type: 'loadUnload.end' };
|
||||
|
||||
export type IntentType = Intent['type'];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rejections — protocol.md §2
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type RejectionCode =
|
||||
| 'NOT_YOUR_TURN'
|
||||
| 'WRONG_PHASE'
|
||||
| 'OPTION_ALREADY_CHOSEN'
|
||||
| 'OPTION_NOT_CHOSEN'
|
||||
| 'NO_MOVES_REMAINING'
|
||||
| 'ILLEGAL_MOVE'
|
||||
| 'NO_SUCH_TRAY'
|
||||
| 'NO_SUCH_CARD'
|
||||
| 'NO_SUCH_FACILITY'
|
||||
| 'CANNOT_DROP_HERE'
|
||||
| 'CONSIST_EMPTY'
|
||||
| 'CONSIST_FULL'
|
||||
| 'HAND_LIMIT'
|
||||
| 'CARD_NOT_IN_HAND'
|
||||
| 'NO_PLACEMENT'
|
||||
| 'NOT_CONNECTED'
|
||||
| 'DECK_EMPTY'
|
||||
| 'SLOT_EMPTY'
|
||||
| 'RESOURCE_SPENT'
|
||||
| 'BOX_FULL'
|
||||
| 'BOX_EMPTY'
|
||||
| 'NO_SUITABLE_CAR'
|
||||
| 'SUITABLE_CAR_EXISTS'
|
||||
| 'WRONG_CAR_TYPE'
|
||||
| 'NOT_SUPERINTENDENT'
|
||||
| 'NO_PENDING_DECISION'
|
||||
| 'NOT_UPGRADEABLE'
|
||||
| 'FACILITY_LOCKED'
|
||||
| 'NO_TRAIN_AT_OFFICE';
|
||||
|
||||
export type Rejection = { code: RejectionCode; message: string };
|
||||
|
||||
export function reject(code: RejectionCode, message: string): Rejection {
|
||||
return { code, message };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Re-exports used by handlers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type { CardId, Direction, GridCoord, OfficeTier, PlayerIndex, TrayId };
|
||||
Reference in New Issue
Block a user