---
# System prepended metadata

title: Saboteur Functional Domain Modeling Type
tags: [saboteur]

---

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

