"Seirawan-Harper Chess": "Seirawan-Harper Chess",
"Shared pieces (v1)": "Shared pieces (v1)",
"Shared pieces (v2)": "Shared pieces (v2)",
+ "Shogi 5 x 5": "Shogi 5 x 5",
"Shoot pieces": "Shoot pieces",
"Squares disappear": "Squares disappear",
"Standard rules": "Standard rules",
"Seirawan-Harper Chess": "Ajedrez Seirawan-Harper",
"Shared pieces (v1)": "Piezas compartidas (v1)",
"Shared pieces (v2)": "Piezas compartidas (v2)",
+ "Shogi 5 x 5": "Shogi 5 x 5",
"Shoot pieces": "Tirar de las piezas",
"Squares disappear": "Las casillas desaparecen",
"Standard rules": "Reglas estandar",
"Seirawan-Harper Chess": "Échecs Seirawan-Harper",
"Shared pieces (v1)": "Pièces partagées (v1)",
"Shared pieces (v2)": "Pièces partagées (v2)",
+ "Shogi 5 x 5": "Shogi 5 x 5",
"Shoot pieces": "Tirez sur les pièces",
"Squares disappear": "Les cases disparaissent",
"Standard rules": "Règles usuelles",
--- /dev/null
+p.boxed Shogi on a 5 x 5 board.
+
+figure.diagram-container
+ .diagram
+ | fen:rbsgk/4p/5/P4/KGSBR:
+ figcaption Initial position.
+
+p.
+ Minishogi is essentially shogi on a 5x5 board. The game was invented
+ (or rediscovered) around 1970 by Shigenobu Kusumoto of Osaka, Japan.
+
+p
+ | The rules are the same as in
+ a(href="/variants/Shogi") Shogi
+ | . Unlike standard shogi, there is no knight or lance.
+ | Promotion is only done in the last rank.
+
+p
+ | See also
+ a(href="https://www.pychess.org/variant/minishogi") Minishogi
+ | on pychess-variants.
--- /dev/null
+p.boxed Shogi en un tablero 5 x 5.
+
+figure.diagram-container
+ .diagram
+ | fen:rbsgk/4p/5/P4/KGSBR:
+ figcaption Posición inicial.
+
+p.
+ Esta variante corresponde al Shogi en un tablero de ajedrez de 5x5.
+ Este juego fue inventado (o redescubierto) en 1970 por Shigenobu Kusumoto
+ de Osaka, Japón.
+
+p
+ | Las reglas son las mismas que en
+ a(href="/variants/Shogi") Shogi
+ | . A diferencia del Shogi estándar, no hay lanza ni caballo.
+ | Las promociones solo se realizan en la última fila.
+
+p
+ | Ver también
+ a(href="https://www.pychess.org/variant/minishogi") Minishogi
+ | & nbsp;en pychess-variants.
--- /dev/null
+p.boxed Shogi sur un plateau 5 x 5.
+
+figure.diagram-container
+ .diagram
+ | fen:rbsgk/4p/5/P4/KGSBR:
+ figcaption Position initiale.
+
+p.
+ Cette variante correspond au Shogi sur un échiquier 5x5.
+ Ce jeu a été inventé (ou redécouvert) en 1970 par Shigenobu Kusumoto
+ d'Osaka, Japon.
+
+p
+ | les règles sont les mêmes qu'au
+ a(href="/variants/Shogi") Shogi
+ | . Contrairement au Shogi standard, il n'y a ni lance ni cavalier.
+ | Les promotion ne s'effectuent que sur la dernière rangée.
+
+p
+ | Voir aussi
+ a(href="https://www.pychess.org/variant/minishogi") Minishogi
+ | sur pychess-variants.
--- /dev/null
+import { ChessRules } from "@/base_rules";
+import { ShogiRules } from "@/variants/Shogi";
+
+export class MinishogiRules extends ShogiRules {
+ static IsGoodFen(fen) {
+ if (!ChessRules.IsGoodFen(fen)) return false;
+ const fenParsed = V.ParseFen(fen);
+ // 3) Check reserves
+ if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{10,10}$/))
+ return false;
+ return true;
+ }
+
+ // No knight or lance
+ static get PIECES() {
+ return [
+ ChessRules.PAWN,
+ ChessRules.ROOK,
+ ChessRules.BISHOP,
+ ChessRules.KING,
+ V.GOLD_G,
+ V.SILVER_G,
+ V.P_PAWN,
+ V.P_SILVER,
+ V.P_ROOK,
+ V.P_BISHOP
+ ];
+ }
+
+ static GenRandInitFen() {
+ return "rbsgk/4p/5/P4/KGSBR w 0 0000000000";
+ }
+
+ getReserveFen() {
+ let counts = new Array(10);
+ for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+ counts[i] = this.reserve["w"][V.RESERVE_PIECES[i]];
+ counts[5 + i] = this.reserve["b"][V.RESERVE_PIECES[i]];
+ }
+ return counts.join("");
+ }
+
+ setOtherVariables(fen) {
+ super.setOtherVariables(fen);
+ const fenParsed = V.ParseFen(fen);
+ // Also init reserves (used by the interface to show landable pieces)
+ this.reserve = {
+ w: {
+ [V.PAWN]: parseInt(fenParsed.reserve[0]),
+ [V.ROOK]: parseInt(fenParsed.reserve[1]),
+ [V.BISHOP]: parseInt(fenParsed.reserve[2]),
+ [V.GOLD_G]: parseInt(fenParsed.reserve[3]),
+ [V.SILVER_G]: parseInt(fenParsed.reserve[4])
+ },
+ b: {
+ [V.PAWN]: parseInt(fenParsed.reserve[5]),
+ [V.ROOK]: parseInt(fenParsed.reserve[6]),
+ [V.BISHOP]: parseInt(fenParsed.reserve[7]),
+ [V.GOLD_G]: parseInt(fenParsed.reserve[8]),
+ [V.SILVER_G]: parseInt(fenParsed.reserve[9])
+ }
+ };
+ }
+
+ static get size() {
+ return { x: 5, y: 5 };
+ }
+
+ static get RESERVE_PIECES() {
+ return (
+ [V.PAWN, V.ROOK, V.BISHOP, V.GOLD_G, V.SILVER_G]
+ );
+ }
+
+ getReserveMoves([x, y]) {
+ const color = this.turn;
+ const p = V.RESERVE_PIECES[y];
+ if (p == V.PAWN) {
+ var oppCol = V.GetOppCol(color);
+ var allowedFiles =
+ [...Array(5).keys()].filter(j =>
+ [...Array(5).keys()].every(i => {
+ return (
+ this.board[i][j] == V.EMPTY ||
+ this.getColor(i, j) != color ||
+ this.getPiece(i, j) != V.PAWN
+ );
+ })
+ )
+ }
+ if (this.reserve[color][p] == 0) return [];
+ let moves = [];
+ const forward = color == 'w' ? -1 : 1;
+ const lastRank = color == 'w' ? 0 : 4;
+ for (let i = 0; i < V.size.x; i++) {
+ if (p == V.PAWN && i == lastRank) continue;
+ for (let j = 0; j < V.size.y; j++) {
+ if (
+ this.board[i][j] == V.EMPTY &&
+ (p != V.PAWN || allowedFiles.includes(j))
+ ) {
+ let mv = new Move({
+ appear: [
+ new PiPo({
+ x: i,
+ y: j,
+ c: color,
+ p: p
+ })
+ ],
+ vanish: [],
+ start: { x: x, y: y }, //a bit artificial...
+ end: { x: i, y: j }
+ });
+ if (p == V.PAWN) {
+ // Do not drop on checkmate:
+ this.play(mv);
+ const res = (this.underCheck(oppCol) && !this.atLeastOneMove());
+ this.undo(mv);
+ if (res) continue;
+ }
+ moves.push(mv);
+ }
+ }
+ }
+ return moves;
+ }
+
+ getSlideNJumpMoves([x, y], steps, options) {
+ options = options || {};
+ const color = this.turn;
+ const oneStep = options.oneStep;
+ const forcePromoteOnLastRank = options.force;
+ const promoteInto = options.promote;
+ const lastRank = (color == 'w' ? 0 : 4);
+ let moves = [];
+ outerLoop: for (let step of steps) {
+ let i = x + step[0];
+ let j = y + step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ if (i != lastRank || !forcePromoteOnLastRank)
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ if (i == lastRank && !!promoteInto) {
+ moves.push(
+ this.getBasicMove(
+ [x, y], [i, j], { c: color, p: promoteInto })
+ );
+ }
+ if (oneStep) continue outerLoop;
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j) && this.canTake([x, y], [i, j])) {
+ if (i != lastRank || !forcePromoteOnLastRank)
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ if (i == lastRank && !!promoteInto) {
+ moves.push(
+ this.getBasicMove(
+ [x, y], [i, j], { c: color, p: promoteInto })
+ );
+ }
+ }
+ }
+ return moves;
+ }
+
+ static get SEARCH_DEPTH() {
+ return 3;
+ }
+};
static get SILVER_G() {
return "s";
}
- static get LANCER() {
+ static get LANCE() {
return "l";
}
static get P_SILVER() {
return 't';
}
- static get P_LANCER() {
+ static get P_LANCE() {
return 'm';
}
static get P_ROOK() {
ChessRules.KING,
V.GOLD_G,
V.SILVER_G,
- V.LANCER,
+ V.LANCE,
V.P_PAWN,
V.P_KNIGHT,
V.P_SILVER,
- V.P_LANCER,
+ V.P_LANCE,
V.P_ROOK,
V.P_BISHOP
];
[V.GOLD_G]: parseInt(fenParsed.reserve[3]),
[V.SILVER_G]: parseInt(fenParsed.reserve[4]),
[V.KNIGHT]: parseInt(fenParsed.reserve[5]),
- [V.LANCER]: parseInt(fenParsed.reserve[6])
+ [V.LANCE]: parseInt(fenParsed.reserve[6])
},
b: {
[V.PAWN]: parseInt(fenParsed.reserve[7]),
[V.GOLD_G]: parseInt(fenParsed.reserve[10]),
[V.SILVER_G]: parseInt(fenParsed.reserve[11]),
[V.KNIGHT]: parseInt(fenParsed.reserve[12]),
- [V.LANCER]: parseInt(fenParsed.reserve[13])
+ [V.LANCE]: parseInt(fenParsed.reserve[13])
}
};
}
// Ordering on reserve pieces
static get RESERVE_PIECES() {
return (
- [V.PAWN, V.ROOK, V.BISHOP, V.GOLD_G, V.SILVER_G, V.KNIGHT, V.LANCER]
+ [V.PAWN, V.ROOK, V.BISHOP, V.GOLD_G, V.SILVER_G, V.KNIGHT, V.LANCE]
);
}
const lastRanks = color == 'w' ? [0, 1] : [8, 7];
for (let i = 0; i < V.size.x; i++) {
if (
- (i == lastRanks[0] && [V.PAWN, V.KNIGHT, V.LANCER].includes(p)) ||
+ (i == lastRanks[0] && [V.PAWN, V.KNIGHT, V.LANCE].includes(p)) ||
(i == lastRanks[1] && p == V.KNIGHT)
) {
continue;
return this.getPotentialBishopMoves([x, y]);
case V.SILVER_G:
return this.getPotentialSilverMoves([x, y]);
- case V.LANCER:
- return this.getPotentialLancerMoves([x, y]);
+ case V.LANCE:
+ return this.getPotentialLanceMoves([x, y]);
case V.KING:
return this.getPotentialKingMoves([x, y]);
case V.P_ROOK:
case V.P_PAWN:
case V.P_SILVER:
case V.P_KNIGHT:
- case V.P_LANCER:
+ case V.P_LANCE:
return this.getPotentialGoldMoves([x, y]);
}
return []; //never reached
sq, V.steps[V.BISHOP], { promote: V.P_BISHOP });
}
- getPotentialLancerMoves(sq) {
+ getPotentialLanceMoves(sq) {
const forward = (this.turn == 'w' ? -1 : 1);
return this.getSlideNJumpMoves(
- sq, [[forward, 0]], { promote: V.P_LANCER });
+ sq, [[forward, 0]], { promote: V.P_LANCE });
}
getPotentialDragonMoves(sq) {
this.isAttackedByKnight(sq, color) ||
this.isAttackedByBishop(sq, color) ||
this.isAttackedByHorse(sq, color) ||
- this.isAttackedByLancer(sq, color) ||
+ this.isAttackedByLance(sq, color) ||
this.isAttackedBySilver(sq, color) ||
this.isAttackedByGold(sq, color) ||
this.isAttackedByKing(sq, color)
V.OnBoard(i, j) &&
this.board[i][j] != V.EMPTY &&
this.getColor(i, j) == color &&
- [V.GOLD_G, V.P_PAWN, V.P_SILVER, V.P_KNIGHT, V.P_LANCER]
+ [V.GOLD_G, V.P_PAWN, V.P_SILVER, V.P_KNIGHT, V.P_LANCE]
.includes(this.getPiece(i, j))
) {
return true;
sq, color, V.KNIGHT, [[forward, 1], [forward, -1]], "oneStep");
}
- isAttackedByLancer(sq, color) {
+ isAttackedByLance(sq, color) {
const forward = (color == 'w' ? 1 : -1);
- return this.isAttackedBySlideNJump(sq, color, V.LANCER, [[forward, 0]]);
+ return this.isAttackedBySlideNJump(sq, color, V.LANCE, [[forward, 0]]);
}
isAttackedByDragon(sq, color) {
('Magnetic', 'Laws of attraction'),
('Makruk', 'Thai Chess'),
('Maxima', 'Occupy the enemy palace'),
+ ('Minishogi', 'Shogi 5 x 5'),
('Monochrome', 'All of the same color'),
('Monster', 'White move twice'),
('Omega', 'A wizard in the corner'),