ai.js
author Oleksandr Gavenko <gavenkoa@gmail.com>
Thu, 02 Jul 2015 03:03:10 +0300
changeset 163 87479ae56889
parent 160 93c44d730198
child 164 cdde49008500
permissions -rw-r--r--
Basic Monte Carlo AI.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
     1
"use strict";
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
     2
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
     3
/** @fileOverview AI modules. */
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
     4
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
     5
/** @module */
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
     6
var ai = {};
163
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
     7
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
     8
/** Directions. @constant */
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
     9
ai.dirs = ["up", "right", "down", "left"];
163
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    10
/** Directions in random order. */
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    11
ai.randDirs = function() {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    12
    var idxs = [0, 1, 2, 3];
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    13
    for (var i = idxs.length - 1; i > 0; i--) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    14
        var j = Math.floor(Math.random()*(i+1));
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    15
        var swap = idxs[j]; idxs[j] = idxs[i]; idxs[i] = swap;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    16
    }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    17
    return [ai.dirs[idxs[0]], ai.dirs[idxs[1]], ai.dirs[idxs[2]], ai.dirs[idxs[3]]];
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    18
}
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
    19
152
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
    20
/** Possible direction check function names ordered by ai.dirs. @constant */
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
    21
ai.canFn = ["canUp", "canRight", "canDown", "canLeft"];
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
    22
/** Possible merge function names ordered by ai.dirs. @constant */
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
    23
ai.mergeFn = ["upMerges", "rightMerges", "downMerges", "leftMerges"];
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    24
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    25
/** Create empty 'to' if argument missing. */
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    26
ai.copyObj = function(from, to) {
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    27
    if (to == null || typeof to !== "object")
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    28
        to = {};
54
2c389325d13b Fix typo.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 53
diff changeset
    29
    if (from == null || typeof from !== "object")
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    30
        return to;
54
2c389325d13b Fix typo.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 53
diff changeset
    31
    for (var attr in from) {
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    32
        if (from.hasOwnProperty(attr))
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    33
            to[attr] = from[attr];
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    34
    }
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    35
    return to;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    36
}
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
    37
139
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    38
ai.brdCache = function() {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    39
    this.cache = [];
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    40
}
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    41
ai.brdCache.prototype.get = function(brd) {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    42
    var compr = brd.compress();
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    43
    var subCache = this.cache[compr[0]];
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    44
    if (subCache) {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    45
        return subCache[compr[1]];
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    46
    }
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    47
    return undefined;
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    48
}
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    49
ai.brdCache.prototype.put = function(brd, val) {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    50
    var compr = brd.compress();
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    51
    var subCache = this.cache[compr[0]];
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    52
    if (subCache) {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    53
        subCache[compr[1]] = val;
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    54
    } else {
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    55
        this.cache[compr[0]] = [];
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    56
        this.cache[compr[0]][compr[1]] = val;
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    57
    }
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    58
}
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
    59
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    60
// Each strategy is a function that except current board position as 2d array and context from
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    61
// previous call to share state/precomputed values between calls.
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    62
12
a9a44cfc3e08 Moves for 2d array board + test toolkit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 10
diff changeset
    63

10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    64
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    65
////////////////////////////////////////////////////////////////
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
    66
