break;
}
}
- fillGameInfos(obj, playerColor == "w" ? 1 : 0);
- if (obj.randvar)
+ const playerIndex = (playerColor == "w" ? 0 : 1);
+ fillGameInfos(obj, 1 - playerIndex);
+ if (obj.players[playerIndex].randvar)
toggleVisible("gameInfos");
else
toggleVisible("boardContainer");
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:ns1="http://sozi.baierouge.fr"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ id="svg12417"
+ sodipodi:docname="target.svg"
+ viewBox="0 0 200.13 200.02"
+ version="1.1"
+ inkscape:version="0.48+devel r10958"
+ >
+ <title
+ id="title825"
+ >Target</title
+ >
+ <sodipodi:namedview
+ id="base"
+ fit-margin-left="10"
+ inkscape:zoom="1"
+ height="0px"
+ borderopacity="1.0"
+ inkscape:current-layer="layer1"
+ inkscape:cx="89.904323"
+ inkscape:cy="99.565238"
+ fit-margin-right="10"
+ inkscape:window-maximized="1"
+ showgrid="false"
+ width="0px"
+ inkscape:guide-bbox="true"
+ showguides="true"
+ bordercolor="#666666"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ fit-margin-bottom="10"
+ inkscape:window-width="1280"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ pagecolor="#ffffff"
+ inkscape:document-units="px"
+ inkscape:window-height="962"
+ fit-margin-top="10"
+ />
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ transform="translate(-248.44 -442.39)"
+ >
+ <g
+ id="g818"
+ transform="translate(-.96350 -1.0044)"
+ >
+ <path
+ id="path12427-9-3-9"
+ sodipodi:rx="180.62735"
+ sodipodi:ry="180.62735"
+ style="color:#000000;stroke:#000000;stroke-width:24.084;fill:none"
+ sodipodi:type="arc"
+ d="m531.77 557.68c0 99.758-80.87 180.63-180.63 180.63-99.758 0-180.63-80.87-180.63-180.63 0-99.758 80.87-180.63 180.63-180.63 99.758 0 180.63 80.87 180.63 180.63z"
+ transform="matrix(.41522 0 0 .41522 203.67 311.84)"
+ sodipodi:cy="557.68408"
+ sodipodi:cx="351.13956"
+ />
+ <path
+ id="path12427-9-3-9-8-5"
+ sodipodi:rx="180.62735"
+ sodipodi:ry="180.62735"
+ style="color:#000000;stroke:#000000;stroke-width:40.139;fill:none"
+ sodipodi:type="arc"
+ d="m531.77 557.68c0 99.758-80.87 180.63-180.63 180.63-99.758 0-180.63-80.87-180.63-180.63 0-99.758 80.87-180.63 180.63-180.63 99.758 0 180.63 80.87 180.63 180.63z"
+ transform="matrix(.24913 0 0 .24913 261.99 404.46)"
+ sodipodi:cy="557.68408"
+ sodipodi:cx="351.13956"
+ />
+ <path
+ id="path12427-9-3-9-8-2-3"
+ sodipodi:rx="180.62735"
+ sodipodi:ry="180.62735"
+ style="color:#000000;fill:#000000"
+ sodipodi:type="arc"
+ d="m531.77 557.68c0 99.758-80.87 180.63-180.63 180.63-99.758 0-180.63-80.87-180.63-180.63 0-99.758 80.87-180.63 180.63-180.63 99.758 0 180.63 80.87 180.63 180.63z"
+ transform="matrix(.12121 0 0 .12121 306.91 475.8)"
+ sodipodi:cy="557.68408"
+ sodipodi:cx="351.13956"
+ />
+ <path
+ id="path13189-0"
+ d="m349.48 455.93v174.95"
+ style="stroke:#000000;stroke-linecap:round;stroke-width:5;fill:none"
+ inkscape:connector-curvature="0"
+ />
+ <path
+ id="path45"
+ style="stroke:#000000;stroke-linecap:round;stroke-width:5;fill:none"
+ inkscape:connector-curvature="0"
+ d="m436.98 543.41h-174.95"
+ />
+ </g
+ >
+ </g
+ >
+ <metadata
+ >
+ <rdf:RDF
+ >
+ <cc:Work
+ >
+ <dc:format
+ >image/svg+xml</dc:format
+ >
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+ />
+ <dc:publisher
+ >
+ <cc:Agent
+ rdf:about="http://openclipart.org/"
+ >
+ <dc:title
+ >Openclipart</dc:title
+ >
+ </cc:Agent
+ >
+ </dc:publisher
+ >
+ <dc:title
+ >Target</dc:title
+ >
+ <dc:date
+ >2012-02-15T07:37:04</dc:date
+ >
+ <dc:description
+ >Target symbol</dc:description
+ >
+ <dc:source
+ >https://openclipart.org/detail/168253/target-by-fanda@cz</dc:source
+ >
+ <dc:creator
+ >
+ <cc:Agent
+ >
+ <dc:title
+ >Fanda@CZ</dc:title
+ >
+ </cc:Agent
+ >
+ </dc:creator
+ >
+ <dc:subject
+ >
+ <rdf:Bag
+ >
+ <rdf:li
+ >target</rdf:li
+ >
+ </rdf:Bag
+ >
+ </dc:subject
+ >
+ </cc:Work
+ >
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/"
+ >
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction"
+ />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution"
+ />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+ />
+ </cc:License
+ >
+ </rdf:RDF
+ >
+ </metadata
+ >
+</svg
+>
function launchGame(gid) {
moveHash[gid] = {};
const gameInfo = Object.assign(
- {seed: Math.floor(Math.random() * 1984), gid: gid},
+ {seed: Math.floor(Math.random() * 19840), gid: gid},
games[gid]
);
// players array is supposed to be full:
- for (const p of games[gid].players) {
- send(p.sid,
- "gamestart",
- Object.assign({randvar: p.randvar}, gameInfo));
- }
+ for (const p of games[gid].players)
+ send(p.sid, "gamestart", gameInfo);
}
function getRandomVariant() {
const allrand = games[obj.gid].rematch.every(r => r == 2);
if (allrand)
vname = getRandomVariant();
- games[obj.gid].players.forEach(p =>
- p.randvar = allrand ? true : false);
+ games[obj.gid].players.forEach(p => p.randvar = allrand);
const gid = initializeGame(vname,
- games[obj.gid].players.reverse(),
- games[obj.gid].options);
+ games[obj.gid].players.reverse(),
+ games[obj.gid].options);
launchGame(gid);
}
}
// {name: 'Alice', desc: 'Both sides of the mirror'},
// {name: 'Align4', desc: 'Align four pawns'},
// {name: 'Allmate', desc: 'Mate any piece'},
-// {name: 'Ambiguous', desc: "Play opponent's pieces"},
+ {name: 'Ambiguous', desc: "Play opponent's pieces"},
// {name: 'Antiking1', desc: 'Keep antiking in check', disp: 'Anti-King'},
// {name: 'Antimatter', desc: 'Dangerous collisions'},
// {name: 'Apocalypse', desc: 'The end of the world'},
import ChessRules from "/base_rules.js";
-import { randInt, shuffle } from "@/utils/alea";
-import { ArrayFun } from "@/utils/array";
+import GiveawayRules from "/variants/Giveaway/class.js";
export default class AmbiguousRules extends ChessRules {
- // TODO: options
+ static get Options() {
+ return {
+ select: C.Options.select,
+ styles: ["cylinder"]
+ };
+ }
get hasFlags() {
return false;
}
genRandInitFen(seed) {
- const gr = new GiveawayRules(
- {mode: "suicide", options: this.options, genFenOnly: true});
+ const options = Object.assign({mode: "suicide"}, this.options);
+ const gr = new GiveawayRules({options: options, genFenOnly: true});
return gr.genRandInitFen(seed);
}
+ canStepOver(x, y) {
+ return this.board[x][y] == "" || this.getPiece(x, y) == V.GOAL;
+ }
+
// Subturn 1: play a move for the opponent on the designated square.
// Subturn 2: play a move for me (which just indicate a square).
getPotentialMovesFrom([x, y]) {
const color = this.turn;
- const oppCol = V.GetOppCol(color);
+ const oppCol = C.GetOppCol(color);
if (this.subTurn == 2) {
// Just play a normal move (which in fact only indicate a square)
let movesHash = {};
return (
super.getPotentialMovesFrom([x, y])
.filter(m => {
- // Filter promotions: keep only one, since no choice now.
+ // Filter promotions: keep only one, since no choice for now.
if (m.appear[0].p != m.vanish[0].p) {
- const hash = V.CoordsToSquare(m.start) + V.CoordsToSquare(m.end);
+ const hash = C.CoordsToSquare(m.start) + C.CoordsToSquare(m.end);
if (!movesHash[hash]) {
movesHash[hash] = true;
return true;
return true;
})
.map(m => {
- if (m.vanish.length == 1) m.appear[0].p = V.GOAL;
- else m.appear[0].p = V.TARGET_CODE[m.vanish[1].p];
- m.appear[0].c = oppCol;
+ if (m.vanish.length == 1) {
+ m.appear[0].c = 'a'; //a-color
+ m.appear[0].p = V.GOAL;
+ }
+ else {
+ m.appear[0].p = V.TARGET_CODE[m.vanish[1].p];
+ m.appear[0].c = oppCol;
+ }
m.vanish.shift();
return m;
})
);
}
- // At subTurn == 1, play a targeted move for opponent
+ // At subTurn == 1, play a targeted move for the opponent.
// Search for target (we could also have it in a stack...)
- let target = { x: -1, y: -1 };
- outerLoop: for (let i = 0; i < V.size.x; i++) {
- for (let j = 0; j < V.size.y; j++) {
- if (this.board[i][j] != V.EMPTY) {
- const piece = this.board[i][j][1];
+ let target = {x: -1, y: -1};
+ outerLoop: for (let i = 0; i < this.size.x; i++) {
+ for (let j = 0; j < this.size.y; j++) {
+ if (this.board[i][j] != "") {
+ const piece = this.getPiece(i, j);
if (
piece == V.GOAL ||
Object.keys(V.TARGET_DECODE).includes(piece)
) {
- target = { x: i, y: j};
+ target = {x: i, y:j};
break outerLoop;
}
}
}
}
- // TODO: could be more efficient than generating all moves.
- this.turn = oppCol;
- const emptyTarget = (this.board[target.x][target.y][1] == V.GOAL);
- if (emptyTarget) this.board[target.x][target.y] = V.EMPTY;
- let moves = super.getPotentialMovesFrom([x, y]);
- if (emptyTarget) {
- this.board[target.x][target.y] = color + V.GOAL;
- moves.forEach(m => {
- m.vanish.push({
- x: target.x,
- y: target.y,
- c: color,
- p: V.GOAL
- });
- });
- }
- this.turn = color;
+ const moves = super.getPotentialMovesFrom([x, y], oppCol);
return moves.filter(m => m.end.x == target.x && m.end.y == target.y);
}
};
}
- pieces() {
- // .........
+ pieces(color, x, y) {
+ const targets = {
+ 's': {"class": "target-pawn", moves: []},
+ 'u': {"class": "target-rook", moves: []},
+ 'o': {"class": "target-knight", moves: []},
+ 'c': {"class": "target-bishop", moves: []},
+ 't': {"class": "target-queen", moves: []},
+ 'l': {"class": "target-king", moves: []}
+ };
+ return Object.assign(
+ { 'g': {"class": "target"} }, targets, super.pieces(color, x, y));
}
atLeastOneMove() {
return moves;
}
+ isKing(symbol) {
+ return ['k', 'l'].includes(symbol);
+ }
+
getCurrentScore() {
// This function is only called at subTurn 1
- const color = V.GetOppCol(this.turn);
- if (this.kingPos[color][0] < 0) return (color == 'w' ? "0-1" : "1-0");
+ const color = C.GetOppCol(this.turn);
+ const kingPos = this.searchKingPos(color);
+ if (kingPos[0] < 0)
+ return (color == 'w' ? "0-1" : "1-0");
return "*";
}
- play(move) {
- let kingCaptured = false;
- if (this.subTurn == 1) {
- this.prePlay(move);
- this.epSquares.push(this.getEpSquare(move));
- kingCaptured = this.kingPos[this.turn][0] < 0;
- }
- if (kingCaptured) move.kingCaptured = true;
- V.PlayOnBoard(this.board, move);
- if (this.subTurn == 2 || kingCaptured) {
- this.turn = V.GetOppCol(this.turn);
+ postPlay(move) {
+ const color = this.turn;
+ if (this.subTurn == 2 || this.searchKingPos(color)[0] < 0) {
+ this.turn = C.GetOppCol(color);
this.movesCount++;
}
- if (!kingCaptured) this.subTurn = 3 - this.subTurn;
+ this.subTurn = 3 - this.subTurn;
}
};
--- /dev/null
+<p>
+ Every move you play can be changed by your opponent by a move arriving
+ on the same square.
+</p>
+
+<p>
+ Consequently, you play twice on each turn: first to select a move for
+ your opponent, then to choose one for you - which could be altered.
+</p>
+
+<p class="author">Fabrice Liardet (2005).</p>
--- /dev/null
+@import url("/base_pieces.css");
+
+piece.target {
+ background-image: url('/pieces/ambiguous_target.svg');
+}
+
+piece.white.target-pawn {
+ background-image: url('/pieces/yellow_pawn.svg');
+}
+piece.white.target-rook {
+ background-image: url('/pieces/yellow_rook.svg');
+}
+piece.white.target-knight {
+ background-image: url('/pieces/yellow_knight.svg');
+}
+piece.white.target-bishop {
+ background-image: url('/pieces/yellow_bishop.svg');
+}
+piece.white.target-queen {
+ background-image: url('/pieces/yellow_queen.svg');
+}
+piece.white.target-king {
+ background-image: url('/pieces/yellow_king.svg');
+}
+
+piece.black.target-pawn {
+ background-image: url('/pieces/red_pawn.svg');
+}
+piece.black.target-rook {
+ background-image: url('/pieces/red_rook.svg');
+}
+piece.black.target-knight {
+ background-image: url('/pieces/red_knight.svg');
+}
+piece.black.target-bishop {
+ background-image: url('/pieces/red_bishop.svg');
+}
+piece.black.target-queen {
+ background-image: url('/pieces/red_queen.svg');
+}
+piece.black.target-king {
+ background-image: url('/pieces/red_king.svg');
+}
}
genRandInitFen(seed) {
- const gr = new GiveawayRules(
- {mode: "suicide", options: this.options, genFenOnly: true});
+ const options = Object.assign({mode: "suicide"}, this.options);
+ const gr = new GiveawayRules({options: options, genFenOnly: true});
// Add Peach + mario flags
return gr.genRandInitFen(seed).slice(0, -17) + '{"flags":"1111"}';
}
this.moveStack = [];
// Change seed (after FEN generation!!)
// so that further calls differ between players:
- Random.setSeed(Math.floor(10000 * Math.random()));
+ Random.setSeed(Math.floor(19840 * Math.random()));
}
// For Toadette bonus
}
genRandInitFen(seed) {
- const gr = new GiveawayRules(
- {mode: "suicide", options: this.options, genFenOnly: true});
+ const options = Object.assign({mode: "suicide"}, this.options);
+ const gr = new GiveawayRules({options: options, genFenOnly: true});
// Add empty cmove:
return (
gr.genRandInitFen(seed).slice(0, -17) + '{"enpassant":"-","cmove":"-"}');