equal
deleted
inserted
replaced
18 for (var attr in from) { |
18 for (var attr in from) { |
19 if (from.hasOwnProperty(attr)) |
19 if (from.hasOwnProperty(attr)) |
20 to[attr] = from[attr]; |
20 to[attr] = from[attr]; |
21 } |
21 } |
22 return to; |
22 return to; |
|
23 } |
|
24 |
|
25 ai.brdCache = function() { |
|
26 this.cache = []; |
|
27 } |
|
28 ai.brdCache.prototype.get = function(brd) { |
|
29 var compr = brd.compress(); |
|
30 var subCache = this.cache[compr[0]]; |
|
31 if (subCache) { |
|
32 return subCache[compr[1]]; |
|
33 } |
|
34 return undefined; |
|
35 } |
|
36 ai.brdCache.prototype.put = function(brd, val) { |
|
37 var compr = brd.compress(); |
|
38 var subCache = this.cache[compr[0]]; |
|
39 if (subCache) { |
|
40 subCache[compr[1]] = val; |
|
41 } else { |
|
42 this.cache[compr[0]] = []; |
|
43 this.cache[compr[0]][compr[1]] = val; |
|
44 } |
23 } |
45 } |
24 |
46 |
25 // Each strategy is a function that except current board position as 2d array and context from |
47 // Each strategy is a function that except current board position as 2d array and context from |
26 // previous call to share state/precomputed values between calls. |
48 // previous call to share state/precomputed values between calls. |
27 |
49 |
341 if (cfg.freeBonus > 0) |
363 if (cfg.freeBonus > 0) |
342 score += cfg.freeBonus * brd.free(); |
364 score += cfg.freeBonus * brd.free(); |
343 return score; |
365 return score; |
344 } |
366 } |
345 ai.expectimax.prototype.analyse = function(brd) { |
367 ai.expectimax.prototype.analyse = function(brd) { |
|
368 this.brdCache = new ai.brdCache(); |
346 var origBrd = new this.brdEngine(brd); |
369 var origBrd = new this.brdEngine(brd); |
347 var nextBrd = new this.brdEngine(); |
370 var nextBrd = new this.brdEngine(); |
348 var maxW = -1; |
371 var maxW = -1; |
349 var bestDir; |
372 var bestDir; |
350 this.cleanup(); |
373 this.cleanup(); |
366 return bestDir; |
389 return bestDir; |
367 } |
390 } |
368 ai.expectimax.prototype.evalFn = function(brd, depth) { |
391 ai.expectimax.prototype.evalFn = function(brd, depth) { |
369 if (depth >= this.depthLimit) |
392 if (depth >= this.depthLimit) |
370 return this.weight(brd); |
393 return this.weight(brd); |
371 if (this.cache[depth]) { |
394 var wCached = this.brdCache.get(brd); |
372 var cache = this.cache[depth]; |
395 if (wCached) |
373 for (var i = cache.length-1; i >= 0; i--) { |
396 return wCached; |
374 if (brd.equals(cache[i].brd)) |
|
375 return cache[i].weight; |
|
376 } |
|
377 } else { |
|
378 this.cache[depth] = []; |
|
379 } |
|
380 var wMin = +Infinity; |
397 var wMin = +Infinity; |
381 for (var i = 0; i < 3; i++) { |
398 for (var i = 0; i < 3; i++) { |
382 for (var j = 0; j < 3; j++) { |
399 for (var j = 0; j < 3; j++) { |
383 if (brd.get(i, j) === 0) { |
400 if (brd.get(i, j) === 0) { |
384 var randBoard = brd.copy(); |
401 var randBoard = brd.copy(); |
400 } |
417 } |
401 wMin = Math.min(wMin, balance * wMax2 + (1 - balance) * wMax4); |
418 wMin = Math.min(wMin, balance * wMax2 + (1 - balance) * wMax4); |
402 } |
419 } |
403 } |
420 } |
404 } |
421 } |
405 this.cache[depth].push({brd: brd, weight: wMin}); |
422 this.brdCache.put(brd, wMin); |
406 return wMin; |
423 return wMin; |
407 } |
424 } |
408 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ |
425 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ |
409 ai.expectimax.prototype.cleanup = function() { |
426 ai.expectimax.prototype.cleanup = function() { |
410 this.cache = []; |
427 } |
411 } |
428 |
412 |
|