// Blind random AI.
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    67
////////////////////////////////////////////////////////////////
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    68
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    69
/** Blind random AI.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
    70
 * @param {Board} brd  board engine from board.js
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    71
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
    72
ai.BlindRandom = function(brd) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
    73
    this.brd = brd;
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    74
}
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
    75
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
    76
ai.BlindRandom.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
    77
    var origBrd = new this.brd(brd2d);
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    78
    while (true) {
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    79
        var rnd = Math.floor(Math.random()*4);
152
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
    80
        if (origBrd[ai.canFn[rnd]]())
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
    81
            return ai.dirs[rnd];
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    82
    }
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    83
}
12
a9a44cfc3e08 Moves for 2d array board + test toolkit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 10
diff changeset
    84
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
    85
ai.BlindRandom.prototype.cleanup = function() { }
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    86
12
a9a44cfc3e08 Moves for 2d array board + test toolkit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 10
diff changeset
    87

10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    88
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
    89
////////////////////////////////////////////////////////////////
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
    90
// Blind weight random AI.
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
    91
////////////////////////////////////////////////////////////////
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
    92
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    93
/**
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    94
 * @name ai.BlindWeightRandom.cfg
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    95
 * @namespace
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    96
 * @property {number} left   weight
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    97
 * @property {number} right  weight
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    98
 * @property {number} up     weight
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
    99
 * @property {number} down   weight
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   100
 */
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   101
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   102
/** Blind weight random AI.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   103
 * @param {Board} brd  board engine from board.js
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   104
 * @param {ai.BlindWeightRandom.cfg} cfg  configuration settings
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   105
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   106
ai.BlindWeightRandom = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   107
    this.brd = brd;
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   108
    this.cfg = ai.copyObj(ai.BlindWeightRandom.bestCfg);
56
76d257640b7d Merge config with best settings.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 54
diff changeset
   109
    ai.copyObj(cfg, this.cfg);
76d257640b7d Merge config with best settings.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 54
diff changeset
   110
    var total = this.cfg.left + this.cfg.right + this.cfg.up + this.cfg.down;
76d257640b7d Merge config with best settings.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 54
diff changeset
   111
    this.threshold1 = this.cfg.left/total;
76d257640b7d Merge config with best settings.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 54
diff changeset
   112
    this.threshold2 = (this.cfg.left + this.cfg.down)/total;
76d257640b7d Merge config with best settings.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 54
diff changeset
   113
    this.threshold3 = (this.cfg.left + this.cfg.down + this.cfg.right)/total;
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   114
}
104
47d42234dd5c Set better coefficient for blind-weight-random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 99
diff changeset
   115
ai.BlindWeightRandom.bestCfg = { left: 1, right: 16, up: 4, down: 8 };
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   116
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   117
ai.BlindWeightRandom.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   118
    var origBrd = new this.brd(brd2d);
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   119
    while (true) {
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   120
        var rnd = Math.random();
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   121
        if (rnd < this.threshold1)
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   122
            var dir = 0;
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   123
        else if (rnd < this.threshold2)
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   124
            var dir = 1;
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   125
        else if (rnd < this.threshold3)
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   126
            var dir = 2;
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   127
        else
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   128
            var dir = 3;
152
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
   129
        if (origBrd[ai.canFn[dir]]())
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   130
            return ai.dirs[dir];
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   131
    }
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   132
}
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   133
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   134
ai.BlindWeightRandom.prototype.cleanup = function() { }
36
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   135
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   136

a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   137
a18fc2601ce8 Add blind eight random AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 35
diff changeset
   138
////////////////////////////////////////////////////////////////
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   139
// Blind cycle AI.
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   140
////////////////////////////////////////////////////////////////
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   141
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   142
/**
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   143
 * @name ai.BlindCycle.cfg
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   144
 * @namespace
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   145
 * @property {boolean} whilePossible  move in one direction while possible
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   146
 * @property {boolean} down           switch direction clockwise
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   147
 */
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   148
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   149
/** Blind cycle AI.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   150
 * @param {Board} brd  board engine from board.js
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   151
 * @param {ai.BlindCycle.cfg} cfg  configuration settings
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   152
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   153
ai.BlindCycle = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   154
    this.brd = brd;
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   155
    this.cfg = cfg || {};
29
30a09d50ae21 Fix typo.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 28
diff changeset
   156
    this.cfg.whilePossible = this.cfg.whilePossible || false;
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   157
    this.cfg.clockwise = this.cfg.clockwise || false;
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   158
}
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   159
ai.BlindCycle.dirs = ["left", "down", "right", "up"];
152
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
   160
ai.BlindCycle.canFn = ["canLeft", "canDown", "canRight", "canUp"];
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   161
ai.BlindCycle.prototype.nextDir = function(dir) {
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   162
    if (this.cfg.clockwise)
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   163
        return (dir + (4-1)) % 4;
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   164
    else
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   165
        return (dir + 1) % 4;
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   166
}
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   167
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   168
ai.BlindCycle.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   169
    var origBrd = new this.brd(brd2d);
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   170
    this.prevDir = this.prevDir || 0;
29
30a09d50ae21 Fix typo.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 28
diff changeset
   171
    if (!this.cfg.whilePossible)
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   172
        this.prevDir = this.nextDir(this.prevDir);
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   173
    while (true) {
152
07814b979a8a Add merges function names. Refactoring: Rename function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 149
diff changeset
   174
        if (origBrd[ai.BlindCycle.canFn[this.prevDir]]())
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   175
            return ai.BlindCycle.dirs[this.prevDir];
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   176
        this.prevDir = this.nextDir(this.prevDir);
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   177
    }
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   178
}
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   179
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
59
28613a54c71c Capitilize AI names.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 57
diff changeset
   180
ai.BlindCycle.prototype.cleanup = function() {
27
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   181
    delete this.prevDir;
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   182
}
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   183
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   184

8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   185
8f96d09a4d94 Add Blind cycle AI. Add example of setting passing.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 24
diff changeset
   186
////////////////////////////////////////////////////////////////
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   187
// 1 step deep with linear weight function on score, max value,
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   188
// bonuses for max value stay at corner or edge and bonuses
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   189
// for each free field.
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   190
////////////////////////////////////////////////////////////////
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   191
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   192
/**
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   193
 * Defines coefficient for linear resulted weight function.
99
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   194
 * @name ai.OneStepAhead.cfg
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   195
 * @namespace
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   196
 * @property {number} scoreCoef    multiplicator for score
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   197
 * @property {number} maxValCoef   multiplicator for max value
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   198
 * @property {number} cornerBonus  bonus for max value at board corner
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   199
 * @property {number} edgeBonus    bonus for max value at board edge
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   200
 * @property {number} freeBonus    bonus for each free cell
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   201
 */
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   202
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   203
/** 1 step deep with * AI.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   204
 * @param {Board} brd  board engine from board.js
99
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   205
 * @param {ai.OneStepAhead.cfg} cfg  configuration settings
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   206
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   207
ai.OneStepAhead = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   208
    this.brd = brd;
99
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   209
    this.cfg = ai.copyObj(ai.OneStepAhead.bestCfg);
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   210
    ai.copyObj(cfg, this.cfg);
12
a9a44cfc3e08 Moves for 2d array board + test toolkit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 10
diff changeset
   211
}
99
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   212
ai.OneStepAhead.bestCfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0};
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   213
ai.OneStepAhead.prototype.weight = function(brd) {
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   214
    var weight = 0;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   215
    if (this.cfg.scoreCoef > 0)
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   216
        weight += this.cfg.scoreCoef * brd.score();
149
2839f8227a38 Refactoring: take proper name to function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 148
diff changeset
   217
    var max = brd.maxVal();
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   218
    if (this.cfg.maxValCoef > 0)
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   219
        weight += this.cfg.maxValCoef * max;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   220
    if (this.cfg.cornerBonus > 0 && brd.atCorner(max))
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   221
        weight += this.cfg.cornerBonus;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   222
    if (this.cfg.edgeBonus > 0 && brd.atEdge(max))
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   223
        weight += this.cfg.edgeBonus;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   224
    if (this.cfg.freeBonus > 0)
148
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   225
        weight += this.cfg.freeBonus * brd.freeCnt();
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   226
    return weight;
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   227
}
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   228
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   229
ai.OneStepAhead.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   230
    var origBrd = new this.brd(brd2d);
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   231
    var nextBrd = new this.brd();
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   232
    var maxWeight = -1;
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   233
    var bestDir;
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   234
    for (var i = 0; i < ai.dirs.length; i++) {
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   235
        var dir = ai.dirs[i];
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   236
        if (origBrd[dir](nextBrd)) {
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   237
            var weight = this.weight(nextBrd);
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   238
            if (maxWeight < weight) {
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   239
                bestDir = dir;
53
ee53cd2cb69a Join all one step deep AIs into one with linear weight function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 36
diff changeset
   240
                maxWeight = weight;
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   241
            }
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   242
        }
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   243
    }
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   244
    return bestDir;
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   245
}
12
a9a44cfc3e08 Moves for 2d array board + test toolkit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 10
diff changeset
   246
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
99
df4736e659f2 Rename AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 74
diff changeset
   247
ai.OneStepAhead.prototype.cleanup = function() { }
10
70ece7f758a0 Move rule and AI engine to separate files.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents:
diff changeset
   248
24
079bcd734b68 Fix: TypeError: ui.ai.current.cleanup is not a function
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 21
diff changeset
   249

14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   250
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   251
////////////////////////////////////////////////////////////////
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   252
// N level deep on score value without random simulation.
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   253
////////////////////////////////////////////////////////////////
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   254
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   255
/**
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   256
 * Defines coefficient for linear resulted weight function.
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   257
 * @name ai.StaticDeepMerges.cfg
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   258
 * @namespace
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   259
 * @property {number} scoreCoef    multiplicator for score
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   260
 * @property {number} maxValCoef   multiplicator for max value
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   261
 * @property {number} cornerBonus  bonus for max value at board corner
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   262
 * @property {number} edgeBonus    bonus for max value at board edge
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   263
 * @property {number} freeBonus    bonus for each free cell
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   264
 */
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   265
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   266
/** Deep merges AI without random simulation.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   267
 * @param {Board} brd  board engine from board.js
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   268
 * @param {Object} cfg  configuration settings
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   269
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   270
ai.StaticDeepMerges = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   271
    this.brd = brd;
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   272
    this.cfg = ai.copyObj(ai.OneStepAhead.bestCfg);
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   273
    ai.copyObj(cfg, this.cfg);
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   274
}
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   275
ai.StaticDeepMerges.bestCfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, weightThreshold: 10};
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   276
ai.StaticDeepMerges.prototype.weight = function(brd) {
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   277
    var weight = 0;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   278
    if (this.cfg.scoreCoef > 0)
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   279
        weight += this.cfg.scoreCoef * brd.score();
149
2839f8227a38 Refactoring: take proper name to function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 148
diff changeset
   280
    var max = brd.maxVal();
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   281
    if (this.cfg.maxValCoef > 0)
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   282
        weight += this.cfg.maxValCoef * max;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   283
    if (this.cfg.cornerBonus > 0 && brd.atCorner(max))
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   284
        weight += this.cfg.cornerBonus;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   285
    if (this.cfg.edgeBonus > 0 && brd.atEdge(max))
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   286
        weight += this.cfg.edgeBonus;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   287
    if (this.cfg.freeBonus > 0)
148
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   288
        weight += this.cfg.freeBonus * brd.freeCnt();
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   289
    return weight;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   290
}
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   291
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   292
ai.StaticDeepMerges.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   293
    var origBrd = new this.brd(brd2d);
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   294
    var nextBrd = new this.brd();
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   295
    var prevScore = -1, nextScore = -1;
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   296
    var maxWeight = -1;
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   297
    var bestDir;
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   298
    for (var i = 0; i < ai.dirs.length; i++) {
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   299
        var dir = ai.dirs[i];
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   300
        if (origBrd[dir](nextBrd)) {
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   301
            var weight = this.evalFn(nextBrd);
118
7e93fb8136a3 Fix: ReferenceError: reference to undefined property this.cfg.weightPriority
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 110
diff changeset
   302
            var ok = (weight - maxWeight) > this.cfg.weightThreshold;
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   303
            if ( ! ok && maxWeight <= weight) {
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   304
                nextScore = this.weight(nextBrd);
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   305
                ok = prevScore < nextScore;
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   306
            }
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   307
            if (ok) {
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   308
                prevScore = nextScore;
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   309
                maxWeight = weight;
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   310
                bestDir = dir;
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   311
            }
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   312
        }
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   313
    }
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   314
    return bestDir;
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   315
}
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   316
ai.StaticDeepMerges.prototype.evalFn = function(brd) {
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   317
    var currScore = brd.score();
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   318
    var maxWeight = currScore;
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   319
    var nextBrd = new this.brd();
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   320
    for (var i = 0; i < ai.dirs.length; i++) {
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   321
        if (brd[ai.dirs[i]](nextBrd)) {
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   322
            var score = nextBrd.score();
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   323
            if (score > currScore)
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   324
                maxWeight = Math.max(maxWeight, this.evalFn(nextBrd));
18
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   325
        }
42d62e5123b2 Choose move that lead to maximum next score among all possible when next moves
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 14
diff changeset
   326
    }
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   327
    return maxWeight;
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   328
}
19
94a4201d27a3 Fold code into loops.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 18
diff changeset
   329
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   330
ai.StaticDeepMerges.prototype.cleanup = function() { }
14
9b49e710f5a7 Add "N level deep on score value without random" AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 12
diff changeset
   331
24
079bcd734b68 Fix: TypeError: ui.ai.current.cleanup is not a function
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 21
diff changeset
   332

20
ab294e8db00c Add detecting value at edge or corner, free cell count. Added AI that count
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 19
diff changeset
   333
ab294e8db00c Add detecting value at edge or corner, free cell count. Added AI that count
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 19
diff changeset
   334
////////////////////////////////////////////////////////////////
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   335
// N level deep with random simulation.
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   336
////////////////////////////////////////////////////////////////
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   337
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   338
/**
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   339
 * Defines coefficient for linear resulted weight function.
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   340
 * @name ai.expectimax.cfg
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   341
 * @namespace
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   342
 * @property {number} scoreCoef    multiplicator for score
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   343
 * @property {number} maxValCoef   multiplicator for max value
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   344
 * @property {number} cornerBonus  bonus for max value at board corner
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   345
 * @property {number} edgeBonus    bonus for max value at board edge
110
e3a91b336976 Join N level deep on score value without random simulation AIs and add
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 109
diff changeset
   346
 * @property {number} freeBonus    bonus for each free cell
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   347
 */
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   348
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   349
/** N level deep with random simulation.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   350
 * @param {Board} brd  board engine from board.js
57
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   351
 * @param {ai.expectimax.cfg} cfg  configuration settings
94e1b2d0bd31 Add JSDoc annotation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 56
diff changeset
   352
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   353
ai.expectimax = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   354
    this.brd = brd;
74
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   355
    this.cfg = ai.copyObj(ai.expectimax.bestCfg);
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   356
    ai.copyObj(cfg, this.cfg);
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   357
    if (this.cfg.balance <= 0)
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   358
        this.cfg.balance = ai.expectimax.bestCfg.balance;
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   359
    if ( this.cfg.balance > 1)
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   360
        this.cfg.balance = 1;
126
e634761d0432 Increase depth limit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 125
diff changeset
   361
    if (!this.cfg.depth || this.cfg.depth < 0 || 9 <= this.cfg.depth)
74
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   362
        this.cfg.depth = ai.expectimax.bestCfg.depth;
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   363
}
126
e634761d0432 Increase depth limit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 125
diff changeset
   364
ai.expectimax.bestCfg = {balance: .9, depth: 5, scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0};
74
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   365
ai.expectimax.prototype.weight = function(brd) {
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   366
    var score = 0;
122
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   367
    var cfg = this.cfg;
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   368
    if (cfg.scoreCoef > 0)
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   369
        score += cfg.scoreCoef * brd.score();
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   370
    if (cfg.maxValCoef > 0 || cfg.cornerBonus > 0 || cfg.edgeBonus > 0) {
149
2839f8227a38 Refactoring: take proper name to function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 148
diff changeset
   371
        var max = brd.maxVal();
122
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   372
        if (cfg.maxValCoef > 0)
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   373
            score += cfg.maxValCoef * max;
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   374
        if (cfg.cornerBonus > 0)
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   375
            if (brd.atCorner(max))
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   376
                score += cfg.cornerBonus;
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   377
        if (cfg.edgeBonus > 0)
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   378
            if (brd.atEdge(max))
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   379
                score += cfg.edgeBonus;
4cc40a51742a Don't calculate max value if it isn't used.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 118
diff changeset
   380
    }
135
935a500cea3b Fix: code in wrong scope.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 126
diff changeset
   381
    if (cfg.freeBonus > 0)
148
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   382
        score += cfg.freeBonus * brd.freeCnt();
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   383
    return score;
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   384
}
147
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   385
/** Select best direction for next step. */
d4f9433e30b9 Use proper name for incoming argument.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 140
diff changeset
   386
