@pompidup/kingdomino-engine 3.2.0 → 3.4.0

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/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ type Tile = {
18
18
  type: Ground;
19
19
  /** Number of crowns (0-3), multiplier for scoring */
20
20
  crowns: Crown;
21
+ /** Whether this tile has a construction square for buildings (Queendomino) */
22
+ hasConstructionSquare?: boolean;
21
23
  };
22
24
  /**
23
25
  * Represents an empty/unplaced tile on the kingdom grid.
@@ -89,6 +91,83 @@ declare const GRIDSIZE = 9;
89
91
  */
90
92
  declare const MAX_KINGDOM_SIZE = 5;
91
93
 
94
+ /**
95
+ * Types of immediate bonuses a building can grant when constructed.
96
+ */
97
+ type ImmediateBonusType = "coins" | "tower" | "knight";
98
+ /**
99
+ * Immediate bonus granted when a building is constructed.
100
+ */
101
+ type ImmediateBonus = {
102
+ type: ImmediateBonusType;
103
+ amount: number;
104
+ };
105
+ /**
106
+ * Types of end-game scoring conditions for buildings.
107
+ */
108
+ type EndGameScoringType = "perTerrain" | "perBuilding" | "perTower" | "perCrown" | "flat";
109
+ /**
110
+ * End-game scoring rule for a building.
111
+ */
112
+ type EndGameScoring = {
113
+ type: EndGameScoringType;
114
+ /** Terrain type (only for perTerrain) */
115
+ terrain?: string;
116
+ /** Points per matching element */
117
+ points: number;
118
+ };
119
+ /**
120
+ * Represents a building tile that can be purchased and placed on a construction square.
121
+ */
122
+ type BuildingTile = {
123
+ /** Unique identifier */
124
+ id: number;
125
+ /** Display name */
126
+ name: string;
127
+ /** Cost in coins to purchase */
128
+ cost: number;
129
+ /** Immediate bonus when constructed (optional) */
130
+ immediateBonus?: ImmediateBonus;
131
+ /** Permanent crowns added to the territory */
132
+ crowns: number;
133
+ /** Towers granted by this building */
134
+ towers: number;
135
+ /** End-game scoring condition (optional) */
136
+ endGameScoring?: EndGameScoring;
137
+ };
138
+ /**
139
+ * A slot on the Builders Board that may hold a building tile.
140
+ */
141
+ type BuildingSlot = BuildingTile | null;
142
+ /**
143
+ * The Builders Board holding available building tiles for purchase.
144
+ */
145
+ type BuildersBoard = {
146
+ /** Visible building tiles available for purchase (4 slots) */
147
+ slots: BuildingSlot[];
148
+ /** Remaining building tiles in the draw pile */
149
+ drawPile: BuildingTile[];
150
+ };
151
+ /**
152
+ * A building that has been placed on a player's kingdom.
153
+ */
154
+ type PlacedBuilding = {
155
+ /** The building tile that was placed */
156
+ building: BuildingTile;
157
+ /** Position on the kingdom grid */
158
+ position: Position;
159
+ };
160
+
161
+ type Result<T> = Ok<T> | Err;
162
+ interface Ok<T> {
163
+ readonly tag: "Ok";
164
+ readonly value: T;
165
+ }
166
+ interface Err {
167
+ readonly tag: "Err";
168
+ readonly error: string;
169
+ }
170
+
92
171
  /**
93
172
  * Represents a lord (player token) used for turn order and domino selection.
94
173
  * In games with 2 players, each player has 2 lords.
@@ -122,6 +201,15 @@ type GameMode = {
122
201
 
123
202
  type ObjectValues<T> = T[keyof T];
124
203
 
204
+ /**
205
+ * Represents a knight placed on a player's kingdom (Queendomino).
206
+ */
207
+ type Knight = {
208
+ /** ID of the player who owns this knight */
209
+ playerId: string;
210
+ /** Position on the kingdom grid where the knight is placed */
211
+ position: Position;
212
+ };
125
213
  /**
126
214
  * Represents a player in the game.
127
215
  */
