53420e8368810eb30612af73118738907919200c
1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
3 export class TitanRules
extends ChessRules
{
5 static get IMAGE_EXTENSION() {
6 // Temporarily, for the time SVG pieces are being designed:
10 // Decode if normal piece, or + bishop or knight
12 const piece
= this.board
[x
][y
].charAt(1);
13 if (ChessRules
.PIECES
.includes(piece
)) return piece
;
34 // Code: a/c = bishop + knight/bishop j/l for king,
35 // m/o for knight, s/t for queen, u/v for rook
36 static get AUGMENTED_PIECES() {
55 // Decode above notation into additional piece
56 getExtraPiece(symbol
) {
57 if (['a','j','m','s','u'].includes(symbol
))
62 // Inverse operation: augment piece
64 const knight
= this.movesCount
<= 1;
66 case V
.ROOK: return (knight
? 'u' : 'v');
67 case V
.KNIGHT: return (knight
? 'm' : 'o');
68 case V
.BISHOP: return (knight
? 'a' : 'c');
69 case V
.QUEEN: return (knight
? 's' : 't');
70 case V
.KING: return (knight
? 'j' : 'l');
72 return '_'; //never reached
75 static IsGoodPosition(position
) {
76 if (position
.length
== 0) return false;
77 const rows
= position
.split("/");
78 if (rows
.length
!= V
.size
.x
) return false;
79 let kings
= { "w": 0, "b": 0 };
80 const allPiecesCodes
= V
.PIECES
.concat(V
.AUGMENTED_PIECES
);
81 const kingBlackCodes
= ['j','k','l'];
82 const kingWhiteCodes
= ['J','K','L'];
83 for (let row
of rows
) {
85 for (let i
= 0; i
< row
.length
; i
++) {
86 if (kingBlackCodes
.includes(row
[i
])) kings
['b']++;
87 else if (kingWhiteCodes
.includes(row
[i
])) kings
['w']++;
88 if (allPiecesCodes
.includes(row
[i
].toLowerCase())) sumElts
++;
90 const num
= parseInt(row
[i
], 10);
91 if (isNaN(num
)) return false;
95 if (sumElts
!= V
.size
.y
) return false;
97 // Both kings should be on board, only one of each color:
98 if (Object
.values(kings
).some(v
=> v
!= 1)) return false;
102 // Kings may be augmented:
104 this.kingPos
= { w: [-1, -1], b: [-1, -1] };
105 const rows
= V
.ParseFen(fen
).position
.split("/");
106 for (let i
= 0; i
< rows
.length
; i
++) {
107 let k
= 0; //column index on board
108 for (let j
= 0; j
< rows
[i
].length
; j
++) {
109 const piece
= rows
[i
].charAt(j
);
110 if (['j','k','l'].includes(piece
.toLowerCase())) {
111 const color
= (piece
.charCodeAt(0) <= 90 ? 'w' : 'b');
112 this.kingPos
[color
] = [i
, k
];
115 const num
= parseInt(rows
[i
].charAt(j
), 10);
116 if (!isNaN(num
)) k
+= num
- 1;
123 // If piece not in usual list, bishop or knight appears.
124 getPotentialMovesFrom([x
, y
]) {
125 if (this.movesCount
<= 3) {
127 const color
= this.getColor(x
, y
);
128 const firstRank
= (color
== 'w' ? 7 : 0);
129 if (x
!= firstRank
|| V
.AUGMENTED_PIECES
.includes(this.board
[x
][y
][1]))
131 const piece
= this.getPiece(x
, y
);
132 const move = new Move({
134 new PiPo({ x: x
, y: y
, c: color
, p: this.getAugmented(piece
) })
137 new PiPo({ x: x
, y: y
, c: color
, p: piece
})
139 start: { x: x
, y: y
},
144 let moves
= super.getPotentialMovesFrom([x
, y
]);
145 const initialPiece
= this.getPiece(x
, y
);
146 const color
= this.turn
;
148 ((color
== 'w' && x
== 7) || (color
== "b" && x
== 0)) &&
149 V
.AUGMENTED_PIECES
.includes(this.board
[x
][y
][1])
151 const newPiece
= this.getExtraPiece(this.board
[x
][y
][1]);
153 m
.appear
[0].p
= initialPiece
;
164 if (m
.vanish
.length
<= 1) return;
165 const [vx
, vy
] = [m
.vanish
[1].x
, m
.vanish
[1].y
];
167 m
.appear
.length
>= 2 && //3 if the king was also augmented
168 m
.vanish
.length
== 2 &&
169 m
.vanish
[1].c
== color
&&
170 V
.AUGMENTED_PIECES
.includes(this.board
[vx
][vy
][1])
172 // Castle, rook is an "augmented piece"
173 m
.appear
[1].p
= V
.ROOK
;
176 p: this.getExtraPiece(this.board
[vx
][vy
][1]),
188 hoverHighlight([x
, y
]) {
191 this.movesCount
<= 3 &&
192 ((c
== 'w' && x
== 7) || (c
== 'b' && x
== 0))
196 // Special case of move 1 = choose squares, knight first, then bishop
198 if (this.movesCount
>= 4) return null;
199 const color
= this.turn
;
200 const [x
, y
] = [square
[0], square
[1]];
201 if ((color
== 'w' && x
!= 7) || (color
== 'b' && x
!= 0)) return null;
202 const selectedPiece
= this.board
[x
][y
][1];
209 p: this.getAugmented(selectedPiece
)
220 start: { x: x
, y: y
},
226 if (this.movesCount
> 4) super.postPlay(move);
230 if (this.movesCount
>= 4) super.postUndo(move);
235 for (let i
= 0; i
< V
.size
.x
; i
++) {
236 for (let j
= 0; j
< V
.size
.y
; j
++) {
237 if (this.board
[i
][j
] != V
.EMPTY
) {
238 const sign
= this.getColor(i
, j
) == "w" ? 1 : -1;
239 const piece
= this.getPiece(i
, j
);
240 evaluation
+= sign
* V
.VALUES
[piece
];
241 const symbol
= this.board
[i
][j
][1];
242 if (V
.AUGMENTED_PIECES
.includes(symbol
)) {
243 const extraPiece
= this.getExtraPiece(symbol
);
244 evaluation
+= sign
* V
.VALUES
[extraPiece
]
254 move.appear
[0].x
!= move.vanish
[0].x
||
255 move.appear
[0].y
!= move.vanish
[0].y
258 V
.AUGMENTED_PIECES
.includes(move.vanish
[0].p
) ||
260 move.appear
.length
>= 2 &&
261 move.vanish
.length
>= 2 &&
262 V
.AUGMENTED_PIECES
.includes(move.vanish
[1].p
)
265 // Simplify move before calling super.getNotation()
266 let smove
= JSON
.parse(JSON
.stringify(move));
267 if (ChessRules
.PIECES
.includes(move.vanish
[0].p
)) {
268 // Castle with an augmented rook
270 smove
.vanish
[1].p
= smove
.appear
[1].p
;
273 // Moving an augmented piece
275 smove
.vanish
[0].p
= smove
.appear
[0].p
;
277 smove
.vanish
.length
== 2 &&
278 smove
.vanish
[0].c
== smove
.vanish
[1].c
&&
279 V
.AUGMENTED_PIECES
.includes(move.vanish
[1].p
)
281 // Castle with an augmented rook
283 smove
.vanish
[1].p
= smove
.appear
[1].p
;
286 return super.getNotation(smove
);
288 // Else, more common case:
289 return super.getNotation(move);
291 // First moves in game, placements:
292 const square
= V
.CoordsToSquare(move.appear
[0]);
294 (['a','j','m','s','u'].includes(move.appear
[0].p
) ? 'N' : 'B');
295 return '+' + reserve
+ '@' + square
;