ai.expectimax.prototype.analyse = function(brd2d) {
139
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
   387
    this.brdCache = new ai.brdCache();
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   388
    var origBrd = new this.brd(brd2d);
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   389
    var nextBrd = new this.brd();
125
fa1f44d3888d Remove comparing with next board weight if expected value differ less then threshold.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 124
diff changeset
   390
    var maxW = -1;
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   391
    var bestDir;
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   392
    this.cleanup();
126
e634761d0432 Increase depth limit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 125
diff changeset
   393
    this.depthLimit = this.cfg.depth;
148
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   394
    var freeCnt = origBrd.freeCnt();
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   395
    if (freeCnt >= 6)
93c122e0ea90 Refactoring: take proper name for function.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 147
diff changeset
   396
        this.depthLimit = Math.min(this.depthLimit, 6 - freeCnt/3);
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   397
    for (var i = 0; i < ai.dirs.length; i++) {
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   398
        var dir = ai.dirs[i];
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   399
        if (origBrd[dir](nextBrd)) {
125
fa1f44d3888d Remove comparing with next board weight if expected value differ less then threshold.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 124
diff changeset
   400
            var w = this.evalFn(nextBrd, 1);
fa1f44d3888d Remove comparing with next board weight if expected value differ less then threshold.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 124
diff changeset
   401
            if (w > maxW) {
fa1f44d3888d Remove comparing with next board weight if expected value differ less then threshold.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 124
diff changeset
   402
                maxW = w;
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   403
                bestDir = dir;
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   404
            }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   405
        }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   406
    }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   407
    this.cleanup();
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   408
    return bestDir;
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   409
}
109
6d5a9d8b00be Renames.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 104
diff changeset
   410
