1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
} from "@/utils/alea";
5 export class AlapoRules
extends ChessRules
{
7 static get HasFlags() {
11 static get HasEnpassant() {
23 return [V
.ROOK
, V
.BISHOP
, V
.QUEEN
, V
.ROOK_S
, V
.BISHOP_S
, V
.QUEEN_S
];
29 static get BISHOP_S() {
32 static get QUEEN_S() {
36 getPotentialMinirookMoves(sq
) {
37 return super.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
], 1);
39 getPotentialMinibishopMoves(sq
) {
40 return super.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
], 1);
42 getPotentialMiniqueenMoves(sq
) {
43 return super.getSlideNJumpMoves(
44 sq
, V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]), 1);
47 getPotentialMovesFrom(sq
) {
48 switch (this.getPiece(sq
[0], sq
[1])) {
49 case V
.ROOK: return super.getPotentialRookMoves(sq
);
50 case V
.BISHOP: return super.getPotentialBishopMoves(sq
);
51 case V
.QUEEN: return super.getPotentialQueenMoves(sq
);
52 case V
.ROOK_S: return this.getPotentialMinirookMoves(sq
);
53 case V
.BISHOP_S: return this.getPotentialMinibishopMoves(sq
);
54 case V
.QUEEN_S: return this.getPotentialMiniqueenMoves(sq
);
60 return { x: 6, y: 6 };
63 getPpath(b
, color
, score
, orientation
) {
64 // 'i' for "inversed":
65 const suffix
= (b
[0] == orientation
? "" : "i");
66 return "Alapo/" + b
+ suffix
;
69 static GenRandInitFen(options
) {
70 if (options
.randomness
== 0)
71 return "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0";
79 let pieces
= { w: new Array(6), b: new Array(6) };
80 // Shuffle pieces on first (and last rank if randomness == 2)
81 for (let c
of ["w", "b"]) {
82 if (c
== 'b' && options
.randomness
== 1) {
83 pieces
['b'] = pieces
['w'];
87 let positions
= ArrayFun
.range(6);
89 // Get random squares for bishops
90 let randIndex
= 2 * randInt(3);
91 const bishop1Pos
= positions
[randIndex
];
92 let randIndex_tmp
= 2 * randInt(3) + 1;
93 const bishop2Pos
= positions
[randIndex_tmp
];
94 positions
.splice(Math
.max(randIndex
, randIndex_tmp
), 1);
95 positions
.splice(Math
.min(randIndex
, randIndex_tmp
), 1);
97 // Get random square for queens
98 randIndex
= randInt(4);
99 const queen1Pos
= positions
[randIndex
];
100 positions
.splice(randIndex
, 1);
101 randIndex
= randInt(3);
102 const queen2Pos
= positions
[randIndex
];
103 positions
.splice(randIndex
, 1);
105 // Rooks positions are now fixed,
106 const rook1Pos
= positions
[0];
107 const rook2Pos
= positions
[1];
109 pieces
[c
][rook1Pos
] = "r";
110 pieces
[c
][bishop1Pos
] = "b";
111 pieces
[c
][queen1Pos
] = "q";
112 pieces
[c
][queen2Pos
] = "q";
113 pieces
[c
][bishop2Pos
] = "b";
114 pieces
[c
][rook2Pos
] = "r";
118 pieces
["b"].join("") + "/" +
119 pieces
["b"].map(p
=> piece2pawn
[p
]).join("") +
121 pieces
["w"].map(p
=> piece2pawn
[p
].toUpperCase()).join("") + "/" +
122 pieces
["w"].join("").toUpperCase() +
127 static IsGoodPosition(position
) {
128 if (position
.length
== 0) return false;
129 const rows
= position
.split("/");
130 if (rows
.length
!= V
.size
.x
) return false;
131 // Just check that at least one piece of each color is there:
132 let pieces
= { "w": 0, "b": 0 };
133 for (let row
of rows
) {
135 for (let i
= 0; i
< row
.length
; i
++) {
136 const lowerRi
= row
[i
].toLowerCase();
137 if (V
.PIECES
.includes(lowerRi
)) {
138 pieces
[row
[i
] == lowerRi
? "b" : "w"]++;
142 const num
= parseInt(row
[i
], 10);
143 if (isNaN(num
)) return false;
147 if (sumElts
!= V
.size
.y
) return false;
149 if (Object
.values(pieces
).some(v
=> v
== 0)) return false;
153 // Find possible captures by opponent on [x, y]
154 findCaptures([x
, y
]) {
155 const color
= this.getColor(x
, y
);
157 const steps
= V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]);
158 const oppCol
= V
.GetOppCol(color
);
159 for (let loop
= 0; loop
< steps
.length
; loop
++) {
160 const step
= steps
[loop
];
164 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
171 this.board
[i
][j
] != V
.EMPTY
&&
172 this.getColor(i
, j
) == oppCol
174 const oppPiece
= this.getPiece(i
, j
);
178 [V
.ROOK_S
, V
.BISHOP_S
, V
.QUEEN_S
].includes(oppPiece
)
182 [V
.BISHOP
, V
.BISHOP_S
].includes(oppPiece
) &&
183 step
.some(e
=> e
== 0)
187 [V
.ROOK
, V
.ROOK_S
].includes(oppPiece
) &&
188 step
.every(e
=> e
!= 0)
210 // Try both colors (to detect potential suicides)
211 for (let c
of ['w', 'b']) {
212 const oppCol
= V
.GetOppCol(c
);
213 const goal
= (c
== 'w' ? 0 : 5);
215 this.board
[goal
].some(
216 (b
,j
) => b
[0] == c
&& !this.findCaptures([goal
, j
])
219 return c
== 'w' ? "1-0" : "0-1";
222 return super.getCurrentScore();
225 static get VALUES() {