-
Notifications
You must be signed in to change notification settings - Fork 2
/
RandomTrialsStrategy.hpp
70 lines (57 loc) · 2.36 KB
/
RandomTrialsStrategy.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#ifndef RANDOM_TRIALS_STRATEGY_HPP
#define RANDOM_TRIALS_STRATEGY_HPP
#include "Strategy.hpp"
class RandomTrialsStrategy : public Strategy {
/*
Parameters:
depth: depth to search, should be positive; note that search space increases exponentially with depth
trials: trials for each move checked
*/
// speed things up with integer arithmetic
// 4 moves, 20 max depth, multiplied by 4 to pack score and move
static constexpr eval_t MULT = 4e18 / (heuristics::MAX_EVAL * 4 * 20 * 4);
static_assert(MULT > 1);
heuristic_t evaluator;
public:
int depth, trials;
RandomTrialsStrategy(const int _depth, const int _trials, const heuristic_t _evaluator) {
depth = _depth;
trials = _trials;
evaluator = _evaluator;
}
RandomTrialsStrategy(const int _depth, const int _trials, const int heuristic_idx) :
RandomTrialsStrategy(_depth, _trials, heuristics::exports[heuristic_idx]) {}
std::unique_ptr<Strategy> clone() override {
return std::make_unique<RandomTrialsStrategy>(depth, trials, evaluator);
}
const int pick_move(const board_t board) override {
return helper(board, depth) & 3;
}
private:
const eval_t helper(const board_t board, const int cur_depth) {
if (simulator.game_over(board)) {
const eval_t score = (evaluator(board) * MULT) << 2;
return score - (score >> 4);
}
if (cur_depth == 0) {
return (evaluator(board) * MULT) << 2; // move doesn't matter
}
eval_t best_score = 0;
int best_move = 0; // default best_move to 0; -1 causes issues with the packing in cases of full boards
for (int i = 0; i < 4; ++i) {
const board_t new_board = simulator.make_move(board, i);
if (board == new_board) continue;
eval_t current_score = 0;
for (int j = 0; j < trials; ++j) {
current_score += helper(simulator.add_tile(new_board, simulator.generate_random_tile_val()),
cur_depth - 1) >> 2; // extract score
}
if (best_score <= current_score) {
best_score = current_score;
best_move = i;
}
}
return ((best_score / trials) << 2) | best_move; // pack both score and move
}
};
#endif