King's Indian Defence Trainer
Details
Author: | Mark |
Rating: | |
Difficulty: | Beginner |
Date: | 2nd February 2021 |
Description: | A trainer to help you learn and memorize all the variations of the King's Indian Defence opening. |
Code
//Please feel welcome to copy this code for your own creations.
//fromFen("rnbqkb1r/pppppp1p/5np1/8/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 0 1");
let root = [
"d4", //1.
"Nf6",
"c4", //2.
"g6",
[
"Nc3", //3.
"Bg7",
"e4", //4.
"d6",
[
"Nf3", //5.
"O-O",
[
"Be2", //6.
{
info: "This is the classical variation"
},
[
"e5",
[
"O-O", //7.
[
"Nc6",
{
info: "This is the Main Line (aka the Mar del Plata Variation)"
},
"d5", //8.
"Ne7",
[
"b4", //9.
{
info: "This is the Bayonet Attack"
}
],
[
"Ne1", //9.
],
[
"Nd2", //9.
]
],
[
"Nbd7",
{
info: "This is the Old Main Line"
},
],
[
"exd4",
"Nxd4", //8.
],
[
"Na6",
[
"dxe5", //8.
"dxe5",
"Qxd8", //9.
"Rxd8"
],
[
"d5", //8.
"Nc5",
"Qc2", //9.
"a5",
{
info: "This may transpose into the Petrosian Variation"
}
],
[
"Bg5", //8.
"h6",
"Bh4", //9.
"Qe8",
"Bxf6", //10.
"Bxf6",
"c5", //11.
]
]
],
[
"d5", //7.
{
info: "This is the Petrosian Variation"
},
[
"a5",
"Bg5", //8.
],
[
"Na6"
]
],
[
"Be3", //7.
{
info: "This is the Gligoric System"
},
[
"Ng4",
"Bg5", //8.
"f6",
"Bh4", //9.
"Nc6",
],
[
"Na6",
"O-O", //8.
{
info: "This transposes into the Modern Defense"
}
],
[
"h6",
"O-O", //8.
"Ng4",
"Bc1", //9.
"Nc6",
"d5", //10.
"Ne7",
"Ne1", //11.
"f5",
"Bxg4", //12.
"fxg4",
],
[
"exd4",
"Nxd4", //8.
"Re8",
"f3", //9.
"c6",
"Qd2", //10.
"d5",
"exd5", //11.
"cxd5",
"O-O", //12.
"Nc6",
"c5", //13.
]
],
[
"dxe5", //7.
{
info: "This is the Exchange Variation"
},
"dxe5",
"Qxd8", //8.
"Rxd8",
]
],
[
"Bg4",
"Be3", //7.
],
[
"c5",
"O-O", //7.
"cxd4",
"Nxd4", //8.
"Nc6",
{
info: "this transposes into the Accelerated Dragon variation of the Sicilian Defence"
}
]
],
[
"Bg5", //6.
{
info: "This is the Zinnowitz Variation"
},
[
"h6"
],
[
"Nbd7"
]
]
],
[
"f5", //5.
{
info: "This is the Sämisch Variation"
},
"O-O",
[
"Bg5", //6.
"c5",
"d5", //7.
"e6",
{
info: "This transposes into the Modern Benoni"
}
],
[
"Be3", //6.
[
"e5",
],
[
"c5",
{
info: "This is the Sämisch Gambit"
},
[
"dxc5", //7.
"dxc5",
[
"Qxd8", //8.
"Rxd8",
"Bxc5", //9.
"Nc6",
],
[
"e5", //8.
"Nfd7",
"f4", //9.
"f6",
"exf6", //10.
]
],
[
"Nge2", //7.
]
],
[
"Nc6",
{
info: "This is the Panno Variation of the Sämisch"
},
"Nge2", //7.
"a6",
"Qd2", //8.
"Rb8",
]
]
],
[
"Be2", //5.
{
info: "This is the Averbakh Variation"
},
"O-O",
"Bg5", //6.
[
"c5"
],
[
"Nbd7"
],
[
"Na6"
]
],
[
"f4", //5.
{
info: "This is the Four Pawns Attack"
},
"O-O",
"Nf3", //6.
[
"c5",
"d5", //7.
"e6",
"Be2", //8.
"exd5",
"cxd5", //9.
[
"Bg4"
],
[
"Re8"
],
[
"b5"
]
],
[
"Na6",
{
info: "This is the Modern Variation"
}
]
]
],
[
"Nf3", //3.
{
info: "This is the Fianchetto Variation"
},
"Bg7",
"g3", //4.
"O-O",
"Bg2", //5.
"d6",
"O-O", //6.
[
"Nbd7",
"Nc3", //7.
"e5",
"e4", //8.
[
"exd4",
{
info: "This is the Gallagher Variation of the Fianchetto Variation"
},
"Nxd4", //9.
"Re8",
"h3", //10.
"a6",
],
[
"c6"
],
[
"a6"
]
],
[
"Nc6",
"Nc3", //7.
"a6",
"d5", //8.
"Na5",
"Nd2", //9.
"c5",
"Qc2", //10.
"Rb8",
"b3", //11.
"b5",
"Bb2", //12.
"bxc4",
"bxc4", //13.
"Bh6",
"f4", //14.
"e5",
]
]
];
let targetMove = "";
onPieceClicked(function (squareName) {
if (typeof targetMove == "string") {
if (squareName == sourceOfSan(targetMove)) {
return true;
}
} else if (Array.isArray(targetMove)) {
for (let temp of targetMove) {
if (squareName == sourceOfSan(temp)) {
return true;
}
}
} else {
throw new Error();
}
if (targetMove == "") {
return false;
}
if (squareName == sourceOfSan(targetMove)) {
return true;
}
highlightSquareRed(squareName);
return false;
});
onMoveAttempted(function (san) {
if (typeof targetMove == "string") {
if (san == targetMove) {
current.index++;
setTimeout(next, 50);
return true;
}
} else if (Array.isArray(targetMove)) {
for (let temp of targetMove) {
if (san == temp) {
for (let i = current.index; i < current.length; i++) {
if (current[i][0] == san) {
current[i].parent = current;
current = current[i];
current.index = 1;
break;
}
}
setTimeout(next, 50);
return true;
}
}
} else {
throw new Error();
}
return false;
});
onNextClicked(function () {
showNextButton(false);
next();
});
function nextDelayed() {
setTimeout(next, 500);
}
function onUndoClicked() {
undo();
if (current.index > 0) {
current.index--;
if (current.index > 0 && current[current.index].info != undefined) {
current.index--;
}
}
if (current.index == 0) {
if (current.parent != undefined) {
current = current.parent;
} else {
//showButton("undo", false);
}
}
next();
}
let current = root;
current.index = 0;
let preInfo = "";
createButton("Undo", onUndoClicked);
showButton("Undo", false);
let undoButtonVisible = false;
function next() {
let showUndoButton = current != root || current.index > 0;
if (undoButtonVisible != showUndoButton) {
showButton("Undo", showUndoButton);
undoButtonVisible = showUndoButton;
}
if (preInfo != "") {
preInfo += "<br><br>";
}
if (current.index >= current.length) {
info(preInfo + "End of the line");
preInfo = "";
return;
}
let step = current[current.index];
if (typeof step == "string") {
if (isWhitesTurn()) {
info(preInfo + "White to play <b>" + currentMoveNumber() + "." + step + "</b>");
} else {
info(preInfo + "Black to play <b>" + currentMoveNumber() + "..." + step + "</b>");
}
targetMove = step;
preInfo = "";
} else if (Array.isArray(step)) {
///assume that the rest of the steps in the current array are also arrays
//i.e. different options from this point
let possibleSteps = [];
for (let i = current.index; i < current.length; i++) {
//assume that the first step in every array is a string
//otherwise it would be seperated out into an array at the previous level
possibleSteps.push(current[i][0]);
}
targetMove = possibleSteps;
if (isWhitesTurn()) {
possibleSteps = possibleSteps.map(x => "<li><b>" + currentMoveNumber() + "." + x + "</b></li>");
info(preInfo + "White can play: <ul>" + possibleSteps.join("") + "</ul>");
} else {
possibleSteps = possibleSteps.map(x => "<li><b>" + currentMoveNumber() + "..." + x + "</b></li>");
info(preInfo + "Black can play: <ul>" + possibleSteps.join("") + "</ul>");
}
preInfo = "";
} else {
if (step.info != undefined) {
preInfo = step.info;
current.index++;
next();
}
}
}
next();