@@ -136,6 +224,14 @@ type Player = {
136
224
  bot?: {
137
225
  strategyName: string;
138
226
  };
227
+ /** Number of coins the player has (Queendomino) */
228
+ coins?: number;
229
+ /** Number of towers the player has (Queendomino) */
230
+ towers?: number;
231
+ /** Knights placed on the kingdom (Queendomino) */
232
+ knights?: Knight[];
233
+ /** Buildings placed on the kingdom (Queendomino) */
234
+ buildings?: PlacedBuilding[];
139
235
  };
140
236
  /**
141
237
  * Payload for creating a new player.
@@ -158,10 +254,33 @@ declare const playerActions: {
158
254
  readonly pickDomino: "pickDomino";
159
255
  /** Pass/discard when no valid placement exists */
160
256
  readonly pass: "pass";
257
+ /** Place a knight on the just-placed domino (Queendomino, optional) */
258
+ readonly placeKnight: "placeKnight";
259
+ /** Construct a building on a construction square (Queendomino, optional) */
260
+ readonly constructBuilding: "constructBuilding";
261
+ /** Use the Dragon to burn a building tile (Queendomino, optional) */
262
+ readonly useDragon: "useDragon";
263
+ /** Skip the current optional action (Queendomino) */
264
+ readonly skipOptionalAction: "skipOptionalAction";
161
265
  };
162
266
  /** Union type of all player actions */
163
267
  type PlayerActions = ObjectValues<typeof playerActions>;
164
268
 
269
+ /**
270
+ * Complete Queendomino-specific game state.
271
+ * This is stored as an optional field on Game and only present in QueenDomino mode.
272
+ */
273
+ type QueenDominoState = {
274
+ /** The Builders Board with available building tiles */
275
+ buildersBoard: BuildersBoard;
276
+ /** ID of the player currently hosting the Queen, or null */
277
+ queenHolderId: string | null;
278
+ /** Whether the Dragon is available for use this round */
279
+ dragonAvailable: boolean;
280
+ /** Whether the Dragon has been used this round (resets each round) */
281
+ dragonUsedThisRound: boolean;
282
+ };
283
+
165
284
  /**
166
285
  * Basic rules that vary based on player count.
167
286
  */
@@ -209,16 +328,6 @@ type SelectedRules = {
209
328
  extra: ExtraRule[];
210
329
  };
211
330
 
212
- type Result<T> = Ok<T> | Err;
213
- interface Ok<T> {
214
- readonly tag: "Ok";
215
- readonly value: T;
216
- }
217
- interface Err {
218
- readonly tag: "Err";
219
- readonly error: string;
220
- }
221
-
222
331
  /**
223
332
  * Represents the complete state of a Kingdomino game.
224
333
  * This is the main aggregate containing all game data.
@@ -244,6 +353,8 @@ type Game = {
244
353
  mode: GameMode;
245
354
  /** Optional seed for deterministic shuffle (replays, sharing) */
246
355
  seed?: string;
356
+ /** Queendomino-specific state (only present in QueenDomino mode) */
357
+ queendomino?: QueenDominoState;
247
358
  };
248
359
  /**
249
360
  * Available game steps representing phases of game setup and completion.
@@ -464,6 +575,30 @@ type GetDynastyResultCommand = {
464
575
  games: GameWithResults[];
465
576
  };
466
577
 
578
+ type PlaceKnightCommand = {
579
+ game: GameWithNextAction;
580
+ lordId: string;
581
+ position: Position;
582
+ };
583
+
584
+ type ConstructBuildingCommand = {
585
+ game: GameWithNextAction;
586
+ lordId: string;
587
+ buildingId: number;
588
+ position: Position;
589
+ };
590
+
591
+ type UseDragonCommand = {
592
+ game: GameWithNextAction;
593
+ lordId: string;
594
+ buildingId: number;
595
+ };
596
+
597
+ type SkipOptionalActionCommand = {
598
+ game: GameWithNextAction;
599
+ lordId: string;
600
+ };
601
+
467
602
  /**
468
603
  * Represents a valid placement position with rotation.
469
604
  */
