ymir-js
Version:
This toolkit is created to make it easier for you to develop games like chess, checkers, go, match 3 puzzle and more. It is still under development.
316 lines (315 loc) • 15.8 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var _ = require("lodash");
var getAvailableColumns_1 = require("../../../utils/getAvailableColumns");
var parseCoord_1 = require("../../../utils/parseCoord");
var board_1 = require("../../core/board");
var item_1 = require("./item");
var TurkishCheckersBoard = /** @class */ (function (_super) {
__extends(TurkishCheckersBoard, _super);
function TurkishCheckersBoard(config) {
if (config === void 0) { config = { x: 8, y: 8 }; }
var _this = _super.call(this, config) || this;
_this.getAvailableCoordsByColor = function (color) {
var currentItems = [];
var availableCoords = {};
Object.entries(_this.board).forEach(function (_a) {
var coord = _a[0], col = _a[1];
if (col.item && col.item.color === color) {
currentItems.push(coord);
}
});
currentItems.forEach(function (coord) {
var item = _this.getItem(coord);
var currentAvailableCoords = _this.getAvailableColumns(coord, item.movement);
if (currentAvailableCoords.length) {
availableCoords[coord] = currentAvailableCoords;
}
});
return availableCoords;
};
_this.getAttackCoordsByColor = function (color) {
var availableCoords = _this.getAvailableCoordsByColor(color);
var attackCoords = {};
Object.entries(availableCoords).forEach(function (_a) {
var coord = _a[0], currentAvailableCoords = _a[1];
currentAvailableCoords.forEach(function (currentAvailableCoord) {
var destroyItemCoord = _this.getItemsBetweenTwoCoords(coord, currentAvailableCoord)[0];
if (destroyItemCoord) {
if (attackCoords[coord]) {
attackCoords[coord].push({
coord: currentAvailableCoord,
destroyItemCoord: destroyItemCoord,
});
}
else {
attackCoords[coord] = [
{ coord: currentAvailableCoord, destroyItemCoord: destroyItemCoord },
];
}
}
});
});
return attackCoords;
};
_this.getDefendCoordsByColor = function (color) {
var defendCoords = {};
var enemyColor = color === 'white' ? 'black' : 'white';
var availableCoords = _this.getAvailableCoordsByColor(color);
var enemyAttackCoords = _this.getAttackCoordsByColor(enemyColor);
Object.entries(enemyAttackCoords).forEach(function (_a) {
var enemyAttack = _a[1];
Object.values(enemyAttack).forEach(function (enemyAttackCoord) {
Object.keys(availableCoords).forEach(function (availableItemOrigin) {
var availableColumnCoords = availableCoords[availableItemOrigin];
if (availableColumnCoords.includes(enemyAttackCoord.coord) &&
availableItemOrigin !== enemyAttackCoord.destroyItemCoord) {
var defendCoordItem = {
coord: enemyAttackCoord.coord,
inDangerCoord: enemyAttackCoord.destroyItemCoord,
};
if (defendCoords[availableItemOrigin]) {
defendCoords[availableItemOrigin].push(defendCoordItem);
}
else {
defendCoords[availableItemOrigin] = [defendCoordItem];
}
}
});
});
});
return defendCoords;
};
_this.getItemsByColor = function (color) {
return Object.values(_this.board)
.filter(function (_a) {
var item = _a.item;
return (item === null || item === void 0 ? void 0 : item.color) === color;
})
.map(function (_a) {
var item = _a.item;
return item;
});
};
_this.getAvailableColumns = function (coord, movement) {
if (_this.isEmpty(coord))
return [];
var columns = (0, getAvailableColumns_1.default)(coord, movement);
var availableColumns = {};
var captureAvailableColumns = {};
var item = _this.getItem(coord);
Object.keys(columns).forEach(function (key) {
var _a;
availableColumns[key] = [];
var isFoundCapture = false;
for (var i = 0; i < columns[key].length; i += 1) {
var currentCoord = columns[key][i];
if (!_this.isExistCoord(currentCoord))
continue;
if (_this.isEmpty(currentCoord)) {
availableColumns[key].push(currentCoord);
continue;
}
else if (isFoundCapture) {
break;
}
var nextCoordItem = _this.getItem(currentCoord);
if ((nextCoordItem === null || nextCoordItem === void 0 ? void 0 : nextCoordItem.color) === item.color) {
break;
}
else if (!isFoundCapture &&
nextCoordItem &&
nextCoordItem.color !== item.color) {
var direction = _this.getDirection(coord, currentCoord);
var movementRule = (_a = {
stepCount: 1
},
_a[direction] = true,
_a);
var afterCoord = Object.values((0, getAvailableColumns_1.default)(currentCoord, movementRule))
.filter(function (arr) { return arr.length; })
.flat()[0];
var afterItem = _this.getItem(afterCoord);
if (afterItem)
break;
if (_this.isEmpty(afterCoord)) {
availableColumns[key] = [afterCoord];
captureAvailableColumns[key] = true;
isFoundCapture = true;
}
else {
break;
}
}
}
});
var resultCoords = {};
var isFoundAnySuccessDirection = Object.values(captureAvailableColumns).some(function (direction) { return direction; });
Object.keys(availableColumns).forEach(function (key) {
if (!isFoundAnySuccessDirection) {
resultCoords[key] = _.uniq(availableColumns[key]);
}
else if (captureAvailableColumns[key]) {
resultCoords[key] = _.uniq(availableColumns[key]);
}
});
return Object.values(resultCoords).flat();
};
_this.autoPlay = function (color, _a) {
var _b;
var onSelect = _a.onSelect, onMove = _a.onMove;
// AVAILABLE SUCCESS MOVES
var availableAttacks = _this.getAttackCoordsByColor(color);
var availableAttacksOriginn = Object.keys(availableAttacks);
if (availableAttacksOriginn.length) {
var attackOriginn = availableAttacksOriginn[0];
var availableAttackColumn = availableAttacks[attackOriginn][0];
onSelect === null || onSelect === void 0 ? void 0 : onSelect(attackOriginn);
onMove === null || onMove === void 0 ? void 0 : onMove(attackOriginn, availableAttackColumn.coord);
return;
}
// AVAILABLE DEFEND MOVES
var potentialDefendsMoves = _this.getDefendCoordsByColor(color);
var potentialDefendsItem = Object.keys(potentialDefendsMoves);
if (potentialDefendsItem.length) {
var defendOriginn = potentialDefendsItem[0];
var availableDefendColumn = potentialDefendsMoves[defendOriginn].map(function (item) { return item.coord; })[0];
onSelect === null || onSelect === void 0 ? void 0 : onSelect(defendOriginn);
onMove === null || onMove === void 0 ? void 0 : onMove(defendOriginn, availableDefendColumn);
return;
}
// AVAILABLE NORMAL MOVES
var availableNormalMoves = _this.getAvailableCoordsByColor(color);
var availableCoords = Object.keys(availableNormalMoves);
var availableEnemyNormalMoves = Object.values(_this.getAvailableCoordsByColor(color === 'white' ? 'black' : 'white')).flat();
var safeMoves = {};
Object.values(availableNormalMoves).filter(function (moves, index) {
moves.forEach(function (move) {
if (!availableEnemyNormalMoves.includes(move)) {
if (safeMoves[availableCoords[index]]) {
safeMoves[availableCoords[index]].push(move);
}
else {
safeMoves[availableCoords[index]] = [move];
}
}
});
});
var currentCoords = availableCoords;
var currentMoves = availableNormalMoves;
// KING POTENTIAL
var kingRowId = color === 'white' ? 7 : 0;
var potentialKingItemCoord;
var potentialAvailableCoord;
Object.keys(currentMoves).forEach(function (coord) {
var availableColumns = currentMoves[coord];
availableColumns.forEach(function (columnCoord) {
var rowId = (0, parseCoord_1.default)(coord)[0];
var moveRowId = (0, parseCoord_1.default)(columnCoord)[0];
if (rowId !== moveRowId && moveRowId === kingRowId) {
potentialKingItemCoord = coord;
potentialAvailableCoord = columnCoord;
}
});
});
if (potentialKingItemCoord && potentialAvailableCoord) {
onSelect === null || onSelect === void 0 ? void 0 : onSelect(potentialKingItemCoord);
onMove === null || onMove === void 0 ? void 0 : onMove(potentialKingItemCoord, potentialAvailableCoord);
return;
}
var safeCoords = Object.keys(safeMoves);
if (safeCoords.length) {
currentCoords = safeCoords;
currentMoves = safeMoves;
}
// RISK ESTIMATION
currentCoords.forEach(function (currentCoord) {
currentMoves[currentCoord].forEach(function (move) {
var riskEstimationBoard = new TurkishCheckersBoard().updateBoard(JSON.parse(JSON.stringify(_this.board)));
riskEstimationBoard.moveItem(currentCoord, move);
var potentialDefendColumns = riskEstimationBoard.getDefendCoordsByColor(color);
if (Object.values(potentialDefendColumns).flat().length) {
currentMoves[currentCoord] = currentMoves[currentCoord].filter(function (mv) { return mv !== move; });
}
});
if (!currentMoves[currentCoord].length) {
currentCoords = currentCoords.filter(function (c) { return c !== currentCoord; });
delete currentMoves[currentCoord];
}
});
// PROPENSITY TO MOVE FORWARD
currentCoords.forEach(function (currentCoord) {
currentMoves[currentCoord].sort(function (first, second) {
var firstRowId = (0, parseCoord_1.default)(first)[0];
var secondRowId = (0, parseCoord_1.default)(second)[0];
if (firstRowId > secondRowId) {
return -1;
}
else if (firstRowId < secondRowId) {
return 1;
}
else {
return 0;
}
});
});
// [TODO]: No random, use foward move
var randomIndex = Math.floor(Math.random() * currentCoords.length);
var selectedCoord = currentCoords[randomIndex];
var moveCoord = (_b = currentMoves[selectedCoord]) === null || _b === void 0 ? void 0 : _b[0];
onSelect === null || onSelect === void 0 ? void 0 : onSelect(selectedCoord);
onMove === null || onMove === void 0 ? void 0 : onMove(selectedCoord, moveCoord);
};
return _this;
}
TurkishCheckersBoard.prototype.init = function () {
var _this = this;
var whiteItemCoords = '1|0 1|1 1|2 1|3 1|4 1|5 1|6 1|7 2|0 2|1 2|2 2|3 2|4 2|5 2|6 2|7';
var blackItemCoords = '5|0 5|1 5|2 5|3 5|4 5|5 5|6 5|7 6|0 6|1 6|2 6|3 6|4 6|5 6|6 6|7';
whiteItemCoords.split(' ').forEach(function (coord) {
_this.setItem(coord, new item_1.default({ color: 'white' }));
});
blackItemCoords.split(' ').forEach(function (coord) {
_this.setItem(coord, new item_1.default({ color: 'black' }));
});
return this;
};
TurkishCheckersBoard.prototype.reset = function () {
Object.keys(this.board).forEach(this.removeItem);
this.init();
};
TurkishCheckersBoard.prototype.getItemsBetweenTwoCoords = function (fromCoord, toCoord) {
var _this = this;
var direction = this.getDirection(fromCoord, toCoord);
var distance = this.getDistanceBetweenTwoCoords(fromCoord, toCoord);
var convertDirection = {
top: 'y',
bottom: 'y',
left: 'x',
right: 'x',
};
var stepCount = Math.abs(distance[convertDirection[direction]]) || 1;
var movement = { stepCount: stepCount };
movement[direction] = true;
var betweenCoords = [];
return betweenCoords
.concat.apply(betweenCoords, Object.values((0, getAvailableColumns_1.default)(fromCoord, movement))).filter(function (coord) { return !_this.isEmpty(coord); });
};
return TurkishCheckersBoard;
}(board_1.default));
exports.default = TurkishCheckersBoard;