56fa15a382639c2b9361d390dc1aa99096b9a829
1 class CheckeredRules
extends ChessRules
6 return b
[0]=='c' ? "Checkered/"+b : b
;
10 const checkered_codes
= {
18 return checkered_codes
[b
[1]];
19 return ChessRules
.board2fen(b
);
23 const checkered_pieces
= {
30 if (Object
.keys(checkered_pieces
).includes(f
))
31 return 'c'+checkered_pieces
[f
];
32 return ChessRules
.fen2board(f
);
37 super.setFlags(fen
); //castleFlags
40 "w": new Array(8), //pawns can move 2 squares?
43 const flags
= fen
.split(" ")[1].substr(4); //skip first 4 digits, for castle
44 for (let c
of ['w','b'])
46 for (let i
=0; i
<8; i
++)
47 this.pawnFlags
[c
][i
] = (flags
.charAt((c
=='w'?0:8)+i
) == '1');
51 // Aggregates flags into one object
53 return [this.castleFlags
, this.pawnFlags
];
59 this.castleFlags
= flags
[0];
60 this.pawnFlags
= flags
[1];
63 canTake([x1
,y1
], [x2
,y2
])
65 const color1
= this.getColor(x1
,y1
);
66 const color2
= this.getColor(x2
,y2
);
67 // Checkered aren't captured
68 return color1
!= color2
&& color2
!= 'c' && (color1
!= 'c' || color2
!= this.turn
);
71 // Post-processing: apply "checkerization" of standard moves
72 getPotentialMovesFrom([x
,y
])
74 let standardMoves
= super.getPotentialMovesFrom([x
,y
]);
75 const lastRank
= this.turn
== "w" ? 0 : 7;
76 if (this.getPiece(x
,y
) == VariantRules
.KING
)
77 return standardMoves
; //king has to be treated differently (for castles)
79 standardMoves
.forEach(m
=> {
80 if (m
.vanish
[0].p
== VariantRules
.PAWN
&& Math
.abs(m
.end
.x
-m
.start
.x
)==2
81 && !this.pawnFlags
[this.turn
][m
.start
.y
])
83 return; //skip forbidden 2-squares jumps
85 if (m
.vanish
.length
== 1)
86 moves
.push(m
); //no capture
89 // A capture occured (m.vanish.length == 2)
92 if (m
.appear
[0].p
!= m
.vanish
[1].p
//avoid promotions:
93 && (m
.vanish
[0].p
!= VariantRules
.PAWN
|| m
.end
.x
!= lastRank
))
95 // Add transformation into captured piece
96 let m2
= JSON
.parse(JSON
.stringify(m
));
97 m2
.appear
[0].p
= m
.vanish
[1].p
;
105 canIplay(side
, [x
,y
])
107 return ((side
=='w' && this.moves
.length
%2==0) || (side
=='b' && this.moves
.length
%2==1))
108 && [side
,'c'].includes(this.getColor(x
,y
));
111 // Does m2 un-do m1 ? (to disallow undoing checkered moves)
112 oppositeMoves(m1
, m2
)
114 return m1
.appear
.length
== 1 && m2
.appear
.length
== 1
115 && m1
.vanish
.length
== 1 && m2
.vanish
.length
== 1
116 && m1
.start
.x
== m2
.end
.x
&& m1
.end
.x
== m2
.start
.x
117 && m1
.start
.y
== m2
.end
.y
&& m1
.end
.y
== m2
.start
.y
118 && m1
.appear
[0].c
== m2
.vanish
[0].c
&& m1
.appear
[0].p
== m2
.vanish
[0].p
119 && m1
.vanish
[0].c
== m2
.appear
[0].c
&& m1
.vanish
[0].p
== m2
.appear
[0].p
;
124 if (moves
.length
== 0)
126 const color
= this.turn
;
127 return moves
.filter(m
=> {
128 const L
= this.moves
.length
;
129 if (L
> 0 && this.oppositeMoves(this.moves
[L
-1], m
))
131 return !this.underCheck(m
);
135 isAttackedByPawn([x
,y
], colors
)
137 for (let c
of colors
)
139 const color
= (c
=="c" ? this.turn : c
);
140 let pawnShift
= (color
=="w" ? 1 : -1);
141 if (x
+pawnShift
>=0 && x
+pawnShift
<8)
143 for (let i
of [-1,1])
145 if (y
+i
>=0 && y
+i
<8 && this.getPiece(x
+pawnShift
,y
+i
)==VariantRules
.PAWN
146 && this.getColor(x
+pawnShift
,y
+i
)==c
)
158 const color
= this.turn
;
160 let res
= this.isAttacked(this.kingPos
[color
], [this.getOppCol(color
),'c']);
165 getCheckSquares(move)
168 const color
= this.turn
;
169 this.moves
.push(move); //artifically change turn, for checkered pawns (TODO)
170 const kingAttacked
= this.isAttacked(this.kingPos
[color
], [this.getOppCol(color
),'c']);
171 let res
= kingAttacked
172 ? [ JSON
.parse(JSON
.stringify(this.kingPos
[color
])) ] //need to duplicate!
179 updateVariables(move)
181 const c
= this.getColor(move.start
.x
,move.start
.y
);
182 if (c
!= 'c') //checkered not concerned by castle flags
183 super.updateVariables(move);
185 // Does it turn off a 2-squares pawn flag?
186 const secondRank
= [1,6];
187 if (secondRank
.includes(move.start
.x
) && move.vanish
[0].p
== VariantRules
.PAWN
)
188 this.pawnFlags
[move.start
.x
==6 ? "w" : "b"][move.start
.y
] = false;
193 const color
= this.turn
;
194 if (!this.isAttacked(this.kingPos
[color
], this.getOppCol(color
))
195 && !this.isAttacked(this.kingPos
[color
], 'c'))
200 return color
== "w" ? "0-1" : "1-0";
205 const [sizeX
,sizeY
] = VariantRules
.size
;
207 //Just count material for now, considering checkered neutral (...)
208 for (let i
=0; i
<sizeX
; i
++)
210 for (let j
=0; j
<sizeY
; j
++)
212 if (this.board
[i
][j
] != VariantRules
.EMPTY
)
214 const sqColor
= this.getColor(i
,j
);
215 const sign
= sqColor
== "w" ? 1 : (sqColor
=="b" ? -1 : 0);
216 evaluation
+= sign
* VariantRules
.VALUES
[this.getPiece(i
,j
)];
223 static GenRandInitFen()
225 return ChessRules
.GenRandInitFen() + "1111111111111111"; //add 16 pawns flags
230 let fen
= super.getFlagsFen();
232 for (let c
of ['w','b'])
234 for (let i
=0; i
<8; i
++)
235 fen
+= this.pawnFlags
[c
][i
] ? '1' : '0';
242 if (move.appear
.length
== 2)
245 if (move.end
.y
< move.start
.y
)
251 // Translate final square
253 String
.fromCharCode(97 + move.end
.y
) + (VariantRules
.size
[0]-move.end
.x
);
255 let piece
= this.getPiece(move.start
.x
, move.start
.y
);
256 if (piece
== VariantRules
.PAWN
)
260 if (move.vanish
.length
> 1)
263 let startColumn
= String
.fromCharCode(97 + move.start
.y
);
264 notation
= startColumn
+ "x" + finalSquare
+ "=" + move.appear
[0].p
.toUpperCase();
267 notation
= finalSquare
;
268 if (move.appear
.length
> 0 && piece
!= move.appear
[0].p
) //promotion
269 notation
+= "=" + move.appear
[0].p
.toUpperCase();
276 return piece
.toUpperCase() + (move.vanish
.length
> 1 ? "x" : "") + finalSquare
277 + (move.vanish
.length
> 1 ? "=" + move.appear
[0].p
.toUpperCase() : "");