midorimici / fairy-chess-online

Fairy chess online is a web app to play or watch fairy chess games with others.
0 stars 0 forks source link

Create games page #6

Open midorimici opened 2 years ago

midorimici commented 2 years ago

/games Fetch game data and display game informations.

from GraphCMS (static data)

name: string
description: string
boardSize: int
withCastling: bool
promotionCandidates: string list  # piece ids
initialBoardImage: one file media
isAsymmetric: bool
initialPiecePositions: JSON object
  [rank]:
    - pieceName | null
pieceName  ::= pieceColor pieceId | pieceId  # pieceColor must be omitted when it is symmetric game
pieceColor ::= 'W' | 'B'
pieceId    ::= [A-Z][a-zA-Z0-9]*

from Realtime Database (dynamic data), in later PR

midorimici commented 2 years ago

Add piece model and contents to GraphCMS.

piece expandMoves is useful to omit duplicated moves.

abbr: enum (piece id)
value: float
moves: JSON object (list of moveNode)
expandMoves?: enum['V' | 'H' | 'X']  # Add reversed moves of "moves" V: ↕, H: ↔, X: ↕↔ ↖↘ ↙↗

moveNode tree structure

move: move
children?: moveNode[]
when?: string

move Either the ref field, or type and direction fields are required. Fields for hopper and penetration will not be implemented at this stage.

ref?: pieceId                    # Id of a piece to copy.
type?: enum['leaper' | 'rider']  # Required when ref is not specified.
direction?: [int, int]           # The direction seen from a white player. Top-right will be greater. Required when ref is not specified.
length?: number (0 -)            # The distance to run (for riders and hoppers). 0 or unspecified means infinity.
# Fields for hopper
# reach?: number
# captureHurdle?: boolean
# Fields for penetration
# penetrationLimit?: number (0 -) # The number of pieces that the piece penetrates. 0 means infinity.
reflectionLimit?: number (1 - 3)  # The times that the piece reflects on the edge of the board.
option?: enum['move-only' | 'capture-only']
midorimici commented 2 years ago

For instance, moves of a knight become like this:

{
  "moves": [
    {
      "move": {
        "type": "leaper",
        "direction": [1, 2],
      },
    },
    {
      "move": {
        "type": "leaper",
        "direction": [2, 1],
      },
    },
    {
      "move": {
        "type": "leaper",
        "direction": [2, -1],
      },
    },
    // ... 5 more ...
  ],
}

// More short with expandMoves:

{
  "moves": [
    {
      "move": {
        "type": "leaper",
        "direction": [1, 2],
      },
    },
  ],
  "expandMoves": "X",
}

griffin:

{
  "moves": [
    {
      "move": {
        "type": "leaper",
        "direction": [1, 1],
        "option": "move-only",
      },
      "children": [
        {
          "move": {
            "type": "rider",
            "direction": [1, 0],
          },
        },
        {
          "move": {
            "type": "rider",
            "direction": [0, 1],
          },
        },
      ],
    },
  ],
  "expandMoves": "X",
}
midorimici commented 2 years ago

Use when field to specify the condition that the move is applied. This is convenient for pieces that alter moves depending on how many times they have moved. For instance, moves of an imitator become like this:

{
  "moves": [
    {
      "move": {
        "ref": "N",
      },
      "when": "piece.moveCount % 5 === 0",
    },
    {
      "move": {
        "ref": "B",
      },
      "when": "piece.moveCount % 5 === 1",
    },
    // ... 3 more ...
  ],
}
midorimici commented 2 years ago

A complex example: pawn

{
  "moves": [
    {
      "move": {
        "type": "rider",
        "direction": [0, 1],
        "length": 2,
        "option": "move-only",
      },
      "when": "piece.moveCount === 0",
    },
    {
      "move": {
        "type": "leaper",
        "direction": [0, 1],
        "option": "move-only",
      },
    },
    {
      "move": {
        "type": "leaper",
        "direction": [1, 1],
        "option": "capture-only",
      },
    },
    {
      "move": {
        "type": "leaper",
        "direction": [-1, 1],
        "option": "capture-only",
      },
    },
  ],
}
midorimici commented 2 years ago

initialPiecePositions of the normal game would be like this:

{
  "1": ["P", "P", "P", "P", "P", "P", "P", "P"],
  "0": ["R", "N", "B", "Q", "K", "B", "N", "R"],
}