shogi.js 4.0.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -1
- package/.prettierignore +1 -1
- package/cjs/Color.js +23 -0
- package/cjs/IMoveDefinition.js +2 -0
- package/{dist/dist → cjs}/Kind.d.ts +3 -1
- package/cjs/Kind.js +49 -0
- package/cjs/Piece.js +123 -0
- package/cjs/Serialization.js +177 -0
- package/cjs/moveDefinitions.js +37 -0
- package/cjs/polyfills.js +22 -0
- package/cjs/presets.js +94 -0
- package/cjs/shogi.js +428 -0
- package/package.json +9 -7
- package/dist/shogi.js +0 -2
- package/dist/shogi.js.LICENSE.txt +0 -6
- /package/{dist/dist → cjs}/Color.d.ts +0 -0
- /package/{dist/dist → cjs}/IMoveDefinition.d.ts +0 -0
- /package/{dist/dist → cjs}/Piece.d.ts +0 -0
- /package/{dist/dist → cjs}/Serialization.d.ts +0 -0
- /package/{dist/dist → cjs}/moveDefinitions.d.ts +0 -0
- /package/{dist/dist → cjs}/polyfills.d.ts +0 -0
- /package/{dist/dist → cjs}/presets.d.ts +0 -0
- /package/{dist/dist → cjs}/shogi.d.ts +0 -0
package/.eslintrc.js
CHANGED
package/.prettierignore
CHANGED
package/cjs/Color.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.colorToString = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 先後番を表すクラス
|
|
6
|
+
*
|
|
7
|
+
* `Black` は先手で、 `White` は後手である.
|
|
8
|
+
*/
|
|
9
|
+
var Color;
|
|
10
|
+
(function (Color) {
|
|
11
|
+
Color[Color["Black"] = 0] = "Black";
|
|
12
|
+
Color[Color["White"] = 1] = "White";
|
|
13
|
+
})(Color || (Color = {}));
|
|
14
|
+
exports["default"] = Color;
|
|
15
|
+
function colorToString(color) {
|
|
16
|
+
switch (color) {
|
|
17
|
+
case Color.Black:
|
|
18
|
+
return "先手";
|
|
19
|
+
case Color.White:
|
|
20
|
+
return "後手";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.colorToString = colorToString;
|
|
@@ -15,6 +15,8 @@ declare enum KindEnum {
|
|
|
15
15
|
RY = 13
|
|
16
16
|
}
|
|
17
17
|
export type Kind = keyof typeof KindEnum;
|
|
18
|
+
export type RawKind = Extract<Kind, "FU" | "KY" | "KE" | "GI" | "KI" | "KA" | "HI">;
|
|
18
19
|
export declare const values: Kind[];
|
|
19
|
-
export declare function kindToString(kind: Kind): string;
|
|
20
|
+
export declare function kindToString(kind: Kind, short?: boolean): string;
|
|
21
|
+
export declare function isRawKind(kind: Kind): kind is RawKind;
|
|
20
22
|
export {};
|
package/cjs/Kind.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.isRawKind = exports.kindToString = exports.values = void 0;
|
|
4
|
+
var KindEnum;
|
|
5
|
+
(function (KindEnum) {
|
|
6
|
+
KindEnum[KindEnum["FU"] = 0] = "FU";
|
|
7
|
+
KindEnum[KindEnum["KY"] = 1] = "KY";
|
|
8
|
+
KindEnum[KindEnum["KE"] = 2] = "KE";
|
|
9
|
+
KindEnum[KindEnum["GI"] = 3] = "GI";
|
|
10
|
+
KindEnum[KindEnum["KI"] = 4] = "KI";
|
|
11
|
+
KindEnum[KindEnum["KA"] = 5] = "KA";
|
|
12
|
+
KindEnum[KindEnum["HI"] = 6] = "HI";
|
|
13
|
+
KindEnum[KindEnum["OU"] = 7] = "OU";
|
|
14
|
+
KindEnum[KindEnum["TO"] = 8] = "TO";
|
|
15
|
+
KindEnum[KindEnum["NY"] = 9] = "NY";
|
|
16
|
+
KindEnum[KindEnum["NK"] = 10] = "NK";
|
|
17
|
+
KindEnum[KindEnum["NG"] = 11] = "NG";
|
|
18
|
+
KindEnum[KindEnum["UM"] = 12] = "UM";
|
|
19
|
+
KindEnum[KindEnum["RY"] = 13] = "RY";
|
|
20
|
+
})(KindEnum || (KindEnum = {}));
|
|
21
|
+
var rawKinds = ["FU", "KY", "KE", "GI", "KI", "KA", "HI"];
|
|
22
|
+
// TODO: this needs type annotations
|
|
23
|
+
exports.values = Object.keys(KindEnum).filter(function (k) {
|
|
24
|
+
return Number.isNaN(parseInt(k));
|
|
25
|
+
});
|
|
26
|
+
function kindToString(kind, short) {
|
|
27
|
+
if (short === void 0) { short = false; }
|
|
28
|
+
return {
|
|
29
|
+
FU: "歩",
|
|
30
|
+
KY: "香",
|
|
31
|
+
KE: "桂",
|
|
32
|
+
GI: "銀",
|
|
33
|
+
KI: "金",
|
|
34
|
+
KA: "角",
|
|
35
|
+
HI: "飛",
|
|
36
|
+
OU: "玉",
|
|
37
|
+
TO: "と",
|
|
38
|
+
NY: short ? "杏" : "成香",
|
|
39
|
+
NK: short ? "圭" : "成桂",
|
|
40
|
+
NG: short ? "全" : "成銀",
|
|
41
|
+
UM: "馬",
|
|
42
|
+
RY: "龍"
|
|
43
|
+
}[kind];
|
|
44
|
+
}
|
|
45
|
+
exports.kindToString = kindToString;
|
|
46
|
+
function isRawKind(kind) {
|
|
47
|
+
return rawKinds.indexOf(kind) >= 0;
|
|
48
|
+
}
|
|
49
|
+
exports.isRawKind = isRawKind;
|
package/cjs/Piece.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
var Color_1 = require("./Color");
|
|
4
|
+
/**
|
|
5
|
+
* 駒を表すクラス
|
|
6
|
+
*/
|
|
7
|
+
var Piece = /** @class */ (function () {
|
|
8
|
+
/**
|
|
9
|
+
* "+FU"などのCSAによる駒表現から駒オブジェクトを作成
|
|
10
|
+
*/
|
|
11
|
+
function Piece(csa) {
|
|
12
|
+
this.color = csa.slice(0, 1) === "+" ? Color_1["default"].Black : Color_1["default"].White;
|
|
13
|
+
this.kind = csa.slice(1);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 成った時の種類を返す.なければそのまま.
|
|
17
|
+
*/
|
|
18
|
+
Piece.promote = function (kind) {
|
|
19
|
+
return ({
|
|
20
|
+
FU: "TO",
|
|
21
|
+
KY: "NY",
|
|
22
|
+
KE: "NK",
|
|
23
|
+
GI: "NG",
|
|
24
|
+
KA: "UM",
|
|
25
|
+
HI: "RY"
|
|
26
|
+
}[kind] || kind);
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* 表に返した時の種類を返す.表の場合はそのまま.
|
|
30
|
+
*/
|
|
31
|
+
Piece.unpromote = function (kind) {
|
|
32
|
+
return ({
|
|
33
|
+
TO: "FU",
|
|
34
|
+
NY: "KY",
|
|
35
|
+
NK: "KE",
|
|
36
|
+
NG: "GI",
|
|
37
|
+
KI: "KI",
|
|
38
|
+
UM: "KA",
|
|
39
|
+
RY: "HI",
|
|
40
|
+
OU: "OU"
|
|
41
|
+
}[kind] || kind);
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* 成れる駒かどうかを返す
|
|
45
|
+
*/
|
|
46
|
+
Piece.canPromote = function (kind) {
|
|
47
|
+
return Piece.promote(kind) !== kind;
|
|
48
|
+
};
|
|
49
|
+
Piece.isPromoted = function (kind) {
|
|
50
|
+
return ["TO", "NY", "NK", "NG", "UM", "RY"].indexOf(kind) >= 0;
|
|
51
|
+
};
|
|
52
|
+
Piece.oppositeColor = function (color) {
|
|
53
|
+
return color === Color_1["default"].Black ? Color_1["default"].White : Color_1["default"].Black;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* SFENによる文字列表現から駒オブジェクトを作成
|
|
57
|
+
*/
|
|
58
|
+
Piece.fromSFENString = function (sfen) {
|
|
59
|
+
var promoted = sfen[0] === "+";
|
|
60
|
+
if (promoted) {
|
|
61
|
+
sfen = sfen.slice(1);
|
|
62
|
+
}
|
|
63
|
+
var color = sfen.match(/[A-Z]/) ? "+" : "-";
|
|
64
|
+
var kind = {
|
|
65
|
+
P: "FU",
|
|
66
|
+
L: "KY",
|
|
67
|
+
N: "KE",
|
|
68
|
+
S: "GI",
|
|
69
|
+
G: "KI",
|
|
70
|
+
B: "KA",
|
|
71
|
+
R: "HI",
|
|
72
|
+
K: "OU"
|
|
73
|
+
}[sfen.toUpperCase()];
|
|
74
|
+
var piece = new Piece(color + kind);
|
|
75
|
+
if (promoted) {
|
|
76
|
+
piece.promote();
|
|
77
|
+
}
|
|
78
|
+
return piece;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* 成る
|
|
82
|
+
*/
|
|
83
|
+
Piece.prototype.promote = function () {
|
|
84
|
+
this.kind = Piece.promote(this.kind);
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* 不成にする
|
|
88
|
+
*/
|
|
89
|
+
Piece.prototype.unpromote = function () {
|
|
90
|
+
this.kind = Piece.unpromote(this.kind);
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* 駒の向きを反転する
|
|
94
|
+
*/
|
|
95
|
+
Piece.prototype.inverse = function () {
|
|
96
|
+
this.color = this.color === Color_1["default"].Black ? Color_1["default"].White : Color_1["default"].Black;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* CSAによる駒表現の文字列を返す
|
|
100
|
+
*/
|
|
101
|
+
Piece.prototype.toCSAString = function () {
|
|
102
|
+
return (this.color === Color_1["default"].Black ? "+" : "-") + this.kind;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* SFENによる駒表現の文字列を返す
|
|
106
|
+
*/
|
|
107
|
+
Piece.prototype.toSFENString = function () {
|
|
108
|
+
var sfenPiece = {
|
|
109
|
+
FU: "P",
|
|
110
|
+
KY: "L",
|
|
111
|
+
KE: "N",
|
|
112
|
+
GI: "S",
|
|
113
|
+
KI: "G",
|
|
114
|
+
KA: "B",
|
|
115
|
+
HI: "R",
|
|
116
|
+
OU: "K"
|
|
117
|
+
}[Piece.unpromote(this.kind)];
|
|
118
|
+
return ((Piece.isPromoted(this.kind) ? "+" : "") +
|
|
119
|
+
(this.color === Color_1["default"].Black ? sfenPiece : sfenPiece.toLowerCase()));
|
|
120
|
+
};
|
|
121
|
+
return Piece;
|
|
122
|
+
}());
|
|
123
|
+
exports["default"] = Piece;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.toSfen = exports.fromSfen = exports.toCSA = exports.fromPreset = void 0;
|
|
4
|
+
var Color_1 = require("./Color");
|
|
5
|
+
var presets_1 = require("./presets");
|
|
6
|
+
var Piece_1 = require("./Piece");
|
|
7
|
+
function fromPreset(shogi, setting) {
|
|
8
|
+
var board = [];
|
|
9
|
+
var hands = [[], []];
|
|
10
|
+
var turn;
|
|
11
|
+
if (setting.preset !== "OTHER") {
|
|
12
|
+
var initial = (0, presets_1.getInitialFromPreset)(setting.preset);
|
|
13
|
+
for (var i = 0; i < 9; i++) {
|
|
14
|
+
board[i] = [];
|
|
15
|
+
for (var j = 0; j < 9; j++) {
|
|
16
|
+
var csa = initial.board[j].slice(24 - i * 3, 24 - i * 3 + 3);
|
|
17
|
+
board[i][j] = csa === " * " ? null : new Piece_1["default"](csa);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
turn = initial.turn;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
for (var i = 0; i < 9; i++) {
|
|
24
|
+
board[i] = [];
|
|
25
|
+
for (var j = 0; j < 9; j++) {
|
|
26
|
+
var p = setting.data.board[i][j];
|
|
27
|
+
board[i][j] = p.kind
|
|
28
|
+
? new Piece_1["default"]((p.color === Color_1["default"].Black ? "+" : "-") + p.kind)
|
|
29
|
+
: null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
turn = setting.data.color;
|
|
33
|
+
for (var c = 0; c < 2; c++) {
|
|
34
|
+
for (var k in setting.data.hands[c]) {
|
|
35
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
36
|
+
if (setting.data.hands[c].hasOwnProperty(k)) {
|
|
37
|
+
var csa = (c === 0 ? "+" : "-") + k;
|
|
38
|
+
for (var i = 0; i < setting.data.hands[c][k]; i++) {
|
|
39
|
+
hands[c].push(new Piece_1["default"](csa));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
shogi.board = board;
|
|
46
|
+
shogi.turn = turn;
|
|
47
|
+
shogi.hands = hands;
|
|
48
|
+
}
|
|
49
|
+
exports.fromPreset = fromPreset;
|
|
50
|
+
function toCSA(shogi) {
|
|
51
|
+
var ret = [];
|
|
52
|
+
for (var y = 0; y < 9; y++) {
|
|
53
|
+
var line = "P" + (y + 1);
|
|
54
|
+
for (var x = 8; x >= 0; x--) {
|
|
55
|
+
var piece = shogi.board[x][y];
|
|
56
|
+
line += piece == null ? " * " : piece.toCSAString();
|
|
57
|
+
}
|
|
58
|
+
ret.push(line);
|
|
59
|
+
}
|
|
60
|
+
for (var i = 0; i < 2; i++) {
|
|
61
|
+
var line = "P" + "+-"[i];
|
|
62
|
+
for (var _i = 0, _a = shogi.hands[i]; _i < _a.length; _i++) {
|
|
63
|
+
var hand = _a[_i];
|
|
64
|
+
line += "00" + hand.kind;
|
|
65
|
+
}
|
|
66
|
+
ret.push(line);
|
|
67
|
+
}
|
|
68
|
+
ret.push(shogi.turn === Color_1["default"].Black ? "+" : "-");
|
|
69
|
+
return ret.join("\n");
|
|
70
|
+
}
|
|
71
|
+
exports.toCSA = toCSA;
|
|
72
|
+
function fromSfen(shogi, sfen) {
|
|
73
|
+
var board = [];
|
|
74
|
+
for (var i = 0; i < 9; i++) {
|
|
75
|
+
board[i] = [];
|
|
76
|
+
for (var j = 0; j < 9; j++) {
|
|
77
|
+
board[i][j] = null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
var segments = sfen.split(" ");
|
|
81
|
+
if (segments[1] !== "w" && segments[1] !== "b")
|
|
82
|
+
throw new Error("Invalid SFEN");
|
|
83
|
+
var sfenBoard = segments[0];
|
|
84
|
+
var x = 8;
|
|
85
|
+
var y = 0;
|
|
86
|
+
for (var i = 0; i < sfenBoard.length; i++) {
|
|
87
|
+
var c = sfenBoard[i];
|
|
88
|
+
if (c === "+") {
|
|
89
|
+
i++;
|
|
90
|
+
c += sfenBoard[i];
|
|
91
|
+
}
|
|
92
|
+
if (c.match(/^[1-9]$/)) {
|
|
93
|
+
x -= Number(c);
|
|
94
|
+
}
|
|
95
|
+
else if (c === "/") {
|
|
96
|
+
y++;
|
|
97
|
+
x = 8;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
board[x][y] = Piece_1["default"].fromSFENString(c);
|
|
101
|
+
x--;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
shogi.board = board;
|
|
105
|
+
shogi.turn = segments[1] === "b" ? Color_1["default"].Black : Color_1["default"].White;
|
|
106
|
+
var hands = [[], []];
|
|
107
|
+
var sfenHands = segments[2];
|
|
108
|
+
if (sfenHands !== "-") {
|
|
109
|
+
while (sfenHands.length > 0) {
|
|
110
|
+
var count = 1;
|
|
111
|
+
var m = sfenHands.match(/^[0-9]+/);
|
|
112
|
+
if (m) {
|
|
113
|
+
count = Number(m[0]);
|
|
114
|
+
sfenHands = sfenHands.slice(m[0].length);
|
|
115
|
+
}
|
|
116
|
+
for (var i = 0; i < count; i++) {
|
|
117
|
+
var piece = Piece_1["default"].fromSFENString(sfenHands[0]);
|
|
118
|
+
hands[piece.color].push(piece);
|
|
119
|
+
}
|
|
120
|
+
sfenHands = sfenHands.slice(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
shogi.hands = hands;
|
|
124
|
+
}
|
|
125
|
+
exports.fromSfen = fromSfen;
|
|
126
|
+
function toSfen(shogi, moveCount) {
|
|
127
|
+
var ret = [];
|
|
128
|
+
var sfenBoard = [];
|
|
129
|
+
for (var y = 0; y < 9; y++) {
|
|
130
|
+
var line = "";
|
|
131
|
+
var empty = 0;
|
|
132
|
+
for (var x = 8; x >= 0; x--) {
|
|
133
|
+
var piece = shogi.board[x][y];
|
|
134
|
+
if (piece == null) {
|
|
135
|
+
empty++;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (empty > 0) {
|
|
139
|
+
line += "" + empty;
|
|
140
|
+
empty = 0;
|
|
141
|
+
}
|
|
142
|
+
line += piece.toSFENString();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (empty > 0) {
|
|
146
|
+
line += "" + empty;
|
|
147
|
+
}
|
|
148
|
+
sfenBoard.push(line);
|
|
149
|
+
}
|
|
150
|
+
ret.push(sfenBoard.join("/"));
|
|
151
|
+
ret.push(shogi.turn === Color_1["default"].Black ? "b" : "w");
|
|
152
|
+
if (shogi.hands[0].length === 0 && shogi.hands[1].length === 0) {
|
|
153
|
+
ret.push("-");
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
var sfenHands = "";
|
|
157
|
+
var kinds = ["R", "B", "G", "S", "N", "L", "P", "r", "b", "g", "s", "n", "l", "p"];
|
|
158
|
+
var count = {};
|
|
159
|
+
for (var i = 0; i < 2; i++) {
|
|
160
|
+
for (var _i = 0, _a = shogi.hands[i]; _i < _a.length; _i++) {
|
|
161
|
+
var hand = _a[_i];
|
|
162
|
+
var key = hand.toSFENString();
|
|
163
|
+
count[key] = (count[key] || 0) + 1;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
for (var _b = 0, kinds_1 = kinds; _b < kinds_1.length; _b++) {
|
|
167
|
+
var kind = kinds_1[_b];
|
|
168
|
+
if (count[kind] > 0) {
|
|
169
|
+
sfenHands += (count[kind] > 1 ? count[kind] : "") + kind;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
ret.push(sfenHands);
|
|
173
|
+
}
|
|
174
|
+
ret.push("" + moveCount);
|
|
175
|
+
return ret.join(" ");
|
|
176
|
+
}
|
|
177
|
+
exports.toSfen = toSfen;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.getMoveDefinitions = void 0;
|
|
4
|
+
var F = [0, -1];
|
|
5
|
+
var B = [0, 1];
|
|
6
|
+
var L = [1, 0];
|
|
7
|
+
var R = [-1, 0];
|
|
8
|
+
var FR = [-1, -1];
|
|
9
|
+
var FL = [1, -1];
|
|
10
|
+
var BR = [-1, 1];
|
|
11
|
+
var BL = [1, 1];
|
|
12
|
+
var kin = { just: [FR, F, FL, R, L, B] };
|
|
13
|
+
var MOVE_DEF = {
|
|
14
|
+
FU: { just: [F] },
|
|
15
|
+
KY: { fly: [F] },
|
|
16
|
+
KE: {
|
|
17
|
+
just: [
|
|
18
|
+
[-1, -2],
|
|
19
|
+
[1, -2],
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
GI: { just: [FR, F, FL, BR, BL] },
|
|
23
|
+
KI: kin,
|
|
24
|
+
TO: kin,
|
|
25
|
+
NY: kin,
|
|
26
|
+
NK: kin,
|
|
27
|
+
NG: kin,
|
|
28
|
+
KA: { fly: [FR, FL, BR, BL] },
|
|
29
|
+
HI: { fly: [F, R, L, B] },
|
|
30
|
+
OU: { just: [FR, F, FL, R, L, BR, B, BL] },
|
|
31
|
+
UM: { fly: [FR, FL, BR, BL], just: [F, R, L, B] },
|
|
32
|
+
RY: { fly: [F, R, L, B], just: [FR, FL, BR, BL] }
|
|
33
|
+
};
|
|
34
|
+
function getMoveDefinitions(kind) {
|
|
35
|
+
return MOVE_DEF[kind];
|
|
36
|
+
}
|
|
37
|
+
exports.getMoveDefinitions = getMoveDefinitions;
|
package/cjs/polyfills.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
if (!Array.prototype.some) {
|
|
4
|
+
Array.prototype.some = function (fun /*, thisp */) {
|
|
5
|
+
"use strict";
|
|
6
|
+
if (this == null) {
|
|
7
|
+
throw new TypeError();
|
|
8
|
+
}
|
|
9
|
+
var t = Object(this), len = t.length >>> 0;
|
|
10
|
+
if (typeof fun != "function") {
|
|
11
|
+
throw new TypeError();
|
|
12
|
+
}
|
|
13
|
+
// eslint-disable-next-line prefer-rest-params
|
|
14
|
+
var thisp = arguments[1];
|
|
15
|
+
for (var i = 0; i < len; i++) {
|
|
16
|
+
if (i in t && fun.call(thisp, t[i], i, t)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
22
|
+
}
|
package/cjs/presets.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.getInitialFromPreset = void 0;
|
|
4
|
+
var Color_1 = require("./Color");
|
|
5
|
+
var EMPTY = " * * * * * * * * * ";
|
|
6
|
+
var BOARD3_9 = [
|
|
7
|
+
"-FU-FU-FU-FU-FU-FU-FU-FU-FU",
|
|
8
|
+
EMPTY,
|
|
9
|
+
EMPTY,
|
|
10
|
+
EMPTY,
|
|
11
|
+
"+FU+FU+FU+FU+FU+FU+FU+FU+FU",
|
|
12
|
+
" * +KA * * * * * +HI * ",
|
|
13
|
+
"+KY+KE+GI+KI+OU+KI+GI+KE+KY",
|
|
14
|
+
];
|
|
15
|
+
var BOARD2_9 = [EMPTY].concat(BOARD3_9);
|
|
16
|
+
/**
|
|
17
|
+
* 既定の初期局面
|
|
18
|
+
*/
|
|
19
|
+
var presetDefinitions = {
|
|
20
|
+
HIRATE: {
|
|
21
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE-KY", " * -HI * * * * * -KA * "].concat(BOARD3_9),
|
|
22
|
+
turn: Color_1["default"].Black
|
|
23
|
+
},
|
|
24
|
+
KY: {
|
|
25
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE * ", " * -HI * * * * * -KA * "].concat(BOARD3_9),
|
|
26
|
+
turn: Color_1["default"].White
|
|
27
|
+
},
|
|
28
|
+
KY_R: {
|
|
29
|
+
board: [" * -KE-GI-KI-OU-KI-GI-KE-KY", " * -HI * * * * * -KA * "].concat(BOARD3_9),
|
|
30
|
+
turn: Color_1["default"].White
|
|
31
|
+
},
|
|
32
|
+
KA: {
|
|
33
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE-KY", " * -HI * * * * * * * "].concat(BOARD3_9),
|
|
34
|
+
turn: Color_1["default"].White
|
|
35
|
+
},
|
|
36
|
+
HI: {
|
|
37
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE-KY", " * * * * * * * -KA * "].concat(BOARD3_9),
|
|
38
|
+
turn: Color_1["default"].White
|
|
39
|
+
},
|
|
40
|
+
HIKY: {
|
|
41
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE * ", " * * * * * * * -KA * "].concat(BOARD3_9),
|
|
42
|
+
turn: Color_1["default"].White
|
|
43
|
+
},
|
|
44
|
+
"2": {
|
|
45
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE-KY"].concat(BOARD2_9),
|
|
46
|
+
turn: Color_1["default"].White
|
|
47
|
+
},
|
|
48
|
+
"3": {
|
|
49
|
+
board: ["-KY-KE-GI-KI-OU-KI-GI-KE * "].concat(BOARD2_9),
|
|
50
|
+
turn: Color_1["default"].White
|
|
51
|
+
},
|
|
52
|
+
"4": {
|
|
53
|
+
board: [" * -KE-GI-KI-OU-KI-GI-KE * "].concat(BOARD2_9),
|
|
54
|
+
turn: Color_1["default"].White
|
|
55
|
+
},
|
|
56
|
+
"5": {
|
|
57
|
+
board: [" * * -GI-KI-OU-KI-GI-KE * "].concat(BOARD2_9),
|
|
58
|
+
turn: Color_1["default"].White
|
|
59
|
+
},
|
|
60
|
+
"5_L": {
|
|
61
|
+
board: [" * -KE-GI-KI-OU-KI-GI * * "].concat(BOARD2_9),
|
|
62
|
+
turn: Color_1["default"].White
|
|
63
|
+
},
|
|
64
|
+
"6": {
|
|
65
|
+
board: [" * * -GI-KI-OU-KI-GI * * "].concat(BOARD2_9),
|
|
66
|
+
turn: Color_1["default"].White
|
|
67
|
+
},
|
|
68
|
+
"7_R": {
|
|
69
|
+
board: [" * * * -KI-OU-KI-GI * * "].concat(BOARD2_9),
|
|
70
|
+
turn: Color_1["default"].White
|
|
71
|
+
},
|
|
72
|
+
"7_L": {
|
|
73
|
+
board: [" * * -GI-KI-OU-KI * * * "].concat(BOARD2_9),
|
|
74
|
+
turn: Color_1["default"].White
|
|
75
|
+
},
|
|
76
|
+
"8": {
|
|
77
|
+
board: [" * * * -KI-OU-KI * * * "].concat(BOARD2_9),
|
|
78
|
+
turn: Color_1["default"].White
|
|
79
|
+
},
|
|
80
|
+
"10": {
|
|
81
|
+
board: [" * * * * -OU * * * * "].concat(BOARD2_9),
|
|
82
|
+
turn: Color_1["default"].White
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var getInitialFromPreset = function (preset) {
|
|
86
|
+
var definition = presetDefinitions[preset];
|
|
87
|
+
if (!definition) {
|
|
88
|
+
throw new Error("Unknown preset: ".concat(preset));
|
|
89
|
+
}
|
|
90
|
+
return definition;
|
|
91
|
+
};
|
|
92
|
+
exports.getInitialFromPreset = getInitialFromPreset;
|
|
93
|
+
var presets = Object.keys(presetDefinitions);
|
|
94
|
+
exports["default"] = presets;
|
package/cjs/shogi.js
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.colorToString = exports.kindToString = exports.Piece = exports.Color = exports.Shogi = void 0;
|
|
4
|
+
/** @license
|
|
5
|
+
* Shogi.js
|
|
6
|
+
* Copyright (c) 2014 na2hiro (https://github.com/na2hiro)
|
|
7
|
+
* This software is released under the MIT License.
|
|
8
|
+
* http://opensource.org/licenses/mit-license.php
|
|
9
|
+
*/
|
|
10
|
+
var Color_1 = require("./Color");
|
|
11
|
+
exports.Color = Color_1["default"];
|
|
12
|
+
exports.colorToString = Color_1.colorToString;
|
|
13
|
+
var Kind_1 = require("./Kind");
|
|
14
|
+
exports.kindToString = Kind_1.kindToString;
|
|
15
|
+
var moveDefinitions_1 = require("./moveDefinitions");
|
|
16
|
+
var Piece_1 = require("./Piece");
|
|
17
|
+
exports.Piece = Piece_1["default"];
|
|
18
|
+
require("./polyfills");
|
|
19
|
+
var Serialization_1 = require("./Serialization");
|
|
20
|
+
/**
|
|
21
|
+
* 将棋盤を管理するクラス
|
|
22
|
+
*/
|
|
23
|
+
var Shogi = /** @class */ (function () {
|
|
24
|
+
function Shogi(setting) {
|
|
25
|
+
this.initialize(setting);
|
|
26
|
+
}
|
|
27
|
+
Shogi.getIllegalUnpromotedRow = function (kind) {
|
|
28
|
+
switch (kind) {
|
|
29
|
+
case "FU":
|
|
30
|
+
case "KY":
|
|
31
|
+
return 1;
|
|
32
|
+
case "KE":
|
|
33
|
+
return 2;
|
|
34
|
+
default:
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* 手番の相手側から数えた段数
|
|
40
|
+
*/
|
|
41
|
+
Shogi.getRowToOppositeEnd = function (y, color) {
|
|
42
|
+
return color === Color_1["default"].Black ? y : 10 - y;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 盤面を初期化する
|
|
46
|
+
* @param {ISettingType} setting 初期局面(なければ平手)
|
|
47
|
+
*/
|
|
48
|
+
Shogi.prototype.initialize = function (setting) {
|
|
49
|
+
if (setting === void 0) { setting = { preset: "HIRATE" }; }
|
|
50
|
+
(0, Serialization_1.fromPreset)(this, setting);
|
|
51
|
+
this.flagEditMode = false;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* SFENによる盤面表現の文字列で盤面を初期化する
|
|
55
|
+
* @param {string} sfen
|
|
56
|
+
*/
|
|
57
|
+
Shogi.prototype.initializeFromSFENString = function (sfen) {
|
|
58
|
+
(0, Serialization_1.fromSfen)(this, sfen);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* CSAによる盤面表現の文字列を返す
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
Shogi.prototype.toCSAString = function () {
|
|
65
|
+
return (0, Serialization_1.toCSA)(this);
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* SFENによる盤面表現の文字列を返す
|
|
69
|
+
* @param {number} moveCount
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
Shogi.prototype.toSFENString = function (moveCount) {
|
|
73
|
+
if (moveCount === void 0) { moveCount = 1; }
|
|
74
|
+
return (0, Serialization_1.toSfen)(this, moveCount);
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* 編集モード切り替え
|
|
78
|
+
* * 通常モード:移動時に手番と移動可能かどうかチェックし,移動可能範囲は手番側のみ返す.
|
|
79
|
+
* * 編集モード:移動時に手番や移動可能かはチェックせず,移動可能範囲は両者とも返す.
|
|
80
|
+
*/
|
|
81
|
+
Shogi.prototype.editMode = function (flag) {
|
|
82
|
+
this.flagEditMode = flag;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* (fromx, fromy)から(tox, toy)へ移動し,promoteなら成り,駒を取っていれば持ち駒に加える..
|
|
86
|
+
*/
|
|
87
|
+
Shogi.prototype.move = function (fromx, fromy, tox, toy, promote) {
|
|
88
|
+
if (promote === void 0) { promote = false; }
|
|
89
|
+
var piece = this.get(fromx, fromy);
|
|
90
|
+
if (piece == null) {
|
|
91
|
+
throw new Error("no piece found at " + fromx + ", " + fromy);
|
|
92
|
+
}
|
|
93
|
+
this.checkTurn(piece.color);
|
|
94
|
+
if (!this.flagEditMode) {
|
|
95
|
+
if (!this.getMovesFrom(fromx, fromy).some(function (move) {
|
|
96
|
+
return move.to.x === tox && move.to.y === toy;
|
|
97
|
+
})) {
|
|
98
|
+
throw new Error("cannot move from " + fromx + ", " + fromy + " to " + tox + ", " + toy);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (this.get(tox, toy) != null) {
|
|
102
|
+
this.capture(tox, toy);
|
|
103
|
+
}
|
|
104
|
+
// 行き所のない駒
|
|
105
|
+
var deadEnd = Shogi.getIllegalUnpromotedRow(piece.kind) >=
|
|
106
|
+
Shogi.getRowToOppositeEnd(toy, piece.color);
|
|
107
|
+
if (promote || deadEnd) {
|
|
108
|
+
piece.promote();
|
|
109
|
+
}
|
|
110
|
+
this.set(tox, toy, piece);
|
|
111
|
+
this.set(fromx, fromy, null);
|
|
112
|
+
this.nextTurn();
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* moveの逆を行う.つまり(tox, toy)から(fromx, fromy)へ移動し,駒を取っていたら戻し,promoteなら成りを戻す.
|
|
116
|
+
*/
|
|
117
|
+
Shogi.prototype.unmove = function (fromx, fromy, tox, toy, promote, capture) {
|
|
118
|
+
if (promote === void 0) { promote = false; }
|
|
119
|
+
var piece = this.get(tox, toy);
|
|
120
|
+
if (piece == null) {
|
|
121
|
+
throw new Error("no piece found at " + tox + ", " + toy);
|
|
122
|
+
}
|
|
123
|
+
this.checkTurn(Piece_1["default"].oppositeColor(piece.color));
|
|
124
|
+
var captured;
|
|
125
|
+
if (capture) {
|
|
126
|
+
captured = this.popFromHand(Piece_1["default"].unpromote(capture), piece.color);
|
|
127
|
+
captured.inverse();
|
|
128
|
+
}
|
|
129
|
+
var editMode = this.flagEditMode;
|
|
130
|
+
this.editMode(true);
|
|
131
|
+
this.move(tox, toy, fromx, fromy);
|
|
132
|
+
if (promote) {
|
|
133
|
+
piece.unpromote();
|
|
134
|
+
}
|
|
135
|
+
if (capture) {
|
|
136
|
+
if (Piece_1["default"].isPromoted(capture)) {
|
|
137
|
+
captured.promote();
|
|
138
|
+
}
|
|
139
|
+
this.set(tox, toy, captured);
|
|
140
|
+
}
|
|
141
|
+
this.editMode(editMode);
|
|
142
|
+
this.prevTurn();
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* (tox, toy)へcolorの持ち駒のkindを打つ.
|
|
146
|
+
*/
|
|
147
|
+
Shogi.prototype.drop = function (tox, toy, kind, color) {
|
|
148
|
+
if (color === void 0) { color = this.turn; }
|
|
149
|
+
this.checkTurn(color);
|
|
150
|
+
if (this.get(tox, toy) != null) {
|
|
151
|
+
throw new Error("there is a piece at " + tox + ", " + toy);
|
|
152
|
+
}
|
|
153
|
+
if (!this.getDropsBy(color).some(function (move) {
|
|
154
|
+
return move.to.x === tox && move.to.y === toy && move.kind === kind;
|
|
155
|
+
})) {
|
|
156
|
+
throw new Error("Cannot move");
|
|
157
|
+
}
|
|
158
|
+
var piece = this.popFromHand(kind, color);
|
|
159
|
+
this.set(tox, toy, piece);
|
|
160
|
+
this.nextTurn();
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* dropの逆を行う,つまり(tox, toy)の駒を駒台に戻す.
|
|
164
|
+
*/
|
|
165
|
+
Shogi.prototype.undrop = function (tox, toy) {
|
|
166
|
+
var piece = this.get(tox, toy);
|
|
167
|
+
if (piece == null) {
|
|
168
|
+
throw new Error("there is no piece at " + tox + ", " + toy);
|
|
169
|
+
}
|
|
170
|
+
this.checkTurn(Piece_1["default"].oppositeColor(piece.color));
|
|
171
|
+
this.pushToHand(piece);
|
|
172
|
+
this.set(tox, toy, null);
|
|
173
|
+
this.prevTurn();
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* (x, y)の駒の移動可能な動きをすべて得る
|
|
177
|
+
* 盤外,自分の駒取りは除外.二歩,王手放置などはチェックせず.
|
|
178
|
+
*/
|
|
179
|
+
Shogi.prototype.getMovesFrom = function (x, y) {
|
|
180
|
+
// 盤外かもしれない(x, y)にcolorの駒が移動しても問題がないか
|
|
181
|
+
var legal = function (x, y, color) {
|
|
182
|
+
if (x < 1 || 9 < x || y < 1 || 9 < y) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
var piece = this.get(x, y);
|
|
186
|
+
return piece == null || piece.color !== color;
|
|
187
|
+
}.bind(this);
|
|
188
|
+
var shouldStop = function (x, y, color) {
|
|
189
|
+
var piece = this.get(x, y);
|
|
190
|
+
return piece != null && piece.color !== color;
|
|
191
|
+
}.bind(this);
|
|
192
|
+
var piece = this.get(x, y);
|
|
193
|
+
if (piece == null) {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
var moveDef = (0, moveDefinitions_1.getMoveDefinitions)(piece.kind);
|
|
197
|
+
var ret = [];
|
|
198
|
+
var from = { x: x, y: y };
|
|
199
|
+
var unit = piece.color === Color_1["default"].Black ? 1 : -1;
|
|
200
|
+
if (moveDef.just) {
|
|
201
|
+
for (var _i = 0, _a = moveDef.just; _i < _a.length; _i++) {
|
|
202
|
+
var def = _a[_i];
|
|
203
|
+
var to = { x: from.x + def[0] * unit, y: from.y + def[1] * unit };
|
|
204
|
+
if (legal(to.x, to.y, piece.color)) {
|
|
205
|
+
ret.push({ from: from, to: to });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (moveDef.fly) {
|
|
210
|
+
for (var _b = 0, _c = moveDef.fly; _b < _c.length; _b++) {
|
|
211
|
+
var def = _c[_b];
|
|
212
|
+
var to = { x: from.x + def[0] * unit, y: from.y + def[1] * unit };
|
|
213
|
+
while (legal(to.x, to.y, piece.color)) {
|
|
214
|
+
ret.push({ from: from, to: { x: to.x, y: to.y } });
|
|
215
|
+
if (shouldStop(to.x, to.y, piece.color)) {
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
to.x += def[0] * unit;
|
|
219
|
+
to.y += def[1] * unit;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return ret;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* colorが打てる動きを全て得る
|
|
227
|
+
*/
|
|
228
|
+
Shogi.prototype.getDropsBy = function (color) {
|
|
229
|
+
var ret = [];
|
|
230
|
+
var places = [];
|
|
231
|
+
var fuExistsArray = [];
|
|
232
|
+
for (var i = 1; i <= 9; i++) {
|
|
233
|
+
var fuExists = false;
|
|
234
|
+
for (var j = 1; j <= 9; j++) {
|
|
235
|
+
var piece = this.get(i, j);
|
|
236
|
+
if (piece == null) {
|
|
237
|
+
places.push({ x: i, y: j });
|
|
238
|
+
}
|
|
239
|
+
else if (piece.color === color && piece.kind === "FU") {
|
|
240
|
+
fuExists = true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
fuExistsArray.push(fuExists);
|
|
244
|
+
}
|
|
245
|
+
var done = {};
|
|
246
|
+
for (var _i = 0, _a = this.hands[color]; _i < _a.length; _i++) {
|
|
247
|
+
var hand = _a[_i];
|
|
248
|
+
var kind = hand.kind;
|
|
249
|
+
if (done[kind]) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
done[kind] = true;
|
|
253
|
+
var illegalUnpromotedRow = Shogi.getIllegalUnpromotedRow(kind);
|
|
254
|
+
for (var _b = 0, places_1 = places; _b < places_1.length; _b++) {
|
|
255
|
+
var place = places_1[_b];
|
|
256
|
+
if (kind === "FU" && fuExistsArray[place.x - 1]) {
|
|
257
|
+
continue; // 二歩
|
|
258
|
+
}
|
|
259
|
+
if (illegalUnpromotedRow >= Shogi.getRowToOppositeEnd(place.y, color)) {
|
|
260
|
+
continue; // 行き所のない駒
|
|
261
|
+
}
|
|
262
|
+
ret.push({ to: place, color: color, kind: kind });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return ret;
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* (x, y)に行けるcolor側のkindの駒の動きを得る
|
|
269
|
+
*/
|
|
270
|
+
Shogi.prototype.getMovesTo = function (x, y, kind, color) {
|
|
271
|
+
if (color === void 0) { color = this.turn; }
|
|
272
|
+
var to = { x: x, y: y };
|
|
273
|
+
var ret = [];
|
|
274
|
+
for (var i = 1; i <= 9; i++) {
|
|
275
|
+
for (var j = 1; j <= 9; j++) {
|
|
276
|
+
var piece = this.get(i, j);
|
|
277
|
+
if (!piece || piece.kind !== kind || piece.color !== color) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
var moves = this.getMovesFrom(i, j);
|
|
281
|
+
if (moves.some(function (move) { return move.to.x === x && move.to.y === y; })) {
|
|
282
|
+
ret.push({ from: { x: i, y: j }, to: to });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return ret;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* (x, y)の駒を得る
|
|
290
|
+
*/
|
|
291
|
+
Shogi.prototype.get = function (x, y) {
|
|
292
|
+
return this.board[x - 1][y - 1];
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* keyを種類,valueを枚数とするオブジェクトとして持ち駒の枚数一覧を返す.
|
|
296
|
+
*/
|
|
297
|
+
Shogi.prototype.getHandsSummary = function (color) {
|
|
298
|
+
var ret = {
|
|
299
|
+
FU: 0,
|
|
300
|
+
KY: 0,
|
|
301
|
+
KE: 0,
|
|
302
|
+
GI: 0,
|
|
303
|
+
KI: 0,
|
|
304
|
+
KA: 0,
|
|
305
|
+
HI: 0
|
|
306
|
+
};
|
|
307
|
+
for (var _i = 0, _a = this.hands[color]; _i < _a.length; _i++) {
|
|
308
|
+
var hand = _a[_i];
|
|
309
|
+
ret[hand.kind]++;
|
|
310
|
+
}
|
|
311
|
+
return ret;
|
|
312
|
+
};
|
|
313
|
+
// 以下editModeでの関数
|
|
314
|
+
/**
|
|
315
|
+
* (x, y)の駒を取ってcolorの持ち駒に加える
|
|
316
|
+
*/
|
|
317
|
+
Shogi.prototype.captureByColor = function (x, y, color) {
|
|
318
|
+
if (!this.flagEditMode) {
|
|
319
|
+
throw new Error("cannot edit board without editMode");
|
|
320
|
+
}
|
|
321
|
+
var piece = this.get(x, y);
|
|
322
|
+
this.set(x, y, null);
|
|
323
|
+
piece.unpromote();
|
|
324
|
+
if (piece.color !== color) {
|
|
325
|
+
piece.inverse();
|
|
326
|
+
}
|
|
327
|
+
this.pushToHand(piece);
|
|
328
|
+
};
|
|
329
|
+
/**
|
|
330
|
+
* (x, y)の駒をフリップする(先手→先手成→後手→後手成→)
|
|
331
|
+
* 成功したらtrueを返す
|
|
332
|
+
*/
|
|
333
|
+
Shogi.prototype.flip = function (x, y) {
|
|
334
|
+
if (!this.flagEditMode) {
|
|
335
|
+
throw new Error("cannot edit board without editMode");
|
|
336
|
+
}
|
|
337
|
+
var piece = this.get(x, y);
|
|
338
|
+
if (!piece) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
if (Piece_1["default"].isPromoted(piece.kind)) {
|
|
342
|
+
piece.unpromote();
|
|
343
|
+
piece.inverse();
|
|
344
|
+
}
|
|
345
|
+
else if (Piece_1["default"].canPromote(piece.kind)) {
|
|
346
|
+
piece.promote();
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
piece.inverse();
|
|
350
|
+
}
|
|
351
|
+
return true;
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* 手番を設定する
|
|
355
|
+
*/
|
|
356
|
+
Shogi.prototype.setTurn = function (color) {
|
|
357
|
+
if (!this.flagEditMode) {
|
|
358
|
+
throw new Error("cannot set turn without editMode");
|
|
359
|
+
}
|
|
360
|
+
this.turn = color;
|
|
361
|
+
};
|
|
362
|
+
// 以下private method
|
|
363
|
+
/**
|
|
364
|
+
* (x, y)に駒を置く
|
|
365
|
+
*/
|
|
366
|
+
Shogi.prototype.set = function (x, y, piece) {
|
|
367
|
+
this.board[x - 1][y - 1] = piece;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* (x, y)の駒を取って反対側の持ち駒に加える
|
|
371
|
+
*/
|
|
372
|
+
Shogi.prototype.capture = function (x, y) {
|
|
373
|
+
var piece = this.get(x, y);
|
|
374
|
+
this.set(x, y, null);
|
|
375
|
+
piece.unpromote();
|
|
376
|
+
piece.inverse();
|
|
377
|
+
this.pushToHand(piece);
|
|
378
|
+
};
|
|
379
|
+
/**
|
|
380
|
+
* 駒pieceを持ち駒に加える
|
|
381
|
+
*/
|
|
382
|
+
Shogi.prototype.pushToHand = function (piece) {
|
|
383
|
+
this.hands[piece.color].push(piece);
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* color側のkindの駒を取って返す
|
|
387
|
+
*/
|
|
388
|
+
Shogi.prototype.popFromHand = function (kind, color) {
|
|
389
|
+
var hand = this.hands[color];
|
|
390
|
+
for (var i = 0; i < hand.length; i++) {
|
|
391
|
+
if (hand[i].kind !== kind) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
var piece = hand[i];
|
|
395
|
+
hand.splice(i, 1); // remove at i
|
|
396
|
+
return piece;
|
|
397
|
+
}
|
|
398
|
+
throw new Error(color + " has no " + kind);
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* 次の手番に行く
|
|
402
|
+
*/
|
|
403
|
+
Shogi.prototype.nextTurn = function () {
|
|
404
|
+
if (this.flagEditMode) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
this.turn = this.turn === Color_1["default"].Black ? Color_1["default"].White : Color_1["default"].Black;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* 前の手番に行く
|
|
411
|
+
*/
|
|
412
|
+
Shogi.prototype.prevTurn = function () {
|
|
413
|
+
if (this.flagEditMode) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
this.nextTurn();
|
|
417
|
+
};
|
|
418
|
+
/**
|
|
419
|
+
* colorの手番で問題ないか確認する.編集モードならok.
|
|
420
|
+
*/
|
|
421
|
+
Shogi.prototype.checkTurn = function (color) {
|
|
422
|
+
if (!this.flagEditMode && color !== this.turn) {
|
|
423
|
+
throw new Error("cannot move opposite piece");
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
return Shogi;
|
|
427
|
+
}());
|
|
428
|
+
exports.Shogi = Shogi;
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shogi.js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "simple shogi library for JavaScript",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
5
|
+
"main": "cjs/shogi.js",
|
|
6
|
+
"types": "cjs/shogi.d.ts",
|
|
7
7
|
"directories": {
|
|
8
8
|
"test": "test"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"clean": "rm -rf ./dist ./bundle",
|
|
12
|
-
"build": "
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"build": "npm run build:cjs && npm run bundle",
|
|
13
|
+
"bundle": "webpack --mode=production",
|
|
14
|
+
"bundle:analyze": "webpack --mode=production --env analyze=1",
|
|
15
|
+
"bundle:watch": "webpack --mode=development --watch",
|
|
16
|
+
"build:cjs": "tsc",
|
|
15
17
|
"lint": "eslint ./ && prettier --check .",
|
|
16
18
|
"lint:fix": "eslint ./ --fix && prettier --write .",
|
|
17
19
|
"test": "jest",
|
|
@@ -37,5 +39,5 @@
|
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"ts-jest": "^27.1.3"
|
|
39
41
|
},
|
|
40
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "78f7c3df433b0f9718b099359768c4b149d1b724"
|
|
41
43
|
}
|
package/dist/shogi.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! For license information please see shogi.js.LICENSE.txt */
|
|
2
|
-
(()=>{"use strict";var t={371:(t,o)=>{var r;Object.defineProperty(o,"__esModule",{value:!0}),o.colorToString=void 0,function(t){t[t.Black=0]="Black",t[t.White=1]="White"}(r||(r={})),o.default=r,o.colorToString=function(t){switch(t){case r.Black:return"先手";case r.White:return"後手"}}},825:(t,o)=>{var r;Object.defineProperty(o,"__esModule",{value:!0}),o.kindToString=o.values=void 0,function(t){t[t.FU=0]="FU",t[t.KY=1]="KY",t[t.KE=2]="KE",t[t.GI=3]="GI",t[t.KI=4]="KI",t[t.KA=5]="KA",t[t.HI=6]="HI",t[t.OU=7]="OU",t[t.TO=8]="TO",t[t.NY=9]="NY",t[t.NK=10]="NK",t[t.NG=11]="NG",t[t.UM=12]="UM",t[t.RY=13]="RY"}(r||(r={})),o.values=Object.keys(r).filter((function(t){return Number.isNaN(parseInt(t))})),o.kindToString=function(t){return{FU:"歩",KY:"香",KE:"桂",GI:"銀",KI:"金",KA:"角",HI:"飛",OU:"玉",TO:"と",NY:"成香",NK:"成桂",NG:"成銀",UM:"馬",RY:"龍"}[t]}},51:(t,o,r)=>{Object.defineProperty(o,"__esModule",{value:!0});var e=r(371),n=function(){function t(t){this.color="+"===t.slice(0,1)?e.default.Black:e.default.White,this.kind=t.slice(1)}return t.promote=function(t){return{FU:"TO",KY:"NY",KE:"NK",GI:"NG",KA:"UM",HI:"RY"}[t]||t},t.unpromote=function(t){return{TO:"FU",NY:"KY",NK:"KE",NG:"GI",KI:"KI",UM:"KA",RY:"HI",OU:"OU"}[t]||t},t.canPromote=function(o){return t.promote(o)!==o},t.isPromoted=function(t){return["TO","NY","NK","NG","UM","RY"].indexOf(t)>=0},t.oppositeColor=function(t){return t===e.default.Black?e.default.White:e.default.Black},t.fromSFENString=function(o){var r="+"===o[0];r&&(o=o.slice(1));var e=new t((o.match(/[A-Z]/)?"+":"-")+{P:"FU",L:"KY",N:"KE",S:"GI",G:"KI",B:"KA",R:"HI",K:"OU"}[o.toUpperCase()]);return r&&e.promote(),e},t.prototype.promote=function(){this.kind=t.promote(this.kind)},t.prototype.unpromote=function(){this.kind=t.unpromote(this.kind)},t.prototype.inverse=function(){this.color=this.color===e.default.Black?e.default.White:e.default.Black},t.prototype.toCSAString=function(){return(this.color===e.default.Black?"+":"-")+this.kind},t.prototype.toSFENString=function(){var o={FU:"P",KY:"L",KE:"N",GI:"S",KI:"G",KA:"B",HI:"R",OU:"K"}[t.unpromote(this.kind)];return(t.isPromoted(this.kind)?"+":"")+(this.color===e.default.Black?o:o.toLowerCase())},t}();o.default=n},297:(t,o,r)=>{Object.defineProperty(o,"__esModule",{value:!0}),o.toSfen=o.fromSfen=o.toCSA=o.fromPreset=void 0;var e=r(371),n=r(446),i=r(51);o.fromPreset=function(t,o){var r,u=[],a=[[],[]];if("OTHER"!==o.preset){for(var f=(0,n.getInitialFromPreset)(o.preset),l=0;l<9;l++){u[l]=[];for(var s=0;s<9;s++){var d=f.board[s].slice(24-3*l,24-3*l+3);u[l][s]=" * "===d?null:new i.default(d)}}r=f.turn}else{for(l=0;l<9;l++)for(u[l]=[],s=0;s<9;s++){var c=o.data.board[l][s];u[l][s]=c.kind?new i.default((c.color===e.default.Black?"+":"-")+c.kind):null}r=o.data.color;for(var h=0;h<2;h++)for(var p in o.data.hands[h])if(o.data.hands[h].hasOwnProperty(p))for(d=(0===h?"+":"-")+p,l=0;l<o.data.hands[h][p];l++)a[h].push(new i.default(d))}t.board=u,t.turn=r,t.hands=a},o.toCSA=function(t){for(var o=[],r=0;r<9;r++){for(var n="P"+(r+1),i=8;i>=0;i--){var u=t.board[i][r];n+=null==u?" * ":u.toCSAString()}o.push(n)}for(var a=0;a<2;a++){n="P"+"+-"[a];for(var f=0,l=t.hands[a];f<l.length;f++)n+="00"+l[f].kind;o.push(n)}return o.push(t.turn===e.default.Black?"+":"-"),o.join("\n")},o.fromSfen=function(t,o){for(var r=[],n=0;n<9;n++){r[n]=[];for(var u=0;u<9;u++)r[n][u]=null}var a=o.split(" "),f=a[0],l=8,s=0;for(n=0;n<f.length;n++){var d=f[n];"+"===d&&(d+=f[++n]),d.match(/^[1-9]$/)?l-=Number(d):"/"===d?(s++,l=8):(r[l][s]=i.default.fromSFENString(d),l--)}t.board=r,t.turn="b"===a[1]?e.default.Black:e.default.White;var c=[[],[]],h=a[2];if("-"!==h)for(;h.length>0;){var p=1,K=h.match(/^[0-9]+/);for(K&&(p=Number(K[0]),h=h.slice(K[0].length)),n=0;n<p;n++){var v=i.default.fromSFENString(h[0]);c[v.color].push(v)}h=h.slice(1)}t.hands=c},o.toSfen=function(t,o){for(var r=[],n=[],i=0;i<9;i++){for(var u="",a=0,f=8;f>=0;f--){var l=t.board[f][i];null==l?a++:(a>0&&(u+=""+a,a=0),u+=l.toSFENString())}a>0&&(u+=""+a),n.push(u)}if(r.push(n.join("/")),r.push(t.turn===e.default.Black?"b":"w"),0===t.hands[0].length&&0===t.hands[1].length)r.push("-");else{for(var s="",d={},c=0;c<2;c++)for(var h=0,p=t.hands[c];h<p.length;h++){var K=p[h].toSFENString();d[K]=(d[K]||0)+1}for(var v=0,I=["R","B","G","S","N","L","P","r","b","g","s","n","l","p"];v<I.length;v++){var g=I[v];d[g]>0&&(s+=(d[g]>1?d[g]:"")+g)}r.push(s)}return r.push(""+o),r.join(" ")}},333:(t,o)=>{Object.defineProperty(o,"__esModule",{value:!0}),o.getMoveDefinitions=void 0;var r=[0,-1],e=[0,1],n=[1,0],i=[-1,0],u=[-1,-1],a=[1,-1],f=[-1,1],l=[1,1],s={just:[u,r,a,i,n,e]},d={FU:{just:[r]},KY:{fly:[r]},KE:{just:[[-1,-2],[1,-2]]},GI:{just:[u,r,a,f,l]},KI:s,TO:s,NY:s,NK:s,NG:s,KA:{fly:[u,a,f,l]},HI:{fly:[r,i,n,e]},OU:{just:[u,r,a,i,n,f,e,l]},UM:{fly:[u,a,f,l],just:[r,i,n,e]},RY:{fly:[r,i,n,e],just:[u,a,f,l]}};o.getMoveDefinitions=function(t){return d[t]}},31:(t,o)=>{Object.defineProperty(o,"__esModule",{value:!0}),Array.prototype.some||(Array.prototype.some=function(t){if(null==this)throw new TypeError;var o=Object(this),r=o.length>>>0;if("function"!=typeof t)throw new TypeError;for(var e=arguments[1],n=0;n<r;n++)if(n in o&&t.call(e,o[n],n,o))return!0;return!1})},446:(t,o,r)=>{Object.defineProperty(o,"__esModule",{value:!0}),o.getInitialFromPreset=void 0;var e=r(371),n=" * * * * * * * * * ",i=["-FU-FU-FU-FU-FU-FU-FU-FU-FU",n,n,n,"+FU+FU+FU+FU+FU+FU+FU+FU+FU"," * +KA * * * * * +HI * ","+KY+KE+GI+KI+OU+KI+GI+KE+KY"],u=[n].concat(i),a={HIRATE:{board:["-KY-KE-GI-KI-OU-KI-GI-KE-KY"," * -HI * * * * * -KA * "].concat(i),turn:e.default.Black},KY:{board:["-KY-KE-GI-KI-OU-KI-GI-KE * "," * -HI * * * * * -KA * "].concat(i),turn:e.default.White},KY_R:{board:[" * -KE-GI-KI-OU-KI-GI-KE-KY"," * -HI * * * * * -KA * "].concat(i),turn:e.default.White},KA:{board:["-KY-KE-GI-KI-OU-KI-GI-KE-KY"," * -HI * * * * * * * "].concat(i),turn:e.default.White},HI:{board:["-KY-KE-GI-KI-OU-KI-GI-KE-KY"," * * * * * * * -KA * "].concat(i),turn:e.default.White},HIKY:{board:["-KY-KE-GI-KI-OU-KI-GI-KE * "," * * * * * * * -KA * "].concat(i),turn:e.default.White},2:{board:["-KY-KE-GI-KI-OU-KI-GI-KE-KY"].concat(u),turn:e.default.White},3:{board:["-KY-KE-GI-KI-OU-KI-GI-KE * "].concat(u),turn:e.default.White},4:{board:[" * -KE-GI-KI-OU-KI-GI-KE * "].concat(u),turn:e.default.White},5:{board:[" * * -GI-KI-OU-KI-GI-KE * "].concat(u),turn:e.default.White},"5_L":{board:[" * -KE-GI-KI-OU-KI-GI * * "].concat(u),turn:e.default.White},6:{board:[" * * -GI-KI-OU-KI-GI * * "].concat(u),turn:e.default.White},"7_R":{board:[" * * * -KI-OU-KI-GI * * "].concat(u),turn:e.default.White},"7_L":{board:[" * * -GI-KI-OU-KI * * * "].concat(u),turn:e.default.White},8:{board:[" * * * -KI-OU-KI * * * "].concat(u),turn:e.default.White},10:{board:[" * * * * -OU * * * * "].concat(u),turn:e.default.White}};o.getInitialFromPreset=function(t){var o=a[t];if(!o)throw new Error("Unknown preset: ".concat(t));return o};var f=Object.keys(a);o.default=f}},o={};function r(e){var n=o[e];if(void 0!==n)return n.exports;var i=o[e]={exports:{}};return t[e](i,i.exports,r),i.exports}var e={};(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.colorToString=t.kindToString=t.Piece=t.Color=t.Shogi=void 0;var o=r(371);t.Color=o.default,Object.defineProperty(t,"colorToString",{enumerable:!0,get:function(){return o.colorToString}});var n=r(825);Object.defineProperty(t,"kindToString",{enumerable:!0,get:function(){return n.kindToString}});var i=r(333),u=r(51);t.Piece=u.default,r(31);var a=r(297),f=function(){function t(t){this.initialize(t)}return t.getIllegalUnpromotedRow=function(t){switch(t){case"FU":case"KY":return 1;case"KE":return 2;default:return 0}},t.getRowToOppositeEnd=function(t,r){return r===o.default.Black?t:10-t},t.prototype.initialize=function(t){void 0===t&&(t={preset:"HIRATE"}),(0,a.fromPreset)(this,t),this.flagEditMode=!1},t.prototype.initializeFromSFENString=function(t){(0,a.fromSfen)(this,t)},t.prototype.toCSAString=function(){return(0,a.toCSA)(this)},t.prototype.toSFENString=function(t){return void 0===t&&(t=1),(0,a.toSfen)(this,t)},t.prototype.editMode=function(t){this.flagEditMode=t},t.prototype.move=function(o,r,e,n,i){void 0===i&&(i=!1);var u=this.get(o,r);if(null==u)throw new Error("no piece found at "+o+", "+r);if(this.checkTurn(u.color),!this.flagEditMode&&!this.getMovesFrom(o,r).some((function(t){return t.to.x===e&&t.to.y===n})))throw new Error("cannot move from "+o+", "+r+" to "+e+", "+n);null!=this.get(e,n)&&this.capture(e,n);var a=t.getIllegalUnpromotedRow(u.kind)>=t.getRowToOppositeEnd(n,u.color);(i||a)&&u.promote(),this.set(e,n,u),this.set(o,r,null),this.nextTurn()},t.prototype.unmove=function(t,o,r,e,n,i){void 0===n&&(n=!1);var a,f=this.get(r,e);if(null==f)throw new Error("no piece found at "+r+", "+e);this.checkTurn(u.default.oppositeColor(f.color)),i&&(a=this.popFromHand(u.default.unpromote(i),f.color)).inverse();var l=this.flagEditMode;this.editMode(!0),this.move(r,e,t,o),n&&f.unpromote(),i&&(u.default.isPromoted(i)&&a.promote(),this.set(r,e,a)),this.editMode(l),this.prevTurn()},t.prototype.drop=function(t,o,r,e){if(void 0===e&&(e=this.turn),this.checkTurn(e),null!=this.get(t,o))throw new Error("there is a piece at "+t+", "+o);if(!this.getDropsBy(e).some((function(e){return e.to.x===t&&e.to.y===o&&e.kind===r})))throw new Error("Cannot move");var n=this.popFromHand(r,e);this.set(t,o,n),this.nextTurn()},t.prototype.undrop=function(t,o){var r=this.get(t,o);if(null==r)throw new Error("there is no piece at "+t+", "+o);this.checkTurn(u.default.oppositeColor(r.color)),this.pushToHand(r),this.set(t,o,null),this.prevTurn()},t.prototype.getMovesFrom=function(t,r){var e=function(t,o,r){if(t<1||9<t||o<1||9<o)return!1;var e=this.get(t,o);return null==e||e.color!==r}.bind(this),n=function(t,o,r){var e=this.get(t,o);return null!=e&&e.color!==r}.bind(this),u=this.get(t,r);if(null==u)return[];var a=(0,i.getMoveDefinitions)(u.kind),f=[],l={x:t,y:r},s=u.color===o.default.Black?1:-1;if(a.just)for(var d=0,c=a.just;d<c.length;d++){var h=c[d];e((v={x:l.x+h[0]*s,y:l.y+h[1]*s}).x,v.y,u.color)&&f.push({from:l,to:v})}if(a.fly)for(var p=0,K=a.fly;p<K.length;p++){h=K[p];for(var v={x:l.x+h[0]*s,y:l.y+h[1]*s};e(v.x,v.y,u.color)&&(f.push({from:l,to:{x:v.x,y:v.y}}),!n(v.x,v.y,u.color));)v.x+=h[0]*s,v.y+=h[1]*s}return f},t.prototype.getDropsBy=function(o){for(var r=[],e=[],n=[],i=1;i<=9;i++){for(var u=!1,a=1;a<=9;a++){var f=this.get(i,a);null==f?e.push({x:i,y:a}):f.color===o&&"FU"===f.kind&&(u=!0)}n.push(u)}for(var l={},s=0,d=this.hands[o];s<d.length;s++){var c=d[s].kind;if(!l[c]){l[c]=!0;for(var h=t.getIllegalUnpromotedRow(c),p=0,K=e;p<K.length;p++){var v=K[p];"FU"===c&&n[v.x-1]||h>=t.getRowToOppositeEnd(v.y,o)||r.push({to:v,color:o,kind:c})}}}return r},t.prototype.getMovesTo=function(t,o,r,e){void 0===e&&(e=this.turn);for(var n={x:t,y:o},i=[],u=1;u<=9;u++)for(var a=1;a<=9;a++){var f=this.get(u,a);f&&f.kind===r&&f.color===e&&this.getMovesFrom(u,a).some((function(r){return r.to.x===t&&r.to.y===o}))&&i.push({from:{x:u,y:a},to:n})}return i},t.prototype.get=function(t,o){return this.board[t-1][o-1]},t.prototype.getHandsSummary=function(t){for(var o={FU:0,KY:0,KE:0,GI:0,KI:0,KA:0,HI:0},r=0,e=this.hands[t];r<e.length;r++)o[e[r].kind]++;return o},t.prototype.captureByColor=function(t,o,r){if(!this.flagEditMode)throw new Error("cannot edit board without editMode");var e=this.get(t,o);this.set(t,o,null),e.unpromote(),e.color!==r&&e.inverse(),this.pushToHand(e)},t.prototype.flip=function(t,o){if(!this.flagEditMode)throw new Error("cannot edit board without editMode");var r=this.get(t,o);return!!r&&(u.default.isPromoted(r.kind)?(r.unpromote(),r.inverse()):u.default.canPromote(r.kind)?r.promote():r.inverse(),!0)},t.prototype.setTurn=function(t){if(!this.flagEditMode)throw new Error("cannot set turn without editMode");this.turn=t},t.prototype.set=function(t,o,r){this.board[t-1][o-1]=r},t.prototype.capture=function(t,o){var r=this.get(t,o);this.set(t,o,null),r.unpromote(),r.inverse(),this.pushToHand(r)},t.prototype.pushToHand=function(t){this.hands[t.color].push(t)},t.prototype.popFromHand=function(t,o){for(var r=this.hands[o],e=0;e<r.length;e++)if(r[e].kind===t){var n=r[e];return r.splice(e,1),n}throw new Error(o+" has no "+t)},t.prototype.nextTurn=function(){this.flagEditMode||(this.turn=this.turn===o.default.Black?o.default.White:o.default.Black)},t.prototype.prevTurn=function(){this.flagEditMode||this.nextTurn()},t.prototype.checkTurn=function(t){if(!this.flagEditMode&&t!==this.turn)throw new Error("cannot move opposite piece")},t}();t.Shogi=f})(),module.exports=e})();
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|