-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_a5.cpp
More file actions
140 lines (131 loc) · 5.62 KB
/
client_a5.cpp
File metadata and controls
140 lines (131 loc) · 5.62 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// だいたい点数の高い順に置き、点数の高い順に壊しながら動くアルゴリズム
#include "kakomimasu.h"
struct Tile_info {
int x, y;
int type, pid;
int point;
// ポイントが高い順にソートできるように比較演算子の定義
bool operator<(const Tile_info &right) const {
return point < right.point;
}
};
int main() {
// 自分のbearerTokenを書く
KakomimasuClient kc("");
kc.waitMatching();
kc.getGameInfo();
const int pno = kc.getPlayerNumber();
const vector<vector<int>> points = kc.getPoints();
const int w = kc.getWidth();
const int h = kc.getHeight();
const int nagents = kc.getAgentCount();
// ポイントの高い順ソート
// point, x, y
vector<tuple<int, int, int>> pntall;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pntall.emplace_back(points[i][j], j, i);
}
}
sort(pntall.rbegin(), pntall.rend());
// ↓ここからがAIの中身↓
while (kc.getGameInfo()) {
vector<Action> actions;
vector<vector<Tile>> field = kc.getFiled();
const int offset = rnd(nagents);
vector<tuple<int, int>> poschk; // 動く予定の場所
auto checkFree = [&](int x, int y) -> bool {
for (int i = 0; i < poschk.size(); i++) {
const auto [px, py] = poschk[i];
if (px == x && py == y)
return false;
}
return true;
};
for (int i = 0; i < nagents; i++) {
const Agent agent = kc.getAgent()[i];
if (agent.x == -1) { // 置く前
const auto [p_point, p_x, p_y] = pntall[i + offset];
actions.push_back({i, "PUT", p_x, p_y});
} else {
vector<Tile_info> dirall;
for (auto [dx, dy] : DIR) {
const int x = agent.x + dx;
const int y = agent.y + dy;
if (x >= 0 && x < w && y >= 0 && y < h && checkFree(x, y)) {
const Tile f = field[y][x];
if (f.type == 0 && f.pid != -1 && f.pid != pno && f.point > 0) { // 敵土地
dirall.push_back({x, y, f.type, f.pid, f.point + 10});
} else if (f.type == 0 && f.pid == -1 && f.point > 0) { // 空き土地
dirall.push_back({x, y, f.type, f.pid, f.point + 5});
} else if (f.type == 1 && f.pid != pno) { // 敵壁
dirall.push_back({x, y, f.type, f.pid, f.point});
}
}
}
if (dirall.size() > 0) {
sort(dirall.rbegin(), dirall.rend());
const Tile_info p = dirall[0];
if (p.type == 0 || p.pid == -1) {
actions.push_back({i, "MOVE", p.x, p.y});
poschk.push_back({p.x, p.y});
} else {
actions.push_back({i, "REMOVE", p.x, p.y});
}
poschk.push_back({agent.x, agent.y});
} else {
// 周りが全部埋まっていたら空いている高得点で一番近いところを目指す
int dis = w * h;
tuple<int, int, int> target;
bool target_flag = false;
for (const auto p : pntall) {
const auto [p_point, p_x, p_y] = p;
if (field[p_y][p_x].type == 0 && field[p_y][p_x].pid == -1) {
const int dx = agent.x - p_x;
const int dy = agent.y - p_y;
const int d = dx * dx + dy * dy;
if (d < dis) {
dis = d;
target = p;
target_flag = true;
}
}
}
if (target_flag) {
auto sgn = [&](int n) -> int {
if (n < 0) return -1;
if (n > 0) return 1;
return 0;
};
auto [target_point, target_x, target_y] = target;
const int x2 = agent.x + sgn(target_x - agent.x);
const int y2 = agent.y + sgn(target_y - agent.y);
const Tile p = field[y2][x2];
if (p.type == 0 || p.pid == -1) {
actions.push_back({i, "MOVE", x2, y2});
poschk.push_back({x2, y2});
} else {
actions.push_back({i, "REMOVE", x2, y2});
}
poschk.push_back({agent.x, agent.y});
} else {
while (1) {
const auto [dx, dy] = DIR[rnd(8)];
const int x = agent.x + dx;
const int y = agent.y + dy;
if (x < 0 || x >= w || y < 0 || y >= h) {
continue;
}
actions.push_back({i, "MOVE", x, y});
poschk.push_back({x, y});
break;
}
}
}
}
}
kc.setAction(actions);
kc.waitNextTurn();
}
return 0;
}