@@ -613,6 +748,30 @@ type GameEngine = {
613
748
  * @returns Ranked dynasty results per player
614
749
  */
615
750
  getDynastyResults: (command: GetDynastyResultCommand) => DynastyResult[];
751
+ /**
752
+ * Places a knight on the lord's kingdom at the specified position (Queendomino).
753
+ * @param command - Contains game state, lord ID, and position
754
+ * @returns Updated game state with next action
755
+ */
756
+ placeKnight: (command: PlaceKnightCommand) => GameState;
757
+ /**
758
+ * Constructs a building on the lord's kingdom (Queendomino).
759
+ * @param command - Contains game state, lord ID, building ID, and position
760
+ * @returns Updated game state with next action
761
+ */
762
+ constructBuilding: (command: ConstructBuildingCommand) => GameState;
763
+ /**
764
+ * Uses the dragon to destroy a building on the builders board (Queendomino).
765
+ * @param command - Contains game state, lord ID, and building ID
766
+ * @returns Updated game state with next action
767
+ */
768
+ useDragon: (command: UseDragonCommand) => GameState;
769
+ /**
770
+ * Skips the current optional action (Queendomino).
771
+ * @param command - Contains game state and lord ID
772
+ * @returns Updated game state with next action
773
+ */
774
+ skipOptionalAction: (command: SkipOptionalActionCommand) => GameState;
616
775
  };
617
776
 
618
777
  /**
@@ -641,6 +800,15 @@ declare const ErrorCode: {
641
800
  readonly DOMINO_ALREADY_PICKED: "DOMINO_ALREADY_PICKED";
642
801
  readonly UNDO_UNAVAILABLE: "UNDO_UNAVAILABLE";
643
802
  readonly REDO_UNAVAILABLE: "REDO_UNAVAILABLE";
803
+ readonly CANNOT_PLACE_KNIGHT: "CANNOT_PLACE_KNIGHT";
804
+ readonly MAX_KNIGHTS_REACHED: "MAX_KNIGHTS_REACHED";
805
+ readonly KNIGHT_TERRITORY_OCCUPIED: "KNIGHT_TERRITORY_OCCUPIED";
806
+ readonly CANNOT_AFFORD_BUILDING: "CANNOT_AFFORD_BUILDING";
807
+ readonly NO_CONSTRUCTION_SQUARE: "NO_CONSTRUCTION_SQUARE";
808
+ readonly DRAGON_UNAVAILABLE: "DRAGON_UNAVAILABLE";
809
+ readonly QUEEN_HOLDER_CANNOT_USE_DRAGON: "QUEEN_HOLDER_CANNOT_USE_DRAGON";
810
+ readonly BUILDING_NOT_FOUND: "BUILDING_NOT_FOUND";
811
+ readonly INVALID_OPTIONAL_ACTION: "INVALID_OPTIONAL_ACTION";
644
812
  };
645
813
  type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode];
646
814
  /**
@@ -752,6 +920,15 @@ declare const TranslationKey: {
752
920
  readonly ACTION_PICK_DOMINO: "action.pickDomino";
753
921
  readonly ACTION_PLACE_DOMINO: "action.placeDomino";
754
922
  readonly ACTION_PASS: "action.pass";
923
+ readonly ERROR_CANNOT_PLACE_KNIGHT: "error.cannotPlaceKnight";
924
+ readonly ERROR_MAX_KNIGHTS_REACHED: "error.maxKnightsReached";
925
+ readonly ERROR_KNIGHT_TERRITORY_OCCUPIED: "error.knightTerritoryOccupied";
926
+ readonly ERROR_CANNOT_AFFORD_BUILDING: "error.cannotAffordBuilding";
927
+ readonly ERROR_NO_CONSTRUCTION_SQUARE: "error.noConstructionSquare";
928
+ readonly ERROR_DRAGON_UNAVAILABLE: "error.dragonUnavailable";
929
+ readonly ERROR_QUEEN_HOLDER_CANNOT_USE_DRAGON: "error.queenHolderCannotUseDragon";
930
+ readonly ERROR_BUILDING_NOT_FOUND: "error.buildingNotFound";
931
+ readonly ERROR_INVALID_OPTIONAL_ACTION: "error.invalidOptionalAction";
755
932
  };
756
933
  type TranslationKeyType = (typeof TranslationKey)[keyof typeof TranslationKey];
757
934
  /**
@@ -988,6 +1165,10 @@ type EngineConfig = {
988
1165
  */
