Skip to content

Commit 01caa0d

Browse files
Minimax implementation (mgechev#171)
* minimax * remove blank line Co-Authored-By: Minko Gechev <mgechev@gmail.com> * cr fixes * simple game tests added Co-authored-by: Minko Gechev <mgechev@gmail.com>
1 parent d534212 commit 01caa0d

File tree

3 files changed

+399
-2
lines changed

3 files changed

+399
-2
lines changed

src/others/minimax.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
(function (exports) {
2+
'use strict';
3+
/* eslint max-params: 0 */
4+
5+
/**
6+
* @param {Function} getPossibleNextStatesFn Function which returns all possible next moves with states .
7+
* @param {Function} isGameOverFn Function which returns if game is over.
8+
* @param {Function} getScoreFn Function which returns score.
9+
* @return {Function} minimax function
10+
*/
11+
function minimaxBuilder(
12+
getPossibleNextStatesFn,
13+
isGameOverFn,
14+
getScoreFn
15+
) {
16+
/**
17+
* Minimax (sometimes MinMax, MM[1] or saddle point[2]) is a decision rule used in artificial intelligence,
18+
* decision theory, game theory, statistics, and philosophy for minimizing the possible loss for a worst case (maximum loss) scenario.
19+
* Optimized with alpha-beta pruning.
20+
* {@link https://en.wikipedia.org/wiki/Minimax}
21+
* {@link https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning}
22+
*
23+
* @public
24+
* @module others/minimax
25+
*
26+
* @example
27+
*
28+
* var miniMax =
29+
* require('path-to-algorithms/src/others/minimax').minimax;
30+
* var result = minimax(
31+
* [1, 2, 3],
32+
* true,
33+
* 5,
34+
* -Infinity,
35+
* Infinity,
36+
* state => ({ move: 0, state: [2, 3, 4] }),
37+
* state => state[1] < 3,
38+
* state => state[1]
39+
* );
40+
*
41+
* @param {*} state Current game state
42+
* @param {Boolean} maximize Defines if the result should be maximized or minimized
43+
* @param {Number} depth Defines the maximum depth search
44+
* @param {Number} alpha Maximum score that the minimizing player is assured
45+
* @param {Number} beta Minimum score that the maximizing player is assured
46+
* @return {{score: Number, move: *}} which contains the minimum coins from the given
47+
* list, required for the change.
48+
*/
49+
const minimax = (
50+
state,
51+
maximize,
52+
depth,
53+
alpha,
54+
beta
55+
) => {
56+
if (depth === 0 || isGameOverFn(state)) {
57+
const score = getScoreFn(state);
58+
return {score, move: null};
59+
}
60+
61+
const possibleMoveResults = getPossibleNextStatesFn(state);
62+
63+
if (maximize) {
64+
65+
let maxResult = {score: -Infinity, move: null};
66+
67+
for (const next of possibleMoveResults) {
68+
const result = minimax(
69+
next.state,
70+
false,
71+
depth - 1,
72+
alpha,
73+
beta,
74+
);
75+
76+
if (result.score > maxResult.score) {
77+
maxResult = {score: result.score, move: next.move};
78+
}
79+
80+
alpha = Math.max(alpha, result.score);
81+
82+
if (alpha >= beta) {
83+
break;
84+
}
85+
}
86+
87+
return maxResult;
88+
} else {
89+
let minResult = {score: Infinity, move: null};
90+
91+
for (const next of possibleMoveResults) {
92+
const result = minimax(
93+
next.state,
94+
true,
95+
depth - 1,
96+
alpha,
97+
beta,
98+
);
99+
100+
if (result.score < minResult.score) {
101+
minResult = {score: result.score, move: next.move};
102+
}
103+
104+
beta = Math.min(beta, result.score);
105+
106+
if (beta <= alpha) {
107+
break;
108+
}
109+
}
110+
111+
return minResult;
112+
}
113+
}
114+
115+
return minimax;
116+
}
117+
118+
exports.minimaxBuilder = minimaxBuilder;
119+
120+
})(typeof window === 'undefined' ? module.exports : window);

test/data-structures/avl-tree.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ describe('AVL Tree', function () {
178178
avlTree.insert(6);
179179
avlTree.remove(32);
180180
avlTree.remove(11);
181-
avlTree.remove(25);
182-
181+
avlTree.remove(25);
182+
183183
// depth 1
184184
expect(avlTree._root.value).toBe(37);
185185
expect(avlTree._root._height).toBe(4);

0 commit comments

Comments
 (0)