ai.expectimax.prototype.evalFn = function(brd, depth) {
126
e634761d0432 Increase depth limit.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 125
diff changeset
   411
    if (depth >= this.depthLimit)
74
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   412
        return this.weight(brd);
139
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
   413
    var wCached = this.brdCache.get(brd);
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
   414
    if (wCached)
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
   415
        return wCached;
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   416
    var wMin = +Infinity;
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   417
    var randBoard = new this.brd();
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   418
    var nextBrd = new this.brd();
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   419
    for (var i = 0; i < 3; i++) {
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   420
        for (var j = 0; j < 3; j++) {
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   421
            if (brd.get(i, j) === 0) {
140
438fd8c3c3ca Create object outside of loop.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 139
diff changeset
   422
                brd.copy(randBoard);
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   423
                randBoard.set(i, j, 1);
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   424
                var wMax2 = 0;
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   425
                for (var diri = 0; diri < ai.dirs.length; diri++) {
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   426
                    if (randBoard[ai.dirs[diri]](nextBrd))
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   427
                        wMax2 = Math.max(wMax2, this.evalFn(nextBrd, depth+1));
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   428
                }
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   429
                var wMax4 = 0;
136
4a143572b9d2 Fix: wrong variable scope.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 135
diff changeset
   430
                var balance = this.cfg.balance;
4a143572b9d2 Fix: wrong variable scope.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 135
diff changeset
   431
                if (balance < 1) {
74
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   432
                    randBoard.set(i, j, 2);
93cb48b73b39 Enable config for expectimax. Fix weight function for expectimax.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 60
diff changeset
   433
                    for (var diri = 0; diri < ai.dirs.length; diri++) {
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   434
                        if (randBoard[ai.dirs[diri]](nextBrd))
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   435
                            wMax4 = Math.max(wMax4, this.evalFn(nextBrd, depth+1));
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   436
                    }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   437
                }
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   438
                wMin = Math.min(wMin, balance * wMax2 + (1 - balance) * wMax4);
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   439
            }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   440
        }
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   441
    }
139
4dde63ac0bb4 Make fast board cache.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 136
diff changeset
   442
    this.brdCache.put(brd, wMin);
124
4a2551dd179d Fix: expectimax select best move which lead to less danger among all worst.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 122
diff changeset
   443
    return wMin;
21
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   444
}
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   445
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   446
ai.expectimax.prototype.cleanup = function() {
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   447
}
ed0292f0c7c6 Expectimax implementation.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 20
diff changeset
   448
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   449