989
1166
  declare const validateGameState: (game: Game) => ValidationIssue[];
990
1167
 
1168
+ type BuildingsRepository = {
1169
+ getAll: () => BuildingTile[];
1170
+ };
1171
+
991
1172
  type DominoesRepository = {
992
1173
  getForMode: (mode: GameMode) => Domino[] | [];
993
1174
  };
@@ -1290,6 +1471,14 @@ declare const getHistorySize: (history: GameHistory) => {
1290
1471
  future: number;
1291
1472
  };
1292
1473
 
1474
+ type PlaceKnightUseCase = (game: GameWithNextAction, lordId: string, position: Position) => GameStateResult;
1475
+
1476
+ type ConstructBuildingUseCase = (game: GameWithNextAction, lordId: string, buildingId: number, position: Position) => GameStateResult;
1477
+
1478
+ type UseDragonUseCase = (game: GameWithNextAction, lordId: string, buildingId: number) => GameStateResult;
1479
+
1480
+ type SkipOptionalActionUseCase = (game: GameWithNextAction, lordId: string) => GameStateResult;
1481
+
1293
1482
  /**
1294
1483
  * Serializes a game state to a JSON string.
1295
1484
  * The serialized string includes version information for future compatibility.
@@ -1360,4 +1549,4 @@ declare const restoreFromSavePoint: (savePoint: GameSavePoint) => Result<GameSta
1360
1549
  */
1361
1550
  declare const createGameEngine: (config: Partial<EngineConfig>) => GameEngine;
1362
1551
 
