135 return maxScore; |
135 return maxScore; |
136 } |
136 } |
137 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ |
137 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ |
138 ai.deepMaxScore.prototype.cleanup = function() { } |
138 ai.deepMaxScore.prototype.cleanup = function() { } |
139 |
139 |
|
140 |
|
141 //////////////////////////////////////////////////////////////// |
|
142 // N level deep on score value + max value prefer corner, |
|
143 // without random simulation. |
|
144 //////////////////////////////////////////////////////////////// |
|
145 |
|
146 /* cfg.cornerBonus - value to add if max value at corner. */ |
|
147 /* cfg.edgeBonus - value to add if max value at edge. */ |
|
148 ai.deepMaxScoreCorner = function(brdEngine, cfg) { |
|
149 this.brdEngine = brdEngine; |
|
150 this.cfg = cfg || {}; |
|
151 this.cfg.cornerBonus = this.cfg.cornerBonus || 20000; |
|
152 this.cfg.edgeBonus = this.cfg.edgeBonus || 100; |
|
153 this.cfg.freeBonus = this.cfg.edgeBonus || 100; |
|
154 } |
|
155 ai.deepMaxScoreCorner.prototype.scoreCorner = function(brd) { |
|
156 var score = brd.score(); |
|
157 var max = brd.max(); |
|
158 if (brd.atCorner(max)) |
|
159 score += this.cfg.cornerBonus; |
|
160 else if (brd.atEdge(max)) |
|
161 score += this.cfg.edgeBonus; |
|
162 score += brd.free() * this.cfg.freeBonus; |
|
163 return score; |
|
164 } |
|
165 ai.deepMaxScoreCorner.prototype.scoreEdge = function(brd) { |
|
166 var score = brd.score(); |
|
167 var max = brd.max(); |
|
168 if (brd.atEdge(max)) |
|
169 score += this.cfg.edgeBonus; |
|
170 score += brd.free() * this.cfg.freeBonus; |
|
171 return score; |
|
172 } |
|
173 ai.deepMaxScoreCorner.prototype.analyse = function(brd) { |
|
174 var origBrd = new this.brdEngine(brd); |
|
175 var nextBrd = new this.brdEngine(); |
|
176 var prevScore = -1, nextScore = -1; |
|
177 var maxScore = -1; |
|
178 var bestDir; |
|
179 for (var i = 0; i < ai.dirs.length; i++) { |
|
180 var dir = ai.dirs[i]; |
|
181 if (origBrd[dir](nextBrd)) { |
|
182 nextScore = this.scoreCorner(nextBrd); |
|
183 var score = this.bestScore(nextBrd); |
|
184 // console.log("dir: %o, prevScore: %o, nextScore: %o, maxScore: %o, score: %o", dir, prevScore, nextScore, maxScore, score); |
|
185 if (maxScore < score || (maxScore === score && prevScore < nextScore)) { |
|
186 prevScore = nextScore; |
|
187 maxScore = score; |
|
188 bestDir = dir; |
|
189 } |
|
190 } |
|
191 } |
|
192 return bestDir; |
|
193 } |
|
194 ai.deepMaxScoreCorner.prototype.bestScore = function(brd, seenBrds) { |
|
195 if (seenBrds) { |
|
196 for (var i = 0; i < seenBrds.length; i++) |
|
197 if (brd.equals(seenBrds[i])) |
|
198 return 0; |
|
199 } else { |
|
200 seenBrds = []; |
|
201 } |
|
202 seenBrds.push(brd); |
|
203 var currScore = this.scoreEdge(brd); |
|
204 var maxScore = currScore; |
|
205 var nextBrd = new this.brdEngine(); |
|
206 for (var i = 0; i < ai.dirs.length; i++) { |
|
207 if (brd[ai.dirs[i]](nextBrd)) { |
|
208 var score = this.scoreEdge(nextBrd); |
|
209 if (score > currScore) |
|
210 maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds)); |
|
211 } |
|
212 } |
|
213 return maxScore; |
|
214 } |
|
215 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ |
|
216 ai.deepMaxScoreCorner.prototype.cleanup = function() { } |
|
217 |