1 import { ChessRules
, PiPo
} from "@/base_rules";
3 export const VariantRules
= class MagneticRules
extends ChessRules
5 static get HasEnpassant() { return false; }
7 getPotentialMovesFrom([x
,y
])
9 let standardMoves
= super.getPotentialMovesFrom([x
,y
]);
11 standardMoves
.forEach(m
=> {
12 let newMove_s
= this.applyMagneticLaws(m
);
13 if (newMove_s
.length
== 1)
14 moves
.push(newMove_s
[0]);
16 moves
= moves
.concat(newMove_s
);
21 // Complete a move with magnetic actions
22 // TODO: job is done multiple times for (normal) promotions.
23 applyMagneticLaws(move)
25 if (move.appear
[0].p
== V
.KING
&& move.appear
.length
==1)
26 return [move]; //kings are not charged
27 const aIdx
= (move.appear
[0].p
!= V
.KING
? 0 : 1); //if castling, rook is charged
28 const [x
,y
] = [move.appear
[aIdx
].x
, move.appear
[aIdx
].y
];
29 const color
= this.turn
;
30 const lastRank
= (color
=="w" ? 0 : 7);
31 const standardMove
= JSON
.parse(JSON
.stringify(move));
32 this.play(standardMove
);
33 for (let step
of [[-1,0],[1,0],[0,-1],[0,1]])
35 let [i
,j
] = [x
+step
[0],y
+step
[1]];
36 while (V
.OnBoard(i
,j
))
38 if (this.board
[i
][j
] != V
.EMPTY
)
40 // Found something. Same color or not?
41 if (this.getColor(i
,j
) != color
)
44 if ((Math
.abs(i
-x
)>=2 || Math
.abs(j
-y
)>=2) && this.getPiece(i
,j
) != V
.KING
)
67 if (this.getPiece(i
,j
) != V
.KING
)
69 // Push it until we meet an obstacle or edge of the board
70 let [ii
,jj
] = [i
+step
[0],j
+step
[1]];
71 while (V
.OnBoard(ii
,jj
))
73 if (this.board
[ii
][jj
] != V
.EMPTY
)
80 if (Math
.abs(ii
-i
)>=1 || Math
.abs(jj
-j
)>=1)
107 this.undo(standardMove
);
109 // Scan move for pawn (max 1) on 8th rank
110 for (let i
=1; i
<move.appear
.length
; i
++)
112 if (move.appear
[i
].p
==V
.PAWN
&& move.appear
[i
].c
==color
113 && move.appear
[i
].x
==lastRank
)
115 move.appear
[i
].p
= V
.ROOK
;
117 for (let piece
of [V
.KNIGHT
, V
.BISHOP
, V
.QUEEN
])
119 let cmove
= JSON
.parse(JSON
.stringify(move));
120 cmove
.appear
[i
].p
= piece
;
123 // Swap appear[i] and appear[0] for moves presentation (TODO: this is awkward)
125 let tmp
= m
.appear
[0];
126 m
.appear
[0] = m
.appear
[i
];
132 if (moves
.length
== 0) //no pawn on 8th rank
139 if (this.kingPos
[this.turn
][0] < 0)
141 return true; //TODO: is it right?
146 return false; //there is no check
149 getCheckSquares(move)
154 updateVariables(move)
156 super.updateVariables(move);
157 const c
= move.vanish
[0].c
;
158 if (move.vanish
.length
>= 2 && move.vanish
[1].p
== V
.KING
)
160 // We took opponent king !
161 const oppCol
= V
.GetOppCol(c
);
162 this.kingPos
[oppCol
] = [-1,-1];
163 this.castleFlags
[oppCol
] = [false,false];
165 // Did we magnetically move our (init) rooks or opponents' ones ?
166 const firstRank
= (c
== "w" ? 7 : 0);
167 const oppFirstRank
= 7 - firstRank
;
168 const oppCol
= V
.GetOppCol(c
);
169 move.vanish
.forEach(psq
=> {
170 if (psq
.x
== firstRank
&& this.INIT_COL_ROOK
[c
].includes(psq
.y
))
171 this.castleFlags
[c
][psq
.y
==this.INIT_COL_ROOK
[c
][0] ? 0 : 1] = false;
172 else if (psq
.x
== oppFirstRank
&& this.INIT_COL_ROOK
[oppCol
].includes(psq
.y
))
173 this.castleFlags
[oppCol
][psq
.y
==this.INIT_COL_ROOK
[oppCol
][0] ? 0 : 1] = false;
177 unupdateVariables(move)
179 super.unupdateVariables(move);
180 const c
= move.vanish
[0].c
;
181 const oppCol
= V
.GetOppCol(c
);
182 if (this.kingPos
[oppCol
][0] < 0)
184 // Last move took opponent's king
185 for (let psq
of move.vanish
)
189 this.kingPos
[oppCol
] = [psq
.x
, psq
.y
];
198 const color
= this.turn
;
199 const kp
= this.kingPos
[color
];
200 if (kp
[0] < 0) //king disappeared
201 return (color
== "w" ? "0-1" : "1-0");
202 if (this.atLeastOneMove()) // game not over
204 return "1/2"; //no moves but kings still there
207 static get THRESHOLD_MATE()
209 return 500; //checkmates evals may be slightly below 1000