# Saboteur Functional Domain Modeling Type ###### tags: `saboteur` ### Vec2 ```ts type Vec2 = [number, number] ``` ### Placement ```ts type Placement = { position: Vec2 card: PathCard } ``` ### Removal ```ts type Removal = { position: Vec2; card: PathCard; } ``` ### Direction ```ts enum Direction { TOP = (1 / 2) * Math.PI, BOTTOM = (3 / 2) * Math.PI, LEFT = 1 * Math.PI, RIGHT = 0 * Math.PI, } ``` ### Card ```ts enum PathCard { START = "start", GOAL_GOLD = "goal gold", GOAL_COAL_BOTTOM_RIGHT = "goal coal bottom right", GOAL_COAL_BOTTOM_LEFT = "goal coal bottom left", CONNECTED_TOP_BOTTOM = "connected top bottom", CONNECTED_TOP_BOTTOM_RIGHT = "connected top bottom right", CONNECTED_CROSS = "connected cross", CONNECTED_TOP_LEFT_RIGHT = "connected top left right", CONNECTED_LEFT_RIGHT = "connected left right", CONNECTED_BOTTOM_RIGHT = "connected bottom right", CONNECTED_BOTTOM_LEFT = "connected bottom left", DEADEND_BOTTOM = "deadend bottom", DEADEND_TOP_BOTTOM = "deadend top bottom", DEADEND_TOP_BOTTOM_RIGHT = "deadend top bottom right", DEADEND_CROSS = "deadend cross", DEADEND_TOP_LEFT_RIGHT = "deadend top left right", DEADEND_LEFT_RIGHT = "deadend left right", DEADEND_BOTTOM_RIGHT = "deadend bottom right", DEADEND_BOTTOM_LEFT = "deadend bottom left", DEADEND_LEFT = "deadend left", } ``` ```ts enum ActionCard { MAP = "map", ROCKFALL = "rockfall", BROKEN_TOOL_CART = "broken tool cart", BROKEN_TOOL_LAMP = "broken tool lamp", BROKEN_TOOL_PICKAXE = "broken tool pickaxe", FIX_TOOL_CART = "fix tool cart", FIX_TOOL_LAMP = "fix tool lamp", FIX_TOOL_PICKAXE = "fix tool pickaxe", FIX_TOOL_LAMP_CART = "fix tool lamp cart", FIX_TOOL_PICKAXE_LAMP = "fix tool pickaxe lamp", FIX_TOOL_PICKAXE_CART = "fix tool pickaxe cart", } ``` ```ts enum RoleCard { GoldMiner = "gold miner", Saboteur = "saboteur", } ``` ```ts const GoalCards = Object.freeze([ PathCard.GOAL_GOLD, PathCard.GOAL_COAL_BOTTOM_RIGHT, PathCard.GOAL_COAL_BOTTOM_LEFT, ]); ``` ```ts= type GoldNuggetCard = "gold"; type Card = PathCard | ActionCard | RoleCard type HandCard = PathCard | ActionCard ``` ```ts const CardCount = Object.freeze({ [PathCard.START]: 1, [PathCard.GOAL_GOLD]: 1, [PathCard.GOAL_COAL_BOTTOM_RIGHT]: 1, [PathCard.GOAL_COAL_BOTTOM_LEFT]: 1, [PathCard.CONNECTED_TOP_BOTTOM]: 4, [PathCard.CONNECTED_TOP_BOTTOM_RIGHT]: 5, [PathCard.CONNECTED_CROSS]: 5, [PathCard.CONNECTED_TOP_LEFT_RIGHT]: 5, [PathCard.CONNECTED_LEFT_RIGHT]: 3, [PathCard.CONNECTED_BOTTOM_RIGHT]: 4, [PathCard.CONNECTED_BOTTOM_LEFT]: 5, [PathCard.DEADEND_BOTTOM]: 1, [PathCard.DEADEND_TOP_BOTTOM]: 1, [PathCard.DEADEND_TOP_BOTTOM_RIGHT]: 1, [PathCard.DEADEND_CROSS]: 1, [PathCard.DEADEND_TOP_LEFT_RIGHT]: 1, [PathCard.DEADEND_LEFT_RIGHT]: 1, [PathCard.DEADEND_BOTTOM_RIGHT]: 1, [PathCard.DEADEND_BOTTOM_LEFT]: 1, [PathCard.DEADEND_LEFT]: 1, [ActionCard.MAP]: 6, [ActionCard.ROCKFALL]: 3, [ActionCard.BROKEN_TOOL_CART]: 3, [ActionCard.BROKEN_TOOL_LAMP]: 3, [ActionCard.BROKEN_TOOL_PICKAXE]: 3, [ActionCard.FIX_TOOL_CART]: 2, [ActionCard.FIX_TOOL_LAMP]: 2, [ActionCard.FIX_TOOL_PICKAXE]: 2, [ActionCard.FIX_TOOL_LAMP_CART]: 1, [ActionCard.FIX_TOOL_PICKAXE_LAMP]: 1, [ActionCard.FIX_TOOL_PICKAXE_CART]: 1, [GoldNuggetCard]: 28, [RoleCard.GoldMiner]: 7, [RoleCard.Saboteur]: 4, }); ``` ### Place Path Card Command ```ts type PlacePathCardCommand = { type: 'place path card', data: Placement } ``` ### Path Card Has Been Placed Event ```ts type PathCardHasBeenPlacedEvent = { type: 'path card has been placed', data: Placement } ``` ### Path Card Has Been Removed Event ```ts type PathCardHasBeenRemovedEvent = { type: 'path card has been removed', data: Placement } ``` ### Position Has Been Placed Error ```ts type PositionHasBeenPlacedError = Error & { name: 'PositionHasBeenPlacedError', message: `the path card ${command.card} cannot be placed at position (${command.position})` } ``` ### Target Can Not Be Removed Error ```ts type TargetCannotBeRemovedError = Error & { name: 'TargetCannotBeRemovedError', message: `can not remove card ${card} at position(${x}, ${y})` } ``` ### Check Position Has Been Placed ```ts type CheckPositionHasBeenPlaced = (placements: CurrentPlacements) => (command: PlacePathCardCommand) => Result< PlacePathCardCommand, PositionHasBeenPlacedError > ``` ### PlacementCannotConnectFromStartError ```ts type PlacementCannotConnectFromStartError = Error & { name: 'PlacementCannotConnectFromStartError', message: `the path card ${placement.card} cannot be placed at position (${placement.position})` } ``` ### PlacementCannotFitNeighborsError ```ts type PlacementCannotFitNeighborsError = Error & { name: 'PlacementCannotFitNeighborsError', message: `the path card ${placement.card} cannot be placed at position (${placement.position})` } ``` ### Check Position Is Connected ```ts type CheckPositionIsConnected = (board: Placement[]) => (command: PlacePathCardCommand) => Result< PlacePathCardCommand, PlacementCannotConnectedError > ``` ### Place Path Card Error ```ts type PlacePathCardError = | GetCurrentPlacementsError | PositionHasBeenPlacedError | PositionIsNotConnectedErrors | RepositoryWriteError ``` ### Place Path Card ```ts type PlacePathCard = (source: EventSource) => (command: PlacePathCardCommand) => ResultAsync< PathCardHasBeenPlacedEvent, PlacePathCardError > ``` ### Current Placements ```ts type CurrentPlacements = Placement[] ``` ### Get Current Placements Error ```ts type GetCurrentPlacementsError = EventSourceReadError ``` ### Get Current Placements ```ts type GetCurrentPlacements = (source: EventSource) => ResultAsync< CurrentPlacements, GetCurrentPlacementsError > ``` ### Tool ```ts enum Tool { Cart, Lamp, Pickaxe, } ``` ### GetToolHasBrokenOnPlayer ``` ``` ### Check Tool Has Broken Error ```ts type CheckToolHasBrokenError = | EventSourceReadError | ToolHasBeenBrokenError | ToolHasNotBeenBrokenError; ``` ### Check Tools Has Broken ```ts export type CheckToolHasBroken = ( command: BrokenToolCommand | FixToolCommand ) => ( toolsHasBroken: Tool[] ) => Result<BrokenToolCommand | FixToolCommand, CheckToolHasBrokenError>; ``` ### Broken Tool Command ```ts type BrokenToolCommand = { type: 'action card (broken tool)', data: { playerId: string tool: Tool } } ``` ### Fix Tool Command ```ts type FixToolCommand = { type: 'action card (broken tool)', data: { playerId: string tool: Tool } } ``` ### Broken Tool Has Been Placed Event ```ts type BrokenToolHasBeenPlacedEvent = { type: "broken tool has been placed", data: { playerId: string tool: Tool } } ``` ### Broken Tool Has Been Removed Event ```ts type BrokenToolHasBeenRemovedEvent = { type: "broken tool has been removed", data: { playerId: string tool: Tool } } ``` ### Place Broken Tool ```ts type PlaceBrokenTool = (source: EventSource<Event>) => (command: BrokenToolCommand) => ResultAsync< BrokenToolHasBeenPlacedEvent, PlaceBrokenToolError > ``` ### Remove Broken Tool ```ts type RemoveBrokenTool = (source: EventSource<Event>) => (command: FixToolCommand) => ResultAsync< BrokenToolHasBeenRemovedEvent, ToolHasBeenBrokenError > ``` ### Place Broken Tool Error ```ts type PlaceBrokenToolError = | ToolHasBrokenError | EventSourceReadError | EventSourceWriteError ``` ### Remove Broken Tool Error ```ts type RemoveBrokenToolError = | ToolHasNotBrokenError | EventSourceReadError | EventSourceWriteError ``` ### Tool Has Broken Error ```ts type ToolHasBeenBrokenError = Error & { name: 'ToolHasBeenBrokenError' message: `can not broke player ${player.id} tool ${tool}` } ``` ### Tool Has Not Been Broken Error ```ts type ToolHasNotBeenBrokenError = Error & { name: 'ToolHasNotBeenBrokenError' message: `can not fix player ${player.id} tool ${tool}` } ``` ### Map Command ```ts type MapCommand = { type: 'use action card (map)', data: { playerId: string position: Vec2 } } ``` ### GoalCardHasBeenRevealEvent ```ts type GoalCardHasBeenRevealEvent = { type: 'GoalCardHasBeenRevealEvent', data: { playerId: string position: Vec2 } } ``` ### GoalCardNotFoundError ```ts type GoalCardNotFoundError = Error & { name: 'GoalCardNotFoundError', message: `goal card not found at position(${x}, ${y})` } ``` ### Reveal Goal ```ts type RevealGoal = (source: EventSource) => (command: MapCommand) => ResultAsync< GoalCardHasBeenRevealEvent, GoalCardNotFoundError > ``` ### Pass ```ts type Pass = ( source: EventSource<Event>, command: PassCommand ) => ResultAsync<TurnHasBeenPassedEvent, PassError>; ```