-
Notifications
You must be signed in to change notification settings - Fork 0
/
agent.h
120 lines (106 loc) · 3.07 KB
/
agent.h
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once
#include <string>
#include <random>
#include <sstream>
#include <map>
#include <type_traits>
#include <algorithm>
#include <cstdio>
#include "board.h"
#include "action.h"
class agent {
public:
agent(const std::string& args = "") {
std::stringstream ss(args);
for (std::string pair; ss >> pair; ) {
std::string key = pair.substr(0, pair.find('='));
std::string value = pair.substr(pair.find('=') + 1);
property[key] = { value };
}
}
virtual ~agent() {}
virtual void open_episode(const std::string& flag = "") {}
virtual void close_episode(const std::string& flag = "") {}
virtual action take_action(const board& b) { return action(); }
virtual bool check_for_win(const board& b) { return false; }
public:
virtual std::string name() const {
auto it = property.find("name");
return it != property.end() ? std::string(it->second) : "unknown";
}
protected:
typedef std::string key;
struct value {
std::string value;
operator std::string() const { return value; }
template<typename numeric, typename = typename std::enable_if<std::is_arithmetic<numeric>::value, numeric>::type>
operator numeric() const { return numeric(std::stod(value)); }
};
std::map<key, value> property;
};
/**
* evil (environment agent)
* add a new random tile on board, or do nothing if the board is full
* 2-tile: 90%
* 4-tile: 10%
*/
class rndenv : public agent {
public:
rndenv(const std::string& args = "") : agent("name=rndenv " + args) {
if (property.find("seed") != property.end())
engine.seed(int(property["seed"]));
}
virtual action take_action(const board& after) {
int space[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
std::shuffle(space, space + 16, engine);
for (int pos : space) {
if (after(pos) != 0) continue;
std::uniform_int_distribution<int> popup(0, 9);
int tile = popup(engine) ? 1 : 2;
return action::place(tile, pos);
}
return action();
}
private:
std::default_random_engine engine;
};
/**
* player (dummy)
* select an action randomly
*/
bool compareFunc(std::pair<int, int> &a, std::pair<int, int> &b)
{
return a.second > b.second;
}
class player : public agent {
public:
player(const std::string& args = "") : agent("name=player " + args) {
if (property.find("seed") != property.end())
engine.seed(int(property["seed"]));
}
virtual action take_action(const board& before) {
int opcode[] = { 0, 1, 2, 3 };
int sum[] = { 0, 0, 0, 0 }; // Up Right Down Left
//std::shuffle(opcode, opcode + 4, engine);
//std::cout << "OP CODE:" << opcode << '\n' ;
board b = before;
b.get_score_dummy1(sum);
std::vector<std::pair<int, int> > vp;
for (int i=0; i < 4 ; ++i)
vp.push_back( std::make_pair( opcode[i], sum[i]) );
std::sort(vp.begin(), vp.end(), compareFunc);
for (int i=0; i < 4 ; ++i)
opcode[i] = vp[i].first ;
// Opcode Move
for (int op : opcode){
board b = before;
if (b.move(op) != -1) {
//std::cout << "Valid OP:" << op << '\n' ;
return action::move(op);
}
}
return action();
}
private:
std::default_random_engine engine;
};