-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfen.ebnf
136 lines (108 loc) · 4.91 KB
/
fen.ebnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(*
# Yet another 5DFEN format, designed for flexibility
This format introduces a way of specifying custom variants and starting position for games.
It is meant to be an extension of any notation using PGN-like headers followed by a body of moves,
by inserting special headers that define the initial positions (or boards) of the game.
A board is considered initial if one of the following conditions is true:
- it does not emanate from any other board (eg. the first board in standard)
- there weren't any move from the board that it emanated that would yield that board (eg. the second board in standard - turn zero)
Initial boards encoded using this format contain the following pieces of information:
- piece kinds
- piece colors
- if pieces had moved already or not
- initial board position (l, t, w)
## Metadata
The following metadata fields are required to have within the headers of a game using this extension:
- `variant = "custom"`, as to indicate that 5DFEN needs to be used
- `size = "WxH"`, with `W` the width of the boards and `H` the height of the boards
- `puzzle = "mate-in-N"`, with `N` the number of actions to be made by the current player. This is only required if the position is meant
as a puzzle and where a mate in N is possible. Other kinds of puzzles may also be encoded in a similar way.
## Example
This is how the standard position would be encoded:
```fen
[size "8x8"]
[variant "custom"]
[r*nbqk*bnr*/p*p*p*p*p*p*p*p*/8/8/8/8/P*P*P*P*P*P*P*P*/R*NBQK*BNR*:0:1:w]
```
This is how `Rook Tactics I` would be encoded, using Shad's notation:
```fen
[size "5x5"]
[puzzle "mate-in-1"]
[variant "custom"]
[4k/5/5/5/K1R2:0:1:w]
1. Kb2 / Ke4
2. Re1 / Kd3
```
## Semantical meaning
A *board string* is the 5DFEN way of describing the state of an initial board.
A board string is enclosed within square brackets (`[]`) and is made of several fields, separated by colons (`:`).
There should be no spaces, as to not confuse a board string with a regular header.
The first field contains the board's pieces.
The different rows of the board are separated by slashes (`/`), the rows are read from top to bottom.
Each row is a string of pieces, encoded using letters (optionally preceded by a `+`), and blanks, encoded using numbers.
A white piece is encoded as an uppercase letter and a black piece as a lowercase letter.
To extend the number of pieces that can be encoded without sacrificing readability, a piece's corresponding letter may be *preceded*
by a `+`.
Here is a list of candidate piece letters for your implementation of this extension.
This list is the one used by Alexbay's implementation of this extension:
- `P/p` for [p]awn
- `B/b` for [b]ishop
- `R/r` for [r]ook
- `N/n` for k[n]ight
- `K/k` for [k]ing
- `Q/q` for [q]ueen
- `U/u` for [u]nicorn
- `D/d` for [d]ragon
- `S/s` for prince[s]s
- `W/w` for bra[w]n
- `C/c` for [c]ommon king
- `Y/y` for ro[y]al queen
Blanks are encoded using numbers:
- If there is a one-piece blank, then it is encoded using `1`.
- If there is a two-piece blank, then it is encoded using `2`.
- If there is a ten-piece blank, then it is encoded using `10.
- If there is a N-piece blank, then it is encoded by writing `N` out in base 10.
If a piece is sensitive to having been moved already or not and hasn't moved yet, then it must be followed by an asterisk (`*`):
- An unmoved white pawn is encoded as `P*`
- An unmoved black king is encoded as `k*`
The other three fields are:
- Timeline, may be `-1`, `-0`, `0`, `+0`, `+1`, etc.
- Turn, as displayed in-game, may be `0`, `1`, `2`, etc.
- Player color, may be `w` for white and `b` for black
*)
(* ## Prerequisites: *)
space = ' ' | '\n';
lowercase = ? a-z ?;
uppercase = ? A-Z ?;
number = ? 0-9 ?;
escaped_string = ? any character that may fit in a quotation-mark-delimited string, including '\"' ?;
period = '.';
underscore = '_';
dash = '-';
(*
This policy can be extended depending on the need for more characters.
*)
piece_white = ['+'], lowercase;
piece_black = ['+'], uppercase;
(*
Whether or not the piece hadn't already moved. This can safely be ignored if the piece has no special move requiring it to had moved or not.
For the standard set of pieces, the following pieces should have their "unmoved" state annotated:
- pawns
- kings
- rooks
*)
unmoved = '*';
(* ## Board coordinates: *)
board_layer = (('-' | '+'), {number}) | '0';
board_time = {number};
board_color = 'w' | 'b';
(* ## FEN-formatted pieces *)
fen_piece = (piece_white | piece_black), [unmoved];
fen_pieces = {fen_piece | number}, {'/', {fen_piece}};
(* In this implementation, moves are formatted using either Shad's notation or Alexbay's *)
MOVE = ? a move formatted in a formalized notation ?, [{space}];
key_character = lowercase | uppercase | period | underscore | dash;
HEADER = '[', {key_character}, {space}, '"', {escaped_string}, '"]', [{space}];
BOARD = '[', fen_pieces, ':', board_layer, ':', board_time, ':', board_color, ']', [{space}];
(* ## Root: *)
ROOT = [{HEADER}], [{BOARD}], [{MOVE}];