1 /* 2 * Copyright (c) 2014-2015 Nonki Takahashi. All rights reserved. 3 * 4 * History: 5 * 0.3 2015-10-26 Bug fixed of origin in toSGF and date in genSGFname, toSGF. 6 * 0.2 2014-03-28 Bug fixed in Entry and toSGF. 7 * 0.1 2014-01-28 Created. Ported from GoSimulator03.smallbasic . 8 */ 9 10 /** 11 * @fileOverview Rec - Game Record Object 12 * @version 0.3 13 * @author Nonki Takahashi 14 */ 15 16 /** 17 * Record Entry 18 * @example 19 * var e1 = new Entry(3, 4, BLACK); // col = 3, row = 4, turn = BLACK 20 * var e2 = new Entry(PASS, BLACK); // means pass for BLACK 21 * var e3 = new Entry(new Move(1, 2), WHITE); // col = 1, row = 2, turn = WHITE 22 * @class Represents Game Record Entry 23 * @this {Entry} 24 * @property {Number} x column co-ordinate of move (1 origin) 25 * @property {Number} y row co-ordinate of move (1 origin) 26 * @property {Number} turn turn BLACK or WHITE 27 * @since 0.1 28 */ 29 Entry = function() { 30 if (arguments.length == 3) { 31 this.mv = new Move(arguments[0], arguments[1]); 32 this.turn = arguments[2]; 33 } else if (arguments.length == 2) { 34 if (arguments[0] == PASS) { 35 this.mv = new Move(PASS); 36 this.turn = arguments[1]; 37 } else if (arguments[0] instanceof Object) { 38 this.mv = arguments[0]; 39 this.turn = arguments[1]; 40 } 41 } 42 }; 43 44 /** 45 * Game Record Object 46 * @example 47 * var rec1 = new Rec(sgfString); // src = sgfString 48 * var rec2 = new Rec(19); // ro = 19 49 * @class Represents Game Record Object 50 * @this {Rec} 51 * @property {Number} ro number of lines on board 52 * @property {String[]} players names of players 53 * @property {Number} numMove number of moves 54 * @property {Entry[]} record game record 55 * @property {String} score score string of the game 56 * @property {Number} ptr pointer for replay 57 * @since 0.1 58 */ 59 Rec = function() { 60 if ( typeof arguments[0] == "number") { 61 this.ro = arguments[0]; 62 this.players = ["CPU", "CPU"]; 63 this.numMove = 0; 64 this.score = "0"; 65 this.record = []; 66 this.ptr = 0; 67 this.from = BLACK; 68 this.turn = BLACK; 69 this.date = new Date(); 70 } else if ( typeof arguments[0] == "string") { 71 this.players = []; 72 this.record = []; 73 var parser = new SGFParser(arguments[0], this); 74 parser.Collection(); 75 } 76 }; 77 78 Rec.prototype = { 79 80 /** 81 * Generate SGF File Name 82 * @return {String} SGF file name 83 * @since 0.1 84 */ 85 genSGFname : function() { 86 var d = this.date; 87 var fname = d.getFullYear().toString(); 88 if ((d.getMonth() + 1).toString().length == 1) 89 fname += "0"; 90 fname += (d.getMonth() + 1).toString(); 91 if (d.getDate().toString().length == 1) 92 fname += "0"; 93 fname += d.getDate().toString(); 94 fname += "_"; 95 if (d.getHours().toString().length == 1) 96 fname += "0"; 97 fname += d.getHours().toString(); 98 if (d.getMinutes().toString().length == 1) 99 fname += "0"; 100 fname += d.getMinutes().toString(); 101 if (d.getSeconds().toString().length == 1) 102 fname += "0"; 103 fname += d.getSeconds().toString(); 104 fname += "_"; 105 fname += this.ro.toString(); 106 fname += this.players[P_BLACK].charAt(0); 107 fname += this.players[P_WHITE].charAt(0); 108 fname += this.numMove; 109 if (this.score == "0") 110 fname += "D"; 111 else { 112 fname += this.score.charAt(0); 113 fname += this.score.substr(2); 114 } 115 fname += ".sgf"; 116 return fname; 117 }, 118 119 /** 120 * Rewind 121 * @since 0.1 122 */ 123 rewind : function() { 124 this.ptr = 0; 125 this.turn = this.from; 126 }, 127 128 /** 129 * Replay - get next move from record 130 * @return {Move} next move 131 * @since 0.1 132 */ 133 replay : function() { 134 return this.record[this.ptr++].mv; 135 }, 136 137 /** 138 * End of data 139 * @return {Boolean} true if end of data 140 * @since 0.1 141 */ 142 eod : function() { 143 return (this.record.length <= this.ptr); 144 }, 145 146 /** 147 * Add a move to record 148 * @example 149 * move(col, row); 150 * move(PASS); 151 * move(new Move(col, row)); 152 * @since 0.1 153 */ 154 move : function() { 155 var entry; 156 if (arguments.length == 2) 157 entry = new Entry(arguments[0], arguments[1], this.turn); 158 else 159 entry = new Entry(arguments[0], this.turn); 160 var numRec = this.record.length; 161 this.record[numRec] = entry; 162 this.turn = OPPOSITE - this.turn; 163 }, 164 165 /** 166 * Convert to SGF 167 * @return {String} SGF string 168 * @since 0.1 169 */ 170 toSGF : function() { 171 // game of Go, format version, size of board 172 var buf = "(;GM[1]FF[4]SZ[" + this.ro + "]"; 173 // player name 174 buf += "PB[" + this.players[P_BLACK] + "]PW[" + this.players[P_WHITE] + "]"; 175 // score 176 buf += "RE[" + this.score + "]\n"; 177 buf += "DT["; 178 var d = this.date; 179 buf += d.getFullYear().toString() + "-"; 180 if ((d.getMonth() + 1).toString().length == 1) 181 buf += "0"; 182 buf += (d.getMonth() + 1).toString() + "-"; 183 if (d.getDate().toString().length == 1) 184 buf += "0"; 185 buf += d.getDate().toString(); 186 buf += "]KM[0.0]RU[Chinese]\n"; 187 buf += "AP[" + programName + ":" + programVer + "]CA[UTF-8]\n"; 188 for (var i = 0; i < this.record.length; i++) { 189 var turn = this.record[i].turn; 190 if (turn == BLACK) 191 buf += ";B["; 192 else if (turn == WHITE) 193 buf += ";W["; 194 if (!this.record[i].mv.isPass) { 195 var col = this.record[i].mv.col; 196 var row = this.record[i].mv.row; 197 buf += ALPHA.charAt(col - 1) + ALPHA.charAt(row - 1); 198 } 199 buf += "]"; 200 if (i % 10 == 9) { 201 buf += "\n"; 202 } 203 } 204 buf += ")\n"; 205 return buf; 206 } 207 }; 208