1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   450
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   451
////////////////////////////////////////////////////////////////
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   452
// Survive as long as possible.
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   453
////////////////////////////////////////////////////////////////
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   454
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   455
/**
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   456
 * Defines coefficient for linear resulted weight function.
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   457
 * @name ai.survive.cfg
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   458
 * @namespace
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   459
 * @property {number} scoreCoef    multiplicator for score
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   460
 * @property {number} maxValCoef   multiplicator for max value
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   461
 * @property {number} cornerBonus  bonus for max value at board corner
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   462
 * @property {number} edgeBonus    bonus for max value at board edge
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   463
 * @property {number} freeBonus    bonus for each free cell
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   464
 */
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   465
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   466
/** N level deep with random simulation.
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   467
 * @param {Board} brd  board engine from board.js
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   468
 * @param {ai.survive.cfg} cfg  configuration settings
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   469
 * @constructor */
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   470
ai.survive = function(brd, cfg) {
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   471
    this.brd = brd;
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   472
    this.cfg = ai.copyObj(ai.survive.bestCfg);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   473
    ai.copyObj(cfg, this.cfg);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   474
    if (this.cfg.freeCells <= 0)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   475
        this.cfg.freeCells = ai.survive.bestCfg.freeCells;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   476
    if (!this.cfg.maxDepth || this.cfg.maxDepth < 0 || 20 <= this.cfg.maxDepth)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   477
        this.cfg.maxDepth = ai.survive.bestCfg.maxDepth;
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   478
    this.cfg.altAI = new ai.StaticDeepMerges(brd, ai.survive.altAICfg);
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   479
}
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   480
ai.survive.bestCfg = {freeCells: 8, maxDepth: 5};
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   481
ai.survive.altAICfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, weightThreshold: 0};
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   482
/** Select best direction for next step. */
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   483
ai.survive.prototype.analyse = function(brd2d) {
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   484
    var origBrd = new this.brd(brd2d);
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   485
    var nextBrd = new this.brd();
156
e6a4bc888b72 Allow IA choose any direction in case when all move lead to game over.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 155
diff changeset
   486
    var bestW = -2;
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   487
    var bestDir;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   488
    var freeCnt = origBrd.freeCnt();
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   489
    if (freeCnt >= this.cfg.freeCells)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   490
        return this.cfg.altAI.analyse(brd2d);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   491
    for (var i = 0; i < ai.dirs.length; i++) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   492
        var dir = ai.dirs[i];
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   493
        if (origBrd[dir](nextBrd)) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   494
            var w = this.evalFn(nextBrd, 1);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   495
            if (w > bestW) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   496
                bestW = w;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   497
                bestDir = dir;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   498
            }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   499
        }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   500
    }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   501
    return bestDir;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   502
}
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   503
ai.survive.prototype.evalFn = function(brd, depth) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   504
    if (brd.freeCnt() >= this.cfg.freeCells)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   505
        return 1;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   506
    if (depth >= this.cfg.maxDepth)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   507
        return 0;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   508
    var wMin = +Infinity;
