/////////////////
// INITIALIZATION
- // fen == "position flags"
+ // fen == "position [flags [turn]]"
constructor(fen, moves)
{
this.moves = moves;
return pieces["b"].join("") +
"/pppppppp/8/8/8/8/PPPPPPPP/" +
pieces["w"].join("").toUpperCase() +
- " 1111"; //add flags
+ " 1111 w"; //add flags + turn
}
// Return current fen according to pieces+colors state
// The score is already computed when calling this function
getPGN(mycolor, score, fenStart, mode)
{
- const zeroPad = x => { return (x<10 ? "0" : "") + x; };
let pgn = "";
pgn += '[Site "vchess.club"]<br>';
- const d = new Date();
const opponent = mode=="human" ? "Anonymous" : "Computer";
pgn += '[Variant "' + variant + '"]<br>';
- pgn += '[Date "' + d.getFullYear() + '-' + (d.getMonth()+1) +
- '-' + zeroPad(d.getDate()) + '"]<br>';
+ pgn += '[Date "' + getDate(new Date()) + '"]<br>';
pgn += '[White "' + (mycolor=='w'?'Myself':opponent) + '"]<br>';
pgn += '[Black "' + (mycolor=='b'?'Myself':opponent) + '"]<br>';
pgn += '[FenStart "' + fenStart + '"]<br>';
// Game logic on a variant page
Vue.component('my-game', {
+ props: ["problem"],
data: function() {
return {
vr: null, //object to check moves, store them, FEN..
sound: parseInt(getCookie("sound", "2")),
};
},
+ watch: {
+ problem: function(p, pp) {
+ // 'problem' prop changed: update board state
+ // TODO: FEN + turn + flags + rappel instructions / solution on click sous l'échiquier
+ // TODO: trouver moyen de passer la situation des reserves pour Crazyhouse,
+ // et l'état des captures pour Grand... bref compléter le descriptif de l'état.
+ this.newGame("problem", p.fen, p.fen.split(" ")[2]);
+ },
+ },
render(h) {
const [sizeX,sizeY] = [V.size.x,V.size.y];
const smallScreen = (window.innerWidth <= 420);
if (this.mycolor == 'b')
setTimeout(this.playComputerMove, 500);
}
- //else: against a (IRL) friend: nothing more to do
+ //else: against a (IRL) friend or problem solving: nothing more to do
},
playComputerMove: function() {
const timeStart = Date.now();
this.selectedPiece.style.display = "inline-block";
this.selectedPiece.style.zIndex = 3000;
let startSquare = this.getSquareFromId(e.target.parentNode.id);
- const iCanPlay = this.mode!="idle"
- && (this.mode=="friend" || this.vr.canIplay(this.mycolor,startSquare));
+ const iCanPlay = this.mode!="idle" &&
+ (["friend","problem"].includes(this.mode) ||
+ this.vr.canIplay(this.mycolor,startSquare));
this.possibleMoves = iCanPlay ? this.vr.getPossibleMovesFrom(startSquare) : [];
// Next line add moving piece just after current image
// (required for Crazyhouse reserve)
<div class="problem col-sm-12" @click="showProblem()">
<div class="diagram" v-html="getDiagram(prob.fen)"></div>
<div class="problem-instructions" v-html="prob.instructions.substr(0,32)"></div>
- <div class="problem-time">{{ timestamp2datetime(prob.added) }}</div>
+ <div class="problem-time">{{ timestamp2date(prob.added) }}</div>
</div>
`,
methods: {
turn: fenParts[2],
});
},
- timestamp2datetime(ts) {
- // TODO
- return ts;
+ timestamp2date(ts) {
+ return getDate(new Date(ts));
},
+ // Propagate "show problem" event to parent component (my-problems)
showProblem: function() {
- alert("show problem");
- //..........
- //TODO: send event with object prob.fen, prob.instructions, prob.solution
- //Event should propagate to game, which set mode=="problem" + other variables
- //click on a problem ==> land on variant page with mode==friend, FEN prefilled... ok
- // click on problem ==> masque problems, affiche game tab, launch new game Friend with
- // FEN + turn + flags + rappel instructions / solution on click sous l'échiquier
+ this.$emit('show-problem');
},
},
})
<button @click="fetchProblems('backward')">Previous</button>
<button @click="fetchProblems('forward')">Next</button>
<button @click="showNewproblemModal">New</button>
- <my-problem-summary
+ <my-problem-summary v-on:show-problem="bubbleUp(p)"
v-for="(p,idx) in sortedProblems" v-bind:prob="p" v-bind:key="idx">
</my-problem-summary>
<input type="checkbox" id="modal-newproblem" class="modal">
`,
computed: {
sortedProblems: function() {
- console.log("call");
// Newest problem first
return this.problems.sort((p1,p2) => { return p2.added - p1.added; });
},
},
},
methods: {
+ // Propagate "show problem" event to parent component (my-variant)
+ bubbleUp: function(problem) {
+ this.$emit('show-problem', JSON.stringify(problem));
+ },
fetchProblems: function(direction) {
return; //TODO: re-activate after server side is implemented (see routes/all.js)
if (this.problems.length == 0)
--- /dev/null
+function zeroPad(x)
+{
+ return (x<10 ? "0" : "") + x;
+}
+
+function getDate(d)
+{
+ return d.getFullYear() + '-' + (d.getMonth()+1) + '-' + zeroPad(d.getDate());
+}
+
+function getTime(d)
+{
+ return zeroPad(d.getHours()) + ":" + zeroPad(d.getMinutes()) + ":" +
+ zeroPad(d.getSeconds());
+}
new Vue({
el: "#variantPage",
- data: { display: "" }, //do not show anything...
- // TODO: listen event "show problem", avec le probleme stringifié en arg
- // Alors: display=game, mode=friend, newGame(fen, turn, ...),
- // et set Instructions+Soluce
+ data: {
+ display: "", //do not show anything...
+ problem: undefined, //current problem in view
+ },
methods: {
toggleDisplay: function(elt) {
if (this.display == elt)
else
this.display = elt; //show
},
+ showProblem: function(problemTxt) {
+ this.problem = JSON.parse(problemTxt);
+ this.display = "game";
+ },
},
});
+ "A" + (antikingPos["w"]<7?7-antikingPos["w"]:"");
const ranks23_white = (antikingPos["b"]>0?antikingPos["b"]:"") + "a"
+ (antikingPos["b"]<7?7-antikingPos["b"]:"") + "/PPPPPPPP";
- let fen = pieces["b"].join("") + "/" + ranks23_black +
+ return pieces["b"].join("") + "/" + ranks23_black +
"/8/8/" +
ranks23_white + "/" + pieces["w"].join("").toUpperCase() +
- " 1111";
- return fen;
+ " 1111 w";
}
}
return !!flags.match(/^[01]{20,20}$/);
}
- setFlags(fen)
+ setFlags(fenflags)
{
- super.setFlags(fen); //castleFlags
+ super.setFlags(fenflags); //castleFlags
this.pawnFlags =
{
- "w": new Array(8), //pawns can move 2 squares?
- "b": new Array(8)
+ "w": _.map(_.range(8), i => true), //pawns can move 2 squares?
+ "b": _.map(_.range(8), i => true)
};
- const flags = fen.split(" ")[1].substr(4); //skip first 4 digits, for castle
+ if (!fenflags)
+ return;
+ const flags = fenflags.substr(4); //skip first 4 digits, for castle
for (let c of ['w','b'])
{
for (let i=0; i<8; i++)
static GenRandInitFen()
{
- return ChessRules.GenRandInitFen() + "1111111111111111"; //add 16 pawns flags
+ const randFen = ChessRules.GenRandInitFen();
+ // Add 16 pawns flags:
+ return randFen.replace(" 1111 w", " 11111111111111111111 w");
}
getFlagsFen()
pieces[c][knight2Pos] = 'n';
pieces[c][rook2Pos] = 'r';
}
- let fen = pieces["b"].join("") +
+ return pieces["b"].join("") +
"/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/" +
pieces["w"].join("").toUpperCase() +
- " 1111";
- return fen;
+ " 1111 w";
}
}
return true; //anything is good: no flags
}
- setFlags(fen)
+ setFlags(fenflags)
{
// No castling, hence no flags; but flags defined for compatibility
this.castleFlags = { "w":[false,false], "b":[false,false] };
return pieces["b"].join("") +
"/pppppppp/8/8/8/8/PPPPPPPP/" +
pieces["w"].join("").toUpperCase() +
- " 0000"; //add flags (TODO?!)
+ " 0000 w"; //add flags (TODO?!)
}
}
this.epSquares = []; //no en-passant here
}
- setFlags(fen)
+ setFlags(fenflags)
{
// TODO: for compatibility?
this.castleFlags = {"w":[false,false], "b":[false,false]};
return pieces["b"].join("") +
"/pppppppp/8/8/8/8/PPPPPPPP/" +
pieces["w"].join("").toUpperCase() +
- " 0000"; //TODO: flags?!
+ " 0000 w"; //TODO: flags?!
}
getFlagsFen()
pieces[c][knight2Pos] = 'n';
pieces[c][rook2Pos] = 'r';
}
- let fen = pieces["b"].join("") +
+ return pieces["b"].join("") +
"/ppppppppppp/11/11/11/11/11/11/PPPPPPPPPPP/" +
pieces["w"].join("").toUpperCase() +
- " 1111";
- return fen;
+ " 1111 w";
}
}
.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
h4.variantpage-title.text-center(v-on:click="toggleDisplay('game')")
| #{variant} Game
- my-game(v-show="display=='game'")
+ my-game(v-show="display=='game'" v-bind:problem="problem")
.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
h4.variantpage-title.text-center(v-on:click="toggleDisplay('problems')")
| #{variant} Problems
- my-problems(v-show="display=='problems'")
+ my-problems(v-show="display=='problems'"
+ v-on:show-problem="showProblem($event)")
block javascripts
script(src="/javascripts/utils/misc.js")
script(src="/javascripts/utils/md5.js")
script(src="/javascripts/utils/printDiagram.js")
script(src="/javascripts/utils/ajax.js")
+ script(src="/javascripts/utils/datetime.js")
script(src="/javascripts/base_rules.js")
script(src="/javascripts/variants/" + variant + ".js")
script.