1363
- export { type ActionEntry, ActionExecutionError, type ActionPayloadMap, type ActionType, type AddExtraRulesCommand, type AddPlayersCommand, type BasicRules, type BotStrategy, type CalculateScoreCommand, type CanPlaceDominoCommand, type ChooseDominoCommand, type CreateGameCommand, type Crown, type DebugLogEntry, type DebugLogLevel, type DebugLogger, type DebugOptions, type DeserializeGameCommand, type DiscardDominoCommand, type DomainError, DomainException, type Domino, type DominoesRepository, type DynastyResult, type EmptyGround, type EmptyTile, type EngineConfig, ErrorCode, type ErrorCodeType, type ExtraRule, type FinalResult, GRIDSIZE, GROUND, type Game, type GameActionLog, type GameEngine, type GameEventCallbacks, type GameHistory, type GameMode, type GameSavePoint, type GameState, type GameStateResult, type GameStateSummary, type GameSteps, type GameWithNextAction, type GameWithNextStep, type GameWithResults, type GetDynastyResultCommand, type GetExtraRulesCommand, type GetModesCommand, type GetResultCommand, type GetValidPlacementsCommand, type Ground, InvalidStepError, type Kingdom, type Logger, type Lord, MAX_KINGDOM_SIZE, type ModeRepository, type NextAction, type NextStep, NotFoundError, type ObjectValues, type PickContext, type PlaceContext, type PlaceDominoCommand, type Player, type PlayerActions, type PlayerInput, type PlayerPayload, type Players, type PlayersPayload, type Position, RedoError, type RevealsDomino, type Rotation, type RuleRepository, type Rules, type Score, type ScoreResult, type SelectedRules, type SerializeGameCommand, type ShuffleMethod, type StartGameCommand, StepExecutionError, type StrategyName, type Tile, TranslationKey, type TranslationKeyType, type Translator, UndoError, type UuidMethod, type ValidPlacement, ValidationError, type ValidationIssue, type ValidationSeverity, advancedStrategy, appendAction, canRedo, canUndo, clearHistory, createActionLog, createDomainError, createGameEngine, createGameHistory, createSavePoint, createTranslator, defaultTranslations, defaultTranslator, deserializeGame, errorCodeToTranslationKey, expertStrategy, gameSteps, getActions, getActionsByTurn, getActionsByType, getHistorySize, getStrategy, getStrategyNames, greedyStrategy, isBotTurn, isGameWithNextAction, isGameWithNextStep, playBotTurn, playBotTurns, playerActions, pushState, randomStrategy, redo, replayActions, restoreFromSavePoint, serializeGame, summarizeGameState, translateErrorCode, undo, validateGameState, wrapWithActionLog, wrapWithDebug, wrapWithEvents };
1552
+ export { type ActionEntry, ActionExecutionError, type ActionPayloadMap, type ActionType, type AddExtraRulesCommand, type AddPlayersCommand, type BasicRules, type BotStrategy, type BuildersBoard, type BuildingSlot, type BuildingTile, type BuildingsRepository, type CalculateScoreCommand, type CanPlaceDominoCommand, type ChooseDominoCommand, type ConstructBuildingCommand, type ConstructBuildingUseCase, type CreateGameCommand, type Crown, type DebugLogEntry, type DebugLogLevel, type DebugLogger, type DebugOptions, type DeserializeGameCommand, type DiscardDominoCommand, type DomainError, DomainException, type Domino, type DominoesRepository, type DynastyResult, type EmptyGround, type EmptyTile, type EndGameScoring, type EndGameScoringType, type EngineConfig, ErrorCode, type ErrorCodeType, type ExtraRule, type FinalResult, GRIDSIZE, GROUND, type Game, type GameActionLog, type GameEngine, type GameEventCallbacks, type GameHistory, type GameMode, type GameSavePoint, type GameState, type GameStateResult, type GameStateSummary, type GameSteps, type GameWithNextAction, type GameWithNextStep, type GameWithResults, type GetDynastyResultCommand, type GetExtraRulesCommand, type GetModesCommand, type GetResultCommand, type GetValidPlacementsCommand, type Ground, type ImmediateBonus, type ImmediateBonusType, InvalidStepError, type Kingdom, type Knight, type Logger, type Lord, MAX_KINGDOM_SIZE, type ModeRepository, type NextAction, type NextStep, NotFoundError, type ObjectValues, type PickContext, type PlaceContext, type PlaceDominoCommand, type PlaceKnightCommand, type PlaceKnightUseCase, type PlacedBuilding, type Player, type PlayerActions, type PlayerInput, type PlayerPayload, type Players, type PlayersPayload, type Position, type QueenDominoState, RedoError, type RevealsDomino, type Rotation, type RuleRepository, type Rules, type Score, type ScoreResult, type SelectedRules, type SerializeGameCommand, type ShuffleMethod, type SkipOptionalActionCommand, type SkipOptionalActionUseCase, type StartGameCommand, StepExecutionError, type StrategyName, type Tile, TranslationKey, type TranslationKeyType, type Translator, UndoError, type UseDragonCommand, type UseDragonUseCase, type UuidMethod, type ValidPlacement, ValidationError, type ValidationIssue, type ValidationSeverity, advancedStrategy, appendAction, canRedo, canUndo, clearHistory, createActionLog, createDomainError, createGameEngine, createGameHistory, createSavePoint, createTranslator, defaultTranslations, defaultTranslator, deserializeGame, errorCodeToTranslationKey, expertStrategy, gameSteps, getActions, getActionsByTurn, getActionsByType, getHistorySize, getStrategy, getStrategyNames, greedyStrategy, isBotTurn, isGameWithNextAction, isGameWithNextStep, playBotTurn, playBotTurns, playerActions, pushState, randomStrategy, redo, replayActions, restoreFromSavePoint, serializeGame, summarizeGameState, translateErrorCode, undo, validateGameState, wrapWithActionLog, wrapWithDebug, wrapWithEvents };