160
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   509
    var randBoard = new this.brd();
93c44d730198 Rename brdEngine to brd.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 156
diff changeset
   510
    var nextBrd = new this.brd();
155
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   511
exit:
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   512
    for (var i = 0; i < 3; i++) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   513
        for (var j = 0; j < 3; j++) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   514
            if (brd.get(i, j) !== 0)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   515
                continue;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   516
            brd.copy(randBoard);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   517
            randBoard.set(i, j, 1);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   518
            var wMax = -1;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   519
            for (var diri = 0; diri < ai.dirs.length; diri++) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   520
                if (randBoard[ai.dirs[diri]](nextBrd)) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   521
                    var w = this.evalFn(nextBrd, depth+1);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   522
                    if (w === 1) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   523
                        wMax = 1;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   524
                        break;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   525
                    }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   526
                    wMax = Math.max(wMax, w);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   527
                }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   528
            }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   529
            if (wMax === -1) {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   530
                wMin = -1;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   531
                break exit;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   532
            }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   533
            wMin = Math.min(wMin, wMax);
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   534
        }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   535
    }
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   536
    if (wMin === +Infinity)
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   537
        return -1;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   538
    return wMin;
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   539
}
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   540
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   541
ai.survive.prototype.cleanup = function() {
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   542
}
1f8df90bd338 AI: Survive as long as possible.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 152
diff changeset
   543
