Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include "lib.cpp"
- #include <CImg.h>
- //#include <emmintrin.h>
- using namespace std;
- using namespace cimg_library;
- #define INLINE inline __attribute__ ((always_inline))
- #define NOINLINE __attribute__ ((noinline))
- #define ALIGNED __attribute__ ((aligned(16)))
- #define likely(x) __builtin_expect(!!(x),1)
- #define unlikely(x) __builtin_expect(!!(x),0)
- #define SSELOAD(a) _mm_load_si128((__m128i*)&a)
- #define SSESTORE(a, b) _mm_store_si128((__m128i*)&a, b)
- #define FOR(i,a,b) for(int i=(a);i<(b);++i)
- #define REP(i,a) FOR(i,0,a)
- #define ZERO(m) memset(m,0,sizeof(m))
- #define ALL(x) x.begin(),x.end()
- #define PB push_back
- #define S size()
- #define LL long long
- #define ULL unsigned long long
- #define LD long double
- #define MP make_pair
- #define X first
- #define Y second
- #define VC vector
- #define PII pair <int, int>
- #define VI VC < int >
- #define VVI VC < VI >
- #define VVVI VC < VVI >
- #define VPII VC < PII >
- #define VD VC < double >
- #define VVD VC < VD >
- #define VS VC < string >
- #define VVS VC < VS >
- #define DB(a) cerr << #a << ": " << (a) << endl;
- template<class T> void print(VC < T > v) {cerr << "[";if (v.S) cerr << v[0];FOR(i, 1, v.S) cerr << ", " << v[i];cerr << "]" << endl;}
- template<class T> string i2s(T x) {ostringstream o; o << x; return o.str();}
- VS splt(string s, char c = ' ') {VS all; int p = 0, np; while (np = s.find(c, p), np >= 0) {if (np != p) all.PB(s.substr(p, np - p)); p = np + 1;} if (p < s.S) all.PB(s.substr(p)); return all;}
- double pi = 2.0 * acos(0.0);
- int cut(int x, double a, int right, int &off) {
- const double EPS = 1E-6;
- double y = tan(a) * x;
- off = 0;
- if (y >= 0.0) {
- int iy = (int) ((y+1.0 + EPS) / 2.0);
- if (fabs(iy * 2.0 - 1.0 - y) < EPS) {
- if (!right) {
- iy--;
- }
- off=1;
- }
- return iy;
- } else {
- int iy = (int) (-(y-1.0 - EPS) / 2.0);
- iy = -iy;
- if (fabs(iy * 2.0 + 1.0 -y) < EPS) {
- if (!right) {
- iy++;
- }
- off = 1;
- }
- return iy;
- }
- }
- vector<pair<pair<int,int>,int> > cut_line_pom(int angle, int n) {
- vector<pair<pair<int,int>,int > > res;
- res.reserve(n);
- if (angle == 90) {
- for (int i = 1; i < n; ++i) res.push_back(make_pair(make_pair(-i, 0), 1));
- } else {
- double a = (double)angle / 180.0 * pi;
- for (int x = 1; x <= 2 * n + 4; x += 2) {
- int off, off2;
- int collast = cut(x- (x == 1 ? 1 : 2), a, 0, off);
- int colcur = cut(x, a, 1, off2);
- if (collast <= colcur) {
- for (int i = collast; i <= colcur; ++i) {
- int corner = (i == collast && off) || (i == colcur && off2);
- res.push_back(make_pair(make_pair(-i, x/2), !corner));
- }
- } else {
- for (int i = collast; i >= colcur; --i) {
- int corner = (i == collast && off) || (i == colcur && off2);
- res.push_back(make_pair(make_pair(-i, x/2), !corner));
- }
- }
- }
- }
- return res;
- }
- vector<pair<pair<int,int>,int> > cut_line(int x, int y, int angle, int n) {
- vector<pair<pair<int,int>,int> > v, res;
- if (angle >= 0 && angle <= 90 || angle >= 271) v = cut_line_pom(angle, n);
- else {
- v = cut_line_pom(angle < 180 ? (angle + 180) : (angle - 180), n);
- for (int i = 0; i < (int)v.size(); ++i) {
- v[i].first.first *= -1;
- v[i].first.second *= -1;
- }
- }
- for (int i = 0; i < (int)v.size(); ++i) {
- int xx = x + v[i].first.first;
- int yy = y + v[i].first.second;
- if (xx >= 0 && xx < n && yy >= 0 && yy < n) res.push_back(make_pair(make_pair(xx,yy),v[i].second));
- }
- return res;
- }
- VI split2VI(string s) {
- VS vs = splt(s, ' ');
- VI v(vs.S);
- REP(i, vs.S) v[i] = atoi(vs[i].c_str());
- return v;
- }
- VD split2VD(string s) {
- VS vs = splt(s, ' ');
- VD v(vs.S);
- REP(i, vs.S) v[i] = atof(vs[i].c_str());
- return v;
- }
- int need_init_full = 0;
- int need_init_vis = 1;
- char txt[10000];
- const int TEAMS_NO = 30;
- const int MAX_N = 120;
- const int MAX_MONSTERS = 30;
- const int MAX_BONUSES = 1000;
- int turn = -1;
- int roundID = -1;
- int turnNo = -1;
- bool gameRunning = false;
- int N;
- int teamsNo;
- int maxMonsters;
- int mapID;
- int teamID;
- PII sniper[TEAMS_NO + 2];
- int sniperDir[TEAMS_NO + 2];
- PII flag[TEAMS_NO + 2];
- int flagOwner[TEAMS_NO + 2];
- PII base[TEAMS_NO + 2];
- int monsterNo[TEAMS_NO + 2];
- int monsterVisNo[TEAMS_NO + 2];
- int mp[MAX_N][MAX_N];
- int bonusNo;
- PII bonus[MAX_BONUSES];
- string bonusType[MAX_BONUSES];
- int bonusTime[MAX_BONUSES];
- PII forceTarget = MP(-1, -1);
- PII sniperTarget = MP(-1, -1);
- int bonusUsed[256];
- string bonusKnown[256];
- int monstersNo;
- PII monsters[MAX_MONSTERS];
- int monstersID[MAX_MONSTERS];
- PII monstersDest[MAX_MONSTERS];
- PII monstersFinalDest[MAX_MONSTERS];
- int monstersSense[MAX_MONSTERS][3];
- int monstersVisNo;
- PII monstersVis[MAX_MONSTERS * 30];
- int monstersVisID[MAX_MONSTERS * 30];
- int monsterMap[MAX_N][MAX_N];
- int sniperMap[MAX_N][MAX_N];
- int bonusMap[MAX_N][MAX_N];
- int shots = 3;
- int lastReload = -100;
- int lastRotate = -100;
- mutex gameUpdate;
- bool needUpdate = false;
- bool mapLoaded = false;
- VI scores;
- VS logData;
- void addLog(string s) {
- s = "Turn: " + i2s(turn) + " :: " + s;
- logData.PB(s);
- }
- #define byte unsigned char
- void loadMap() {
- string s = "../ctf" + i2s(SERVER_ID+1) + "/map_" + i2s(mapID/10) + i2s(mapID%10) + ".txt";
- cout << "Loading Map : " << s << endl;
- ifstream fs(s.c_str());
- int x;
- fs >> x;
- ZERO(mp);
- REP(i, N) {
- fs >> s;
- REP(j, N) mp[i][j] = s[j] == '#';
- }
- fs.close();
- cout << "Map Loaded" << endl;
- mapLoaded = true;
- }
- VPII shootLine(int angle) {
- VC<pair<PII,int>> v = cut_line(sniper[teamID].X, sniper[teamID].Y, angle, N);
- VPII rv;
- REP(i, v.S) {
- if (mp[v[i].X.X][v[i].X.Y]) break;
- if (v[i].Y && monsterMap[v[i].X.X][v[i].X.Y]) rv.PB(v[i].X);
- }
- return rv;
- }
- int calcShootScore(int angle, bool close = false) {
- VPII v = shootLine(angle);
- int rv = 0;
- REP(i, v.S) {
- int d = abs(sniper[teamID].X-v[i].X) + abs(sniper[teamID].Y-v[i].Y);
- if (d > 1 && close) break;
- if (monsterMap[v[i].X][v[i].Y] == 0) addLog("Wut?");
- rv += monsterMap[v[i].X][v[i].Y] == teamID ? -1 : 1;
- }
- return rv;
- }
- VVI bfs(PII s) {
- queue<int> q;
- VVI v(N, VI(N, 1<<20));
- q.push(0);
- q.push(s.X);
- q.push(s.Y);
- while (!q.empty()) {
- int d = q.front(); q.pop();
- int x = q.front(); q.pop();
- int y = q.front(); q.pop();
- if (x < 0 || x >= N || y < 0 || y >= N || mp[x][y] || v[x][y] <= d) continue;
- v[x][y] = d;
- q.push(d+1), q.push(x+1), q.push(y);
- q.push(d+1), q.push(x-1), q.push(y);
- q.push(d+1), q.push(x), q.push(y+1);
- q.push(d+1), q.push(x), q.push(y-1);
- }
- return v;
- }
- VPII genPath(VVI &v, PII p) {
- int x = p.X;
- int y = p.Y;
- if (v[x][y] >= 1 << 19) return VPII();
- VPII vp;
- while (v[x][y]) {
- vp.PB(MP(x, y));
- if (x && v[x-1][y] < v[x][y]) {
- x--;
- } else if (x + 1 < N && v[x+1][y] < v[x][y]) {
- x++;
- } else if (y && v[x][y-1] < v[x][y]) {
- y--;
- } else if (y + 1 < N && v[x][y+1] < v[x][y]) {
- y++;
- }
- }
- vp.PB(MP(x, y));
- reverse(ALL(vp));
- return vp;
- }
- PII genDest(VPII &path) {
- int dirNo = 0;
- int dirs[4] = {0};
- int ox = path[0].X;
- int oy = path[0].Y;
- FOR(i, 1, path.S) {
- int d = path[i].X != path[i-1].X ? (path[i].X<path[i-1].X?0:1) : (path[i].Y<path[i-1].Y?2:3);
- if (dirs[d]==0) {
- dirNo++;
- if (dirNo>2) return path[i-1];
- if (dirNo==2) {
- int x = ox + (d == 0 ? -1 : d == 1 ? 1 : 0);
- int y = oy + (d == 2 ? -1 : d == 3 ? 1 : 0);
- if (x < 0 || x >= N || y < 0 || y >= N || mp[x][y]) return path[i-1];
- }
- }
- dirs[d]=1;
- }
- return path[path.S-1];
- }
- int angleDiff(int a, int b) {
- if (b < a) swap(a, b);
- return min(b - a, a - b + 360);
- }
- int optimalAngle(PII p1, PII p2) {
- int x = p2.X - p1.X;
- int y = p2.Y - p1.Y;
- double a = y;//asteroids[best].y - spaceships[i].y;
- double b = -x;//spaceships[i].x - asteroids[best].x;
- double alfa = (atan2(b,a) + 2.0 * pi) / 2.0 / pi * 360.0;
- int alfa2 = alfa;
- alfa2 %= 360;
- if (alfa2 < 0) alfa2 += 360;
- return alfa2;
- }
- double randDouble() {
- return (rand() + 0.5) / (RAND_MAX + 1.0);
- }
- char chooseMove() {
- const string moves = "NSWE";
- double values[4] = {0};
- int dx[] = {-1,1,0,0};
- int dy[] = {0,0,-1,1};
- REP(d, 4) {
- int x = sniper[teamID].X;
- int y = sniper[teamID].Y;
- x += dx[d];
- y += dy[d];
- if (x < 0 || y < 0 || x >= N || y >= N) continue;
- if (monsterMap[x][y] && monsterMap[x][y] != teamID) values[d] = -1e9;
- REP(dd, 4) {
- int nx = x + dx[d];
- int ny = y + dy[d];
- if (nx >= 0 && nx < N && ny >= 0 && ny < N && monsterMap[x][y] && monsterMap[x][y] != teamID) values[d] -= 10;
- }
- if (monsterMap[x][y] == teamID || mp[x][y]) values[d]--;
- }
- REP(d, 4) values[d] += randDouble();
- int rv = 0;
- REP(i, 4) if (values[i] > values[rv]) rv = i;
- return moves[rv];
- }
- int enemiesClose(PII p) {
- int dx[] = {-1,1,0,0};
- int dy[] = {0,0,-1,1};
- int rv = 0;
- REP(d, 4) {
- int x = p.X + dx[d];
- int y = p.Y + dy[d];
- rv += x >= 0 && x < N && y >= 0 && y < N && monsterMap[x][y] && monsterMap[x][y] != teamID;
- }
- return rv;
- }
- string moveSniper() {
- if (sniper[teamID].X == -1) {
- shots = 3;
- sniperTarget = MP(-1, -1);
- forceTarget = MP(-1, -1);
- return "RESPAWN";
- }
- if (forceTarget == sniper[teamID]) forceTarget = MP(-1, -1);
- int flags = 0;
- FOR(t, 1, teamsNo+1) flags += flagOwner[t] == teamID;
- bool flagBelow = false;
- FOR(t, 1, teamsNo+1) if (t != teamID && flagOwner[t] == 0 && flag[t] == sniper[teamID]) flagBelow = true;
- if (flags < 5 && flagBelow && enemiesClose(sniper[teamID]) == 0) {
- return "PICK_UP";
- }
- if (turn > lastReload + 5 && calcShootScore(sniperDir[teamID]) > 0 && enemiesClose(sniper[teamID]) - calcShootScore(sniperDir[teamID], true) <= 0) {
- shots--;
- if (shots == 0) lastReload = turn, shots = 3;
- return "SHOOT";
- }
- VVI dist = bfs(sniper[teamID]);
- int bflag = -1;
- int bv = 1<<20;
- FOR(t, 1, teamsNo+1) if (t != teamID && flagOwner[t] == 0 && flag[t].X != -1) {
- int av = dist[flag[t].X][flag[t].Y];
- if (av >= 1<<19) continue;
- if (av < bv) {
- bflag = t;
- bv = av;
- }
- }
- if (flags < 5 && bflag == -1) {
- return string("MOVE ") + chooseMove();
- }
- if (flags < 5 && bv == 0 && (flags > 0 || enemiesClose(sniper[teamID]) == 0)) {
- return "PICK_UP";
- }
- PII target = flags < 5 ? flag[bflag] : base[teamID];
- if (forceTarget.X != -1) target = forceTarget;
- sniperTarget = target;
- VVI dist2 = bfs(target);
- if (enemiesClose(sniper[teamID]) == 0 && angleDiff(sniperDir[teamID], optimalAngle(sniper[teamID], target)) > 45) {
- int angle = optimalAngle(sniper[teamID], target);
- if (angle % 90 == 45) angle--;
- return "ROTATE " + i2s(angle);
- lastRotate = turn;
- }
- const string moves = "NSWE";
- double values[4] = {0};
- int dx[] = {-1,1,0,0};
- int dy[] = {0,0,-1,1};
- int ox = sniper[teamID].X;
- int oy = sniper[teamID].Y;
- REP(d, 4) {
- int x = sniper[teamID].X + dx[d];
- int y = sniper[teamID].Y + dy[d];
- if (x < 0 || y < 0 || x >= N || y >= N || mp[x][y] || monsterMap[x][y] == teamID) {
- values[d] = -1e5;
- continue;
- }
- if (monsterMap[x][y] && monsterMap[x][y] != teamID) {
- values[d] = -1e9;
- continue;
- }
- values[d] -= 10 * enemiesClose(MP(x, y));
- if (sniperMap[x][y]) values[d] -= 6;
- if (dist2[ox][oy] > dist2[x][y]) values[d] += 5;
- if (dist2[ox][oy] == dist2[x][y]) values[d] += 2.5;
- }
- REP(d, 4) values[d] += randDouble();
- int rv = 0;
- REP(i, 4) if (values[i] > values[rv]) rv = i;
- if (values[rv] < -1 && enemiesClose(sniper[teamID]) == 0) {
- int ba = 0;
- int bv = -1<<20;
- for (int i = 22; i < 360; i += 45) {
- int av = calcShootScore(i);
- if (av > bv) {
- bv = av;
- ba = i;
- }
- }
- if (bv > 0) return string("ROTATE ") + i2s(ba);
- }
- return string("MOVE ") + moves[rv];
- }
- class XGame : public Game {
- void saveGameState() {
- }
- void loadGameState() {
- }
- void clearGameState() {
- gameUpdate.lock();
- mapLoaded = false;
- forceTarget = MP(-1, -1);
- sniperTarget = MP(-1, -1);
- shots = 3;
- bonusNo = 0;
- lastReload = -100;
- lastRotate = -100;
- ZERO(bonusUsed);
- REP(i, 256) bonusKnown[i] = "";
- logData.clear();
- gameUpdate.unlock();
- }
- void debug(string s) {
- printf("%s\n", s.c_str());
- network.logger.log(s.c_str());
- }
- void play() {
- int commandsLeft = 20;
- network.logger.log("New play");
- cout << "New Turn" << endl;
- VI gt = network.getTime();
- while (gt.empty() || gt[1] > gt[2]) {
- usleep((gt.empty() || gt[1] > gt[2]) ? 1000 * 200 : 1000 * 100);
- gt = network.getTime();
- }
- static int last_round = -1;
- /* Detect whether a new game has started in the meantime. */
- if (gt[0] != last_round) {
- cout << "New game" << endl;
- last_round = gt[0];
- clearGameState();
- }
- commandsLeft--;
- if (turn == gt[1]) return;
- gameUpdate.lock();
- roundID = gt[0];
- turn = gt[1];
- turnNo = gt[2];
- network.sendLine("DESCRIBE_WORLD");
- network.readOk();
- commandsLeft--;
- string line;
- line = network.readLine();
- VI v = split2VI(line);
- N = v[0];
- mapID = v[1];
- maxMonsters = v[2];
- teamsNo = v[3];
- teamID = v[4];
- if (!mapLoaded) {
- loadMap();
- }
- FOR(team, 1, teamsNo + 1) {
- VI v0 = split2VI(network.readLine());
- VI v1 = split2VI(network.readLine());
- VI v2 = split2VI(network.readLine());
- VI v3 = split2VI(network.readLine());
- sniper[team] = MP(v0[0], v0[1]);
- sniperDir[team] = v0[2];
- flag[team] = MP(v1[0], v1[1]);
- flagOwner[team] = v1[2];
- base[team] = MP(v2[0], v2[1]);
- monsterNo[team] = v3[0];
- monsterVisNo[team] = v3[1];
- }
- ZERO(bonusMap);
- REP(i, bonusNo) if (bonusTime[i] > 2) bonusMap[bonus[i].X][bonus[i].Y] = bonusType[i][0];
- bonusNo = atoi(network.readLine().c_str());
- REP(i, bonusNo) {
- VS vs = splt(network.readLine(), ' ');
- bonus[i] = MP(atoi(vs[0].c_str()), atoi(vs[1].c_str()));
- bonusType[i] = vs[2];
- bonusTime[i] = atoi(vs[3].c_str());
- bonusMap[bonus[i].X][bonus[i].Y] = 0;
- }
- REP(i, N) REP(j, N) if (bonusMap[i][j]) bonusUsed[bonusMap[i][j]] = 1;
- network.sendLine("DESCRIBE_MONSTERS");
- network.readOk();
- commandsLeft--;
- monstersNo = atoi(network.readLine().c_str());
- REP(i, monstersNo) {
- v = split2VI(network.readLine());
- monsters[i] = MP(v[1], v[2]);
- monstersDest[i] = MP(v[3], v[4]);
- monstersID[i] = v[0];
- monstersSense[i][0] = v[5];
- monstersSense[i][1] = v[6];
- monstersSense[i][2] = v[7];
- }
- needUpdate = true;
- if (sniper[teamID].X != -1) {
- network.sendLine("LOOK");
- network.readOk();
- commandsLeft--;
- monstersVisNo = atoi(network.readLine().c_str());
- REP(i, monstersVisNo) {
- v = split2VI(network.readLine());
- monstersVis[i] = MP(v[0], v[1]);
- monstersVisID[i] = v[2];
- }
- } else {
- monstersVisNo = 0;
- }
- ZERO(monsterMap);
- ZERO(sniperMap);
- REP(i, monstersNo) monsterMap[monsters[i].X][monsters[i].Y] = teamID;
- REP(i, monstersVisNo) monsterMap[monstersVis[i].X][monstersVis[i].Y] = monstersVisID[i];
- FOR(t, 1, teamsNo+1) if (sniper[t].X != -1) sniperMap[sniper[t].X][sniper[t].Y] = t;
- string sniperCMD = moveSniper();
- network.sendLine(sniperCMD.c_str());
- if (network.readOk()) {
- addLog(sniperCMD);
- } else {
- addLog(sniperCMD + " (FAILED!)");
- }
- commandsLeft--;
- int targets[TEAMS_NO + 2] = {0};
- targets[teamID] = 1000;
- int monsterMoved[30] = {0};
- VVI dist[MAX_MONSTERS];
- REP(i, monstersNo) {
- dist[i] = bfs(monsters[i]);
- monstersFinalDest[i] = MP(-1,-1);
- }
- while (commandsLeft) {
- int bd = 1<<20;
- int mid = -1;
- int sid = -1;
- REP(i, monstersNo) if (!monsterMoved[i]) FOR(t, 1, teamsNo+1) if (sniper[t].X != -1) {
- int ad = dist[i][sniper[t].X][sniper[t].Y];
- if (ad >= 1<<19) continue;
- ad += targets[t] * N / 2;
- if (ad < bd) {
- bd = ad;
- mid = i;
- sid = t;
- }
- }
- if (mid == -1) break;
- monsterMoved[mid] = 1;
- targets[sid]++;
- VPII path = genPath(dist[mid], sniper[sid]);
- PII dest = genDest(path);
- monstersFinalDest[mid] = sniper[sid];
- if (monstersDest[mid] == dest) continue;
- commandsLeft--;
- network.sendLine(("SEND_MONSTER " + i2s(monstersID[mid]) + " " + i2s(dest.X) + " " + i2s(dest.Y)).c_str());
- network.readOk();
- }
- while (commandsLeft) {
- int id = -1;
- REP(i, 256) if (bonusUsed[i] && bonusKnown[i] == "") id = i;
- if (id == -1) break;
- commandsLeft--;
- string cmd = string("BONUS_INFO ") + (char)id;
- DB(cmd);
- DB(id);
- network.sendLine((cmd).c_str());
- network.readOk();
- bonusKnown[id] = network.readLine();
- }
- if (commandsLeft >= 2) {
- scores = network.getAllScores();
- int myScore = network.getMyScore();
- REP(i, scores.S) if (scores[i] == myScore) scores[i] = -scores[i], myScore = -1;
- }
- // int enemyMonstersVisNo = 0;
- gameUpdate.unlock();
- fflush(stdout);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement