ddd-team1 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domain/value-objects/Board.ts +33 -81
- package/src/domain/value-objects/Piece.ts +58 -64
- package/src/domain/value-objects/StandardAlgebraicNotationMove.ts +7 -9
- package/src/domain/value-objects/pieces/Bishop.ts +31 -0
- package/src/domain/value-objects/pieces/King.ts +33 -0
- package/src/domain/value-objects/pieces/Knight.ts +31 -0
- package/src/domain/value-objects/pieces/Pawn.ts +53 -0
- package/src/domain/value-objects/pieces/Queen.ts +29 -0
- package/src/domain/value-objects/pieces/Rook.ts +5 -6
- package/src/domain/value-objects/pieces/index.ts +7 -0
- package/src/domain/value-objects/PieceV2.ts +0 -79
package/package.json
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
1
|
import type { StandardAlgebraicNotationMove } from "./StandardAlgebraicNotationMove.ts";
|
|
2
|
-
import { Piece } from "./Piece.ts";
|
|
3
2
|
import { Position } from "./Position.ts";
|
|
4
3
|
import { ValueObject } from "../shared";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
4
|
+
import { Piece } from "./Piece.ts";
|
|
5
|
+
import { Rook, Knight, Bishop, King, Queen, Pawn } from "./pieces/index.ts";
|
|
6
|
+
|
|
7
7
|
|
|
8
|
-
type BoardState = (Piece |
|
|
8
|
+
type BoardState = (Piece | null)[][];
|
|
9
9
|
|
|
10
10
|
export class Board extends ValueObject {
|
|
11
11
|
static initialBoardState: BoardState = [
|
|
12
12
|
[
|
|
13
13
|
new Rook("white"),
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
new Knight("white"),
|
|
15
|
+
new Bishop("white"),
|
|
16
|
+
new Queen("white"),
|
|
17
|
+
new King("white"),
|
|
18
|
+
new Bishop("white"),
|
|
19
|
+
new Knight("white"),
|
|
20
20
|
new Rook("white"),
|
|
21
21
|
],
|
|
22
22
|
[
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
new Pawn("white"),
|
|
24
|
+
new Pawn("white"),
|
|
25
|
+
new Pawn("white"),
|
|
26
|
+
new Pawn("white"),
|
|
27
|
+
new Pawn("white"),
|
|
28
|
+
new Pawn("white"),
|
|
29
|
+
new Pawn("white"),
|
|
30
|
+
new Pawn("white"),
|
|
31
31
|
],
|
|
32
32
|
[null, null, null, null, null, null, null, null],
|
|
33
33
|
[null, null, null, null, null, null, null, null],
|
|
34
34
|
[null, null, null, null, null, null, null, null],
|
|
35
35
|
[null, null, null, null, null, null, null, null],
|
|
36
36
|
[
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
new Pawn("black"),
|
|
38
|
+
new Pawn("black"),
|
|
39
|
+
new Pawn("black"),
|
|
40
|
+
new Pawn("black"),
|
|
41
|
+
new Pawn("black"),
|
|
42
|
+
new Pawn("black"),
|
|
43
|
+
new Pawn("black"),
|
|
44
|
+
new Pawn("black"),
|
|
45
45
|
],
|
|
46
46
|
[
|
|
47
47
|
new Rook("black"),
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
new Knight("black"),
|
|
49
|
+
new Bishop("black"),
|
|
50
|
+
new Queen("black"),
|
|
51
|
+
new King("black"),
|
|
52
|
+
new Bishop("black"),
|
|
53
|
+
new Knight("black"),
|
|
54
54
|
new Rook("black"),
|
|
55
55
|
],
|
|
56
56
|
];
|
|
@@ -110,55 +110,7 @@ export class Board extends ValueObject {
|
|
|
110
110
|
if (capturedPiece?.color == this.color) {
|
|
111
111
|
throw new Error("You cannot capture yourself");
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
if (move.piece?.type === "pawn" && this.color === "white") {
|
|
115
|
-
if (capturedPiece !== null) {
|
|
116
|
-
if (position.file > 0) rulesToCheck.push([position.offset(-1, -1)]);
|
|
117
|
-
if (position.file < 7) rulesToCheck.push([position.offset(1, -1)]);
|
|
118
|
-
} else {
|
|
119
|
-
let forwardMoves = [position.offset(0, -1)];
|
|
120
|
-
if (position.rank === 3) {
|
|
121
|
-
forwardMoves.push(position.offset(0, -2));
|
|
122
|
-
}
|
|
123
|
-
rulesToCheck.push(forwardMoves);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (move.piece?.type === "pawn" && this.color === "black") {
|
|
128
|
-
if (capturedPiece !== null) {
|
|
129
|
-
if (position.file > 0) rulesToCheck.push([position.offset(-1, 1)]);
|
|
130
|
-
if (position.file < 7) rulesToCheck.push([position.offset(1, 1)]);
|
|
131
|
-
} else {
|
|
132
|
-
let forwardMoves = [position.offset(0, 1)];
|
|
133
|
-
if (position.rank === 4) {
|
|
134
|
-
forwardMoves.push(position.offset(0, 2));
|
|
135
|
-
}
|
|
136
|
-
rulesToCheck.push(forwardMoves);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (move.piece?.type === "bishop") {
|
|
141
|
-
rulesToCheck = position.diagonalMask;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (move.piece?.type === "knight") {
|
|
145
|
-
rulesToCheck = position.jumpMask;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (move.piece?.type === "queen") {
|
|
149
|
-
rulesToCheck = position.straightMask.concat(position.diagonalMask);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (move.piece?.type === "king") {
|
|
153
|
-
rulesToCheck = position.straightMask
|
|
154
|
-
.slice(0, 1)
|
|
155
|
-
.concat(position.diagonalMask.slice(0, 1));
|
|
156
|
-
}
|
|
157
|
-
} else {
|
|
158
|
-
if (move.piece instanceof Rook) {
|
|
159
|
-
rulesToCheck = move.piece.getRulesToCheck(position);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
113
|
+
rulesToCheck = move.piece?.getRulesToCheck(position, capturedPiece) ?? [];
|
|
162
114
|
|
|
163
115
|
/*
|
|
164
116
|
* checks each position in the rules to see if the piece at that position matches the move's piece, and returns
|
|
@@ -1,91 +1,85 @@
|
|
|
1
|
-
import { ValueObject } from
|
|
1
|
+
import { ValueObject } from "../shared";
|
|
2
|
+
import { Position } from "./Position.ts";
|
|
2
3
|
|
|
3
|
-
export type PieceColor =
|
|
4
|
-
export type PieceType =
|
|
4
|
+
export type PieceColor = "white" | "black";
|
|
5
|
+
export type PieceType =
|
|
6
|
+
| "king"
|
|
7
|
+
| "queen"
|
|
8
|
+
| "rook"
|
|
9
|
+
| "bishop"
|
|
10
|
+
| "knight"
|
|
11
|
+
| "pawn";
|
|
5
12
|
|
|
6
13
|
const ICONS: Record<PieceColor, Record<PieceType, string>> = {
|
|
7
|
-
black: {
|
|
8
|
-
|
|
14
|
+
black: {
|
|
15
|
+
king: "♔",
|
|
16
|
+
queen: "♕",
|
|
17
|
+
rook: "♖",
|
|
18
|
+
bishop: "♗",
|
|
19
|
+
knight: "♘",
|
|
20
|
+
pawn: "♙",
|
|
21
|
+
},
|
|
22
|
+
white: {
|
|
23
|
+
king: "♚",
|
|
24
|
+
queen: "♛",
|
|
25
|
+
rook: "♜",
|
|
26
|
+
bishop: "♝",
|
|
27
|
+
knight: "♞",
|
|
28
|
+
pawn: "♟",
|
|
29
|
+
},
|
|
9
30
|
};
|
|
10
31
|
|
|
11
32
|
const PIECE_LETTER: Record<string, PieceType> = {
|
|
12
|
-
K:
|
|
13
|
-
Q:
|
|
14
|
-
R:
|
|
15
|
-
B:
|
|
16
|
-
N:
|
|
17
|
-
|
|
33
|
+
K: "king",
|
|
34
|
+
Q: "queen",
|
|
35
|
+
R: "rook",
|
|
36
|
+
B: "bishop",
|
|
37
|
+
N: "knight",
|
|
38
|
+
"": "pawn",
|
|
18
39
|
};
|
|
19
40
|
|
|
20
41
|
const LETTER_PIECE: Record<PieceType, string> = {
|
|
21
|
-
king:
|
|
22
|
-
queen:
|
|
23
|
-
rook:
|
|
24
|
-
bishop:
|
|
25
|
-
knight:
|
|
26
|
-
pawn:
|
|
27
|
-
}
|
|
42
|
+
king: "K",
|
|
43
|
+
queen: "Q",
|
|
44
|
+
rook: "R",
|
|
45
|
+
bishop: "B",
|
|
46
|
+
knight: "N",
|
|
47
|
+
pawn: "",
|
|
48
|
+
};
|
|
28
49
|
|
|
29
|
-
export class Piece extends ValueObject {
|
|
30
|
-
private
|
|
31
|
-
public readonly color: PieceColor,
|
|
32
|
-
public readonly type: PieceType,
|
|
33
|
-
) {
|
|
34
|
-
super();
|
|
35
|
-
}
|
|
50
|
+
export abstract class Piece extends ValueObject {
|
|
51
|
+
private static registry = new Map<PieceType, new (color: PieceColor) => Piece>();
|
|
36
52
|
|
|
37
|
-
|
|
38
|
-
|
|
53
|
+
static register(type: PieceType, constructor: new (color: PieceColor) => Piece) {
|
|
54
|
+
this.registry.set(type, constructor);
|
|
39
55
|
}
|
|
40
56
|
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
constructor(public readonly color: PieceColor) {
|
|
58
|
+
super();
|
|
43
59
|
}
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
abstract readonly icon: string;
|
|
62
|
+
abstract readonly char: string;
|
|
63
|
+
abstract getRulesToCheck(position: Position, getCapturedPiece?: any): Position[][];
|
|
48
64
|
|
|
49
|
-
|
|
50
|
-
return
|
|
65
|
+
override toString(): string {
|
|
66
|
+
return `${this.icon} (${this.color} ${this.constructor.name})`;
|
|
51
67
|
}
|
|
52
68
|
|
|
53
69
|
protected getAtomicValues(): any[] {
|
|
54
|
-
return [this.color, this.
|
|
70
|
+
return [this.color, this.constructor.name];
|
|
55
71
|
}
|
|
56
72
|
|
|
57
|
-
static
|
|
58
|
-
for (const color in ICONS) {
|
|
59
|
-
for (const type in ICONS[color as PieceColor]) {
|
|
60
|
-
if (ICONS[color as PieceColor][type as PieceType] === icon) {
|
|
61
|
-
return new Piece(color as PieceColor, type as PieceType);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
static fromLetter(letter: string, color: 'white' | 'black'): Piece | null {
|
|
73
|
+
static fromLetter(letter: string, color: "white" | "black"): Piece | null {
|
|
69
74
|
const pieceType = PIECE_LETTER[letter.toUpperCase()];
|
|
70
75
|
if (!pieceType) {
|
|
71
76
|
return null;
|
|
72
77
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
static readonly WhiteKing = new Piece('white', 'king');
|
|
78
|
-
static readonly WhiteQueen = new Piece('white', 'queen');
|
|
79
|
-
static readonly WhiteRook = new Piece('white', 'rook');
|
|
80
|
-
static readonly WhiteBishop = new Piece('white', 'bishop');
|
|
81
|
-
static readonly WhiteKnight = new Piece('white', 'knight');
|
|
82
|
-
static readonly WhitePawn = new Piece('white', 'pawn');
|
|
78
|
+
const PieceConstructor = this.registry.get(pieceType);
|
|
79
|
+
if (!PieceConstructor) {
|
|
80
|
+
throw new Error(`Piece type ${pieceType} not registered`);
|
|
81
|
+
}
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
static readonly BlackQueen = new Piece('black', 'queen');
|
|
87
|
-
static readonly BlackRook = new Piece('black', 'rook');
|
|
88
|
-
static readonly BlackBishop = new Piece('black', 'bishop');
|
|
89
|
-
static readonly BlackKnight = new Piece('black', 'knight');
|
|
90
|
-
static readonly BlackPawn = new Piece('black', 'pawn');
|
|
83
|
+
return new PieceConstructor(color);
|
|
84
|
+
}
|
|
91
85
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Piece, type PieceType } from "./Piece.ts";
|
|
2
1
|
import { Position } from "./Position.ts";
|
|
3
2
|
import { ValueObject } from "../shared";
|
|
4
|
-
import
|
|
3
|
+
import { Piece } from "./Piece.ts";
|
|
5
4
|
import { Rook } from "./pieces/Rook.ts";
|
|
6
5
|
|
|
7
6
|
const SAN_REGEX =
|
|
@@ -24,7 +23,7 @@ export class StandardAlgebraicNotationMove extends ValueObject {
|
|
|
24
23
|
private constructor(
|
|
25
24
|
public readonly turn: number,
|
|
26
25
|
public readonly destination: Position | null,
|
|
27
|
-
public readonly piece: Piece |
|
|
26
|
+
public readonly piece: Piece | null,
|
|
28
27
|
public readonly isCapture: boolean,
|
|
29
28
|
public readonly fromFile: number | null,
|
|
30
29
|
public readonly fromRank: number | null,
|
|
@@ -65,10 +64,8 @@ export class StandardAlgebraicNotationMove extends ValueObject {
|
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
const destination = Position.fromAlgebraicNotation(g.toFile! + g.toRank!);
|
|
68
|
-
let piece: Piece |
|
|
69
|
-
|
|
70
|
-
piece = new Rook(color);
|
|
71
|
-
}
|
|
67
|
+
let piece: Piece | null = Piece.fromLetter(g.piece ?? "", color);
|
|
68
|
+
|
|
72
69
|
const isCapture = g.capture === "x";
|
|
73
70
|
|
|
74
71
|
// Disambiguation: fromFile/fromRank only count when toFile is also present
|
|
@@ -91,6 +88,7 @@ export class StandardAlgebraicNotationMove extends ValueObject {
|
|
|
91
88
|
const promotion = g.promotion
|
|
92
89
|
? Piece.fromLetter(g.promotion!, color)
|
|
93
90
|
: null;
|
|
91
|
+
|
|
94
92
|
const check = (g.check as "+" | "#") ?? null;
|
|
95
93
|
|
|
96
94
|
return new StandardAlgebraicNotationMove(
|
|
@@ -116,7 +114,7 @@ export class StandardAlgebraicNotationMove extends ValueObject {
|
|
|
116
114
|
}
|
|
117
115
|
|
|
118
116
|
if (this.piece) {
|
|
119
|
-
result += this.piece.
|
|
117
|
+
result += this.piece.char;
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
if (this.fromFile !== null) {
|
|
@@ -134,7 +132,7 @@ export class StandardAlgebraicNotationMove extends ValueObject {
|
|
|
134
132
|
result += this.destination!.toString();
|
|
135
133
|
|
|
136
134
|
if (this.promotion) {
|
|
137
|
-
result += `=${this.promotion.
|
|
135
|
+
result += `=${this.promotion.char}`;
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
if (this.check) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
|
+
import { Position } from "../Position.ts";
|
|
3
|
+
|
|
4
|
+
export class Bishop extends Piece {
|
|
5
|
+
constructor(color: PieceColor) {
|
|
6
|
+
super(color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get icon(): string {
|
|
10
|
+
if (this.color === "white") {
|
|
11
|
+
return "♝";
|
|
12
|
+
}
|
|
13
|
+
return "♗";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get char(): string {
|
|
17
|
+
return "B";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override toString(): string {
|
|
21
|
+
return `${this.icon} (${this.color} Bishop)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getRulesToCheck(position: Position) {
|
|
25
|
+
return position.diagonalMask;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Piece.register("bishop", Bishop);
|
|
30
|
+
|
|
31
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
|
+
import { Position } from "../Position.ts";
|
|
3
|
+
|
|
4
|
+
export class King extends Piece {
|
|
5
|
+
constructor(color: PieceColor) {
|
|
6
|
+
super(color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get icon(): string {
|
|
10
|
+
if (this.color === "white") {
|
|
11
|
+
return "♚";
|
|
12
|
+
}
|
|
13
|
+
return "♔";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get char(): string {
|
|
17
|
+
return "K";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override toString(): string {
|
|
21
|
+
return `${this.icon} (${this.color} King)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getRulesToCheck(position: Position) {
|
|
25
|
+
return position.straightMask
|
|
26
|
+
.slice(0, 1)
|
|
27
|
+
.concat(position.diagonalMask.slice(0, 1));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Piece.register("king", King);
|
|
32
|
+
|
|
33
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
|
+
import { Position } from "../Position.ts";
|
|
3
|
+
|
|
4
|
+
export class Knight extends Piece {
|
|
5
|
+
constructor(color: PieceColor) {
|
|
6
|
+
super(color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get icon(): string {
|
|
10
|
+
if (this.color === "white") {
|
|
11
|
+
return "♞";
|
|
12
|
+
}
|
|
13
|
+
return "♘";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get char(): string {
|
|
17
|
+
return "N";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override toString(): string {
|
|
21
|
+
return `${this.icon} (${this.color} Knight)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getRulesToCheck(position: Position) {
|
|
25
|
+
return position.jumpMask;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Piece.register("knight", Knight);
|
|
30
|
+
|
|
31
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
|
+
import { Position } from "../Position.ts";
|
|
3
|
+
|
|
4
|
+
export class Pawn extends Piece {
|
|
5
|
+
constructor(color: PieceColor) {
|
|
6
|
+
super(color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get icon(): string {
|
|
10
|
+
if (this.color === "white") {
|
|
11
|
+
return "♟";
|
|
12
|
+
}
|
|
13
|
+
return "♙";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get char(): string {
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override toString(): string {
|
|
21
|
+
return `${this.icon} (${this.color} Pawn)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getRulesToCheck(position: Position, capturedPiece: any = null) {
|
|
25
|
+
let rulesToCheck: Position[][] = [];
|
|
26
|
+
|
|
27
|
+
const colorRules = {
|
|
28
|
+
"white": {
|
|
29
|
+
direction: -1,
|
|
30
|
+
rank: 3
|
|
31
|
+
},
|
|
32
|
+
"black": {
|
|
33
|
+
direction: 1,
|
|
34
|
+
rank: 4
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (capturedPiece !== null) {
|
|
39
|
+
if (position.file > 0) rulesToCheck.push([position.offset(-1, colorRules[this.color].direction)]);
|
|
40
|
+
if (position.file < 7) rulesToCheck.push([position.offset(1, colorRules[this.color].direction)]);
|
|
41
|
+
} else {
|
|
42
|
+
let forwardMoves = [position.offset(0, colorRules[this.color].direction)];
|
|
43
|
+
if (position.rank === colorRules[this.color].rank) {
|
|
44
|
+
forwardMoves.push(position.offset(0, 2 * colorRules[this.color].direction));
|
|
45
|
+
}
|
|
46
|
+
rulesToCheck.push(forwardMoves);
|
|
47
|
+
}
|
|
48
|
+
return rulesToCheck;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Piece.register("pawn", Pawn);
|
|
53
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
|
+
import { Position } from "../Position.ts";
|
|
3
|
+
|
|
4
|
+
export class Queen extends Piece {
|
|
5
|
+
constructor(color: PieceColor) {
|
|
6
|
+
super(color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get icon(): string {
|
|
10
|
+
if (this.color === "white") {
|
|
11
|
+
return "♛";
|
|
12
|
+
}
|
|
13
|
+
return "♕";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get char(): string {
|
|
17
|
+
return "Q";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override toString(): string {
|
|
21
|
+
return `${this.icon} (${this.color} Queen)`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getRulesToCheck(position: Position) {
|
|
25
|
+
return position.straightMask.concat(position.diagonalMask);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Piece.register("queen", Queen);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Piece, type PieceColor } from "../Piece.ts";
|
|
2
2
|
import { Position } from "../Position.ts";
|
|
3
3
|
|
|
4
|
-
export class Rook extends
|
|
4
|
+
export class Rook extends Piece {
|
|
5
5
|
constructor(color: PieceColor) {
|
|
6
6
|
super(color);
|
|
7
7
|
}
|
|
@@ -17,10 +17,6 @@ export class Rook extends PieceV2 {
|
|
|
17
17
|
return "R";
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
toChar(): string {
|
|
21
|
-
return "R";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
20
|
override toString(): string {
|
|
25
21
|
return `${this.icon} (${this.color} Rook)`;
|
|
26
22
|
}
|
|
@@ -29,3 +25,6 @@ export class Rook extends PieceV2 {
|
|
|
29
25
|
return position.straightMask;
|
|
30
26
|
}
|
|
31
27
|
}
|
|
28
|
+
|
|
29
|
+
Piece.register("rook", Rook);
|
|
30
|
+
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { ValueObject } from "../shared";
|
|
2
|
-
import { Rook } from "./pieces/Rook";
|
|
3
|
-
|
|
4
|
-
export type PieceColor = "white" | "black";
|
|
5
|
-
export type PieceType =
|
|
6
|
-
| "king"
|
|
7
|
-
| "queen"
|
|
8
|
-
| "rook"
|
|
9
|
-
| "bishop"
|
|
10
|
-
| "knight"
|
|
11
|
-
| "pawn";
|
|
12
|
-
|
|
13
|
-
const ICONS: Record<PieceColor, Record<PieceType, string>> = {
|
|
14
|
-
black: {
|
|
15
|
-
king: "♔",
|
|
16
|
-
queen: "♕",
|
|
17
|
-
rook: "♖",
|
|
18
|
-
bishop: "♗",
|
|
19
|
-
knight: "♘",
|
|
20
|
-
pawn: "♙",
|
|
21
|
-
},
|
|
22
|
-
white: {
|
|
23
|
-
king: "♚",
|
|
24
|
-
queen: "♛",
|
|
25
|
-
rook: "♜",
|
|
26
|
-
bishop: "♝",
|
|
27
|
-
knight: "♞",
|
|
28
|
-
pawn: "♟",
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const PIECE_LETTER: Record<string, PieceType> = {
|
|
33
|
-
K: "king",
|
|
34
|
-
Q: "queen",
|
|
35
|
-
R: "rook",
|
|
36
|
-
B: "bishop",
|
|
37
|
-
N: "knight",
|
|
38
|
-
"": "pawn",
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const LETTER_PIECE: Record<PieceType, string> = {
|
|
42
|
-
king: "K",
|
|
43
|
-
queen: "Q",
|
|
44
|
-
rook: "R",
|
|
45
|
-
bishop: "B",
|
|
46
|
-
knight: "N",
|
|
47
|
-
pawn: "",
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export abstract class PieceV2 extends ValueObject {
|
|
51
|
-
constructor(public readonly color: PieceColor) {
|
|
52
|
-
super();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
abstract readonly icon: string;
|
|
56
|
-
abstract readonly char: string;
|
|
57
|
-
abstract toChar(): string;
|
|
58
|
-
|
|
59
|
-
override toString(): string {
|
|
60
|
-
return `${this.icon} (${this.color} ${this.constructor.name})`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
protected getAtomicValues(): any[] {
|
|
64
|
-
return [this.color, this.constructor.name];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static fromLetter(letter: string, color: "white" | "black"): PieceV2 | null {
|
|
68
|
-
const pieceType = PIECE_LETTER[letter.toUpperCase()];
|
|
69
|
-
if (!pieceType) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
switch (pieceType) {
|
|
73
|
-
case "rook":
|
|
74
|
-
return new Rook(color);
|
|
75
|
-
default:
|
|
76
|
-
throw new Error(`Unknown letter ${letter}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|