163
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   544

87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   545
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   546
////////////////////////////////////////////////////////////////
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   547
// MonteCarlo simulations.
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   548
////////////////////////////////////////////////////////////////
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   549
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   550
/**
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   551
 * Defines coefficient for linear resulted weight function.
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   552
 * @name ai.MonteCarlo.cfg
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   553
 * @namespace
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   554
 * @property {number} maxDepth     depth limit
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   555
 * @property {number} simulations  simulation count limit
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   556
 */
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   557
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   558
/** MonteCarlo simulations.
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   559
 * @param {Board} brd  board engine from board.js
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   560
 * @param {ai.MonteCarlo.cfg} cfg  configuration settings
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   561
 * @constructor */
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   562
ai.MonteCarlo = function(brd, cfg) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   563
    this.brd = brd;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   564
    this.cfg = ai.copyObj(ai.MonteCarlo.bestCfg);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   565
    ai.copyObj(cfg, this.cfg);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   566
    if (this.cfg.simulations <= 0)
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   567
        this.cfg.simulations = ai.MonteCarlo.bestCfg.simulations;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   568
    if (!this.cfg.maxDepth || this.cfg.maxDepth <= 0 || 20 <= this.cfg.maxDepth)
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   569
        this.cfg.maxDepth = ai.MonteCarlo.bestCfg.maxDepth;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   570
}
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   571
ai.MonteCarlo.bestCfg = {simulations: 1000, maxDepth: 20};
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   572
/** Select best direction for next step. */
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   573
ai.MonteCarlo.prototype.analyse = function(brd2d) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   574
    var origBrd = new this.brd(brd2d);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   575
    var nextBrd = new this.brd();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   576
    var bestW = - this.cfg.simulations;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   577
    var bestDir;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   578
    var freeCnt = origBrd.freeCnt();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   579
    for (var i = 0; i < ai.dirs.length; i++) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   580
        var dir = ai.dirs[i];
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   581
        if (origBrd[dir](nextBrd)) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   582
            var w = 0;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   583
            for (var gameCnt = this.cfg.simulations; gameCnt > 0; gameCnt--) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   584
                var tmpBrd = nextBrd.copy();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   585
                w += this.play(tmpBrd, this.cfg.maxDepth);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   586
            }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   587
            if (w > bestW) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   588
                bestW = w;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   589
                bestDir = dir;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   590
            }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   591
        }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   592
    }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   593
    return bestDir;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   594
}
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   595
ai.MonteCarlo.prototype.play = function(brd, depth) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   596
    if (depth <= 0) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   597
        return brd.freeCnt();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   598
    }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   599
    brd.rnd(1);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   600
    var dirs = ai.randDirs();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   601
    for (var i = 0; i < 4; i++) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   602
        var dir = dirs[i];
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   603
        var nextBrd = new brd.constructor();
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   604
        if (brd[dir](nextBrd)) {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   605
            return this.play(nextBrd, depth-1);
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   606
        }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   607
    }
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   608
    return -1;
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   609
}
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   610
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   611
ai.MonteCarlo.prototype.cleanup = function() {
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   612
}
87479ae56889 Basic Monte Carlo AI.
Oleksandr Gavenko <gavenkoa@gmail.com>
parents: 160
diff changeset
   613