1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 | // ECMAScript 5 strict mode
/* jshint globalstrict: true*/
/* global WHITE,BLACK */
"use strict";
(function() {
/*
var WHITE = 1;
var BLACK = 0;
*/
function Move(piece,color,from,to,promotion,result,str) {
this.piece = piece ? piece : "P";
this.color = color;
this.from = from;
this.to = to;
this.promotion = promotion;
this.result = result;
this.str = str;
}
String.prototype.removeBrackets = function(open,close) {
var count = 0;
var newString = "";
for (var i = 0; i < this.length; i++) {
var c = this.charAt(i);
if (c === open) {
count++;
continue;
}
if (c === close) {
count--;
continue;
}
if (count === 0) {
newString += c;
}
}
return newString;
};
function parsePGN(pgn) {
var moves = {};
moves.fen = null;
moves.sequence = [];
moves.startColor = WHITE;
var color = WHITE;
//var re_fen = /[pnbrqkPNBRQK1-8]+(\/[pnbrqkPNBRQK1-8]+){7} +[wb] +([KQ]{1,2}|-) *([kq]{1,2}|-)( +(([a-h][1-8])|-))? +\d+ +\d+/
var re_fen = /\[FEN *" *([pnbrqkPNBRQK1-8]+(?:\/[pnbrqkPNBRQK1-8]+){7} +([wb]) +(?:[KQ]{1,2}|-) *(?:[kq]{1,2}|-)(?: +(?:(?:[a-h][1-8])|-))? +\d+ +\d+) *" *\]/;
var match = pgn.match(re_fen);
if (match) {
moves.fen = match[1];
color = match[2] === "w" ? WHITE : BLACK;
moves.startColor = color;
}
var cleanPGN = pgn
.removeBrackets("[","]") // removes metadata
.removeBrackets("{","}") // removes comments
.removeBrackets("(",")") // removes comments
.replace(/\$\d+/g,'') // removes this thing
.replace(/\d+\.{1,3}/g,'') // removes move numbers
.replace(/\s+/g,' ') // replaces multiple whitespaces by simple spaces
.trim() // removes front and back whitespaces
.replace(/(0-1)$/g,'') // result black won
.replace(/(1-0)$/g,'') // result white won
.replace(/(1\/2-1\/2)$/g,'') // result draw
.replace(/(\*)$/g,'') // result ongoing
.trim()
.split(' '); // split moves
// regex for basic moves
// |pieces | |src col/row| |dest col/row| promo |check|
var re_pieceMove =/^([NBRQK])?([a-h]?[1-8]?)?x?([a-h][1-8])(=[NBRQK])?([+#])?/;
// regex for castling
var re_castling = "(O-O(?:-O)?)([+#])?";
var castling = {
"O-O" : {
from:['e8','e1'],
to:['g8','g1']
},
"O-O-O": {
from:['e8','e1'],
to:['c8','c1']
}
};
cleanPGN.forEach(function(move) {
var info=[];
info = move.match(re_pieceMove);
if(info) {
moves.sequence.push(new Move(
info[1],
color,
info[2],
info[3],
info[4],
info[5],
move
));
}
info = move.match(re_castling);
if(info) {
moves.sequence.push(new Move(
"K",
color,
castling[info[1]].from[color],
castling[info[1]].to[color],
undefined,
info[2],
move
));
}
color = 1-color;
});
return moves;
}
window.parsePGN = parsePGN;
})();
|