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