# 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>;
```