MauriJefe

P35895_en - Ork Island Q1 2017-18 - Joc EDA FIB UPC

Jan 9th, 2018
383
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "Player.hh"
  2. #include "State.hh"
  3. #include <list>
  4. #include <algorithm>
  5. #include <map>
  6. #include <set>
  7. #include <string>
  8. #include <cmath>
  9. #include <limits.h>
  10.  
  11.  
  12. /**
  13.  * Write the name of your player and save this file
  14.  * with the same name and .cc extension.
  15.  */
  16. #define PLAYER_NAME EnfermeraJoy
  17.  
  18.  
  19. struct PLAYER_NAME : public Player {
  20.  
  21.   /**
  22.    * Factory: returns a new instance of this class.
  23.    * Do not modify this function.
  24.    */
  25.   static Player* factory () {
  26.     return new PLAYER_NAME;
  27.   }
  28.  
  29.   /**
  30.   * Types and attributes for your player can be defined here.
  31.   */
  32.  
  33.   //////////////////STRUCTS DEFINITION/////////////////
  34.  
  35.   struct CityInfo;
  36.   struct PathInfo;
  37.   struct OrkThoughts;
  38.  
  39.   ////////////////VARIABLES//////////////
  40.  
  41.   map<int,OrkThoughts> orkBrain;
  42.   vector<CityInfo> cities;
  43.   vector<PathInfo> paths;
  44.   int orksPerCityAndPath;
  45.   set<int> aliveOrks;
  46.  
  47.   //////////////////STRUCTS ////////////////
  48.  
  49.   enum targetType {
  50.     T_ENEMY,
  51.     T_CITY,
  52.     T_PATH,
  53.     T_CELL,
  54.     T_NONE
  55.   };
  56.  
  57.   struct CityInfo{
  58.     Pos pos;
  59.     Pos posCenter; //Center position, if uncentered wins TOP and/or RIGHT
  60.     int id;
  61.     int height;
  62.     int width;
  63.     vector<Pos> positions;
  64.     vector<int> path;
  65.     map<int, pair<Pos,Dir> > pathBegin;
  66.     vector<int> nearCity;
  67.  
  68.     set<int> orksMine; //TODO update regularly
  69.  
  70.   };
  71.  
  72.   struct PathInfo{
  73.     int cityBegin;
  74.     int cityEnd;
  75.     Dir beginDir;
  76.     Dir endDir;
  77.     int id;
  78.     vector<Pos> positions;
  79.     int length;
  80.  
  81.     set<int> orksMine;
  82.   };
  83.  
  84.   struct Target {
  85.     targetType type;
  86.     int id;
  87.     int cell;
  88.     Pos pos;
  89.  
  90.     Target() : type(T_NONE) , id(-1) , cell(-1) {}
  91.   };
  92.  
  93.   Pos targetPos(Target t){
  94.     switch (t.type) {
  95.       case T_CITY:
  96.         return t.pos;
  97.         break;
  98.       case T_ENEMY:
  99.         return unit(t.id).pos;
  100.         break;
  101.       case T_PATH:
  102.         return t.pos;
  103.         break;
  104.       case T_CELL:
  105.         return t.pos;
  106.         break;
  107.       default:
  108.         //cerr << "Debug: Target pos unknown (targetType=" << t.type << ")" << endl;
  109.         Pos p(30,30);
  110.         return p;
  111.         break;
  112.     }
  113.   }
  114.  
  115.   struct OrkThoughts{
  116.     Target target;
  117.     vector < vector<Unit> > enemyAtStepsAway;
  118.     int sf; //Steps Followed an enemy
  119.   };
  120.  
  121.   //////////////////////FUNCTIONS////////////////////
  122.  
  123.   Pos distance(Pos a, Pos b){
  124.     if(b.i == 0 and b.j == 0) return b;
  125.     b.i -= a.i;
  126.     b.j -= a.j;
  127.     return b;
  128.   }
  129.  
  130.   Pos calcCityCenter(Pos pos, const int& width, const int& height){
  131.     pos.j += width/2;
  132.     pos.i += height/2;
  133.     return pos;
  134.   }
  135.  
  136.   CityInfo createCity(const vector<Pos>& positions, const int& id){
  137.     CityInfo c;
  138.     c.id = id;
  139.     //auto result = minmax_element(positions.begin(), positions.end());
  140.     //Pos size = distance(positions[result.first - positions.begin()], positions[result.second - positions.begin()]);
  141.     Pos size;
  142.     size = distance(positions[0], positions[positions.size()-1]); // alternative
  143.     c.width = size.j;
  144.     c.height = size.i;
  145.     c.positions = positions;
  146.     c.pos = positions[0];
  147.     c.posCenter = calcCityCenter(positions[0], size.j, size.i);
  148.     return c;
  149.   }
  150.  
  151.   Dir closestCityCellIsAt(const Pos& p){
  152.     vector<Dir> d;
  153.     d.push_back(TOP);
  154.     d.push_back(BOTTOM);
  155.     d.push_back(RIGHT);
  156.     d.push_back(LEFT);
  157.     for (int i = 0; i < 4; i++) {
  158.       if(cell(p+d[i]).type == CITY) return d[i];
  159.     }
  160.     return NONE;
  161.   }
  162.  
  163.   Dir closestWaterCellIsAt(const Pos& p){
  164.     vector<Dir> d;
  165.     d.push_back(TOP);
  166.     d.push_back(BOTTOM);
  167.     d.push_back(RIGHT);
  168.     d.push_back(LEFT);
  169.     vector<int> r(4);
  170.     r = random_permutation(4);
  171.     for (int i = 0; i < (int)r.size(); i++) {
  172.       if(cell(p+d[r[i]]).type == WATER) return d[r[i]];
  173.     }
  174.     return NONE;
  175.   }
  176.  
  177.   bool hasWaterNear(const int& orkId){
  178.     return closestWaterCellIsAt(unit(orkId).pos) != NONE;
  179.   }
  180.  
  181.   PathInfo createPath(const pair< pair<int,int>, vector<Pos> >& positions, const int& id){
  182.     PathInfo p;
  183.     p.cityBegin = positions.first.first;
  184.     p.cityEnd = positions.first.second;
  185.     p.beginDir = closestCityCellIsAt(positions.second[0]);
  186.     p.endDir = closestCityCellIsAt(positions.second[positions.second.size()-1]);
  187.     p.id = id;
  188.     p.positions = positions.second;
  189.     p.length = positions.second.size();
  190.     return p;
  191.   }
  192.  
  193.   int distanceLength(const Pos& a){
  194.     return abs(a.i) + abs(a.j);
  195.   }
  196.  
  197.   bool isSafe(const Pos& p){
  198.     return (cell(p).type == CITY) or (cell(p).type == PATH);
  199.   }
  200.  
  201.   bool isSafe(const int& orkId){
  202.     return (cell(unit(orkId).pos).type == CITY) or (cell(unit(orkId).pos).type == PATH);
  203.   }
  204.  
  205.   bool isInAPath(const int& orkId){
  206.     return cell(unit(orkId).pos).type == PATH;
  207.   }
  208.  
  209.   bool isInACity(const int& orkId){
  210.     return cell(unit(orkId).pos).type == CITY;
  211.   }
  212.  
  213.   bool targetIsAPath(const int& orkId){
  214.     return orkBrain[orkId].target.type == T_PATH;
  215.   }
  216.  
  217.   bool targetIsACity(const int& orkId){
  218.     return orkBrain[orkId].target.type == T_CITY;
  219.   }
  220.  
  221.   bool targetIsACell(const int& orkId){
  222.     return orkBrain[orkId].target.type == T_CELL;
  223.   }
  224.  
  225.   int currentCity(const int& orkId){
  226.     return cell(unit(orkId).pos).city_id;
  227.   }
  228.  
  229.   int currentPath(const int& orkId){
  230.     return cell(unit(orkId).pos).path_id;
  231.   }
  232.  
  233.   Dir randDir(){
  234.     if(random(0,50) == 0) return NONE;
  235.     return random(0,1) ? randDir(TOP,BOTTOM) : randDir(LEFT,RIGHT);
  236.   }
  237.  
  238.   Dir randDir(const Dir& a, const Dir& b){
  239.     return random(0,1) ? a : b;
  240.   }
  241.  
  242.   Dir randDir(const Dir& a, const Dir& b, const Dir& c){
  243.     return random(0,1) ? randDir(a,b) : b;
  244.   }
  245.  
  246.   Dir dominantDir(const Pos& p){
  247.     double x = p.j;
  248.     double y = -p.i;
  249.     if(x==0.0 and y==0.0) return NONE; //also could be randDir()
  250.     double aRad = atan2(y, x);
  251.     double a = (aRad / M_PI) * 180.0;
  252.  
  253.     if(a<0) a += 360.0;
  254.  
  255.     switch((int)a){
  256.       case 45: return randDir(TOP,RIGHT); break;
  257.       case 135: return randDir(TOP,LEFT); break;
  258.       case 225: return randDir(BOTTOM,LEFT); break;
  259.       case 315: return randDir(BOTTOM,RIGHT); break;
  260.     }
  261.     if(a<45.0 or a>315.0) return RIGHT;
  262.     if(a>45.0 and a<135.0) return TOP;
  263.     if(a>135.0 and a<225.0) return LEFT;
  264.     if(a>225.0 and a<315.0) return BOTTOM;
  265.     return randDir();
  266.   }
  267.  
  268.   Dir opositeDir(const Dir& d){
  269.     switch (d) {
  270.       case TOP: return BOTTOM; break;
  271.       case BOTTOM: return TOP; break;
  272.       case LEFT: return RIGHT; break;
  273.       case RIGHT: return LEFT; break;
  274.       default: return d; break;
  275.     }
  276.   }
  277.  
  278.   string dirName(const Dir& d){
  279.     switch (d) {
  280.       case TOP: return "TOP"; break;
  281.       case BOTTOM: return "BOTTOM"; break;
  282.       case RIGHT: return "RIGHT"; break;
  283.       case LEFT: return "LEFT"; break;
  284.       case NONE: return "NONE"; break;
  285.       default: return "UNKNOWN"; break;
  286.     }
  287.   }
  288.  
  289.   void move(const int& orkId, const Dir& dir){
  290.     avoidCloserEnemies(orkId,dir);
  291.     move2(orkId, dir,0);
  292.   }
  293.  
  294.   void move2(const int& orkId, const Dir& dir, int tryNum){
  295.     Pos newPos = unit(orkId).pos + dir;
  296.     if(tryNum<30){
  297.       ++tryNum;
  298.       if(pos_ok(newPos) and cell(newPos).type != WATER){
  299.         int friendOrkId = cell(newPos).unit_id;
  300.         if(isMyOrk(friendOrkId)){
  301.           //cerr << "Debug: Ork " << orkId << " tried to walk on a friend by going to " << dirName(dir) << " at " << newPos << endl; //debug
  302.           if (isSafe(newPos) and random(0,4)!=0) {
  303.             execute(Command(orkId, dir));
  304.           }else{
  305.             move2(orkId, randDir(),tryNum);
  306.           }
  307.           orkBrain[orkId].target.type = T_NONE;
  308.         }else{
  309.           execute(Command(orkId, dir));
  310.           //if(dir == NONE) cerr << "Debug: Ork " << orkId << " didn't move" << endl; //debug
  311.           //else cerr << "Debug: Ork " << orkId << " moved " << dirName(dir) << " to " << newPos << endl; //debug
  312.         }
  313.       }else{
  314.         //cerr << "Debug: Ork " << orkId << " tried to walk on water by going to " << dirName(dir) << " at " << newPos << endl; //debug
  315.         move2(orkId, randDir(),tryNum);
  316.         orkBrain[orkId].target.type = T_NONE;
  317.       }
  318.     }else{
  319.       //cerr << "Debug: Ork " << orkId << " tried " << tryNum << " times to move, so he won't care about where to go" << endl; //debug
  320.       execute(Command(orkId, dir));
  321.       //if(dir == NONE) cerr << "Debug: Ork " << orkId << " didn't move" << endl; //debug
  322.       //else cerr << "Debug: Ork " << orkId << " moved " << dirName(dir) << " to " << newPos << endl; //debug
  323.     }
  324.   }
  325.  
  326.   void avoidCloserEnemies(const int& orkId, const Dir& dir){
  327.     Pos newPos = unit(orkId).pos + dir;
  328.     vector<Unit> enemies = enemiesCloserThanWithMoreHealth(orkId,2);
  329.     if(not enemies.empty()){
  330.       //cerr << "Debug: Ork " << orkId << " has enemies with more health close" << endl;
  331.       //cerr << "has enemies closer" << endl;
  332.       set<Dir> dirToGo = {TOP,BOTTOM,RIGHT,LEFT};
  333.       for (int i = 0; i < (int)enemies.size(); i++) {
  334.         Pos enemyPos = enemies[i].pos;
  335.         if(enemies[i].health >= unit(orkId).health){
  336.           if(newPos == (enemyPos + BOTTOM)) dirToGo.erase(TOP);
  337.           if(newPos == (enemyPos + LEFT)) dirToGo.erase(RIGHT);
  338.           if(newPos == (enemyPos + TOP)) dirToGo.erase(BOTTOM);
  339.           if(newPos == (enemyPos + RIGHT)) dirToGo.erase(LEFT);
  340.           if(newPos == enemyPos) dirToGo.erase(dir);
  341.         }
  342.       }
  343.       if(find(dirToGo.begin(), dirToGo.end(), dir) == dirToGo.end()){
  344.         auto it = dirToGo.begin();
  345.         advance(it,random(0, dirToGo.size()-1));
  346.         //cerr << "Debug: Ork " << orkId << " dogged an enemy going to " << dirName(*it) << endl;
  347.         move2(orkId, *it,0);
  348.         orkBrain[orkId].target.type = T_NONE;
  349.       }
  350.       /*
  351.       if(dirToGo.empty()){
  352.         cerr << "Debug: Ork " << orkId << " is traped but will continue walking" << endl; //debug
  353.       }else{
  354.         set<Dir> safeDirToGo(dirToGo);
  355.         for (auto it = safeDirToGo.begin(); it != safeDirToGo.end(); ++it) {
  356.           if(not isSafe(unit(orkId).pos + *it)) safeDirToGo.erase(it);
  357.         }
  358.         if(safeDirToGo.empty()){
  359.           cerr << "Debug: Ork " << orkId << " can't go to any safe cell" << endl; //debug
  360.           auto it = dirToGo.begin();
  361.           advance(it,random(0, dirToGo.size()-1));
  362.           move2(orkId, *it,0);
  363.           orkBrain[orkId].target.type = T_NONE;
  364.         }else{
  365.           if(find(safeDirToGo.begin(), safeDirToGo.end(), dir) == safeDirToGo.end()){
  366.             auto it = safeDirToGo.begin();
  367.             advance(it,random(0, safeDirToGo.size()-1));
  368.             move2(orkId, *it,0);
  369.             orkBrain[orkId].target.type = T_NONE;
  370.           }
  371.         }
  372.       }*/
  373.     }
  374.   }
  375.  
  376.   void getTerrainInfo() {
  377.     for (int i = 0; i < nb_cities(); i++) {
  378.       cities[i] = createCity(city(i), i);
  379.     }
  380.  
  381.     pair< pair<int,int>, vector<Pos> > p;
  382.     for (int i = 0; i < nb_paths(); i++) {
  383.       p = path(i);
  384.       cities[p.first.first].nearCity.push_back(p.first.second);
  385.       cities[p.first.first].path.push_back(i);
  386.       cities[p.first.second].nearCity.push_back(p.first.first);
  387.       cities[p.first.second].path.push_back(i);
  388.       paths[i] = createPath(p,i);
  389.       cities[p.first.first].pathBegin[i].first = p.second[0] + paths[i].beginDir;
  390.       cities[p.first.first].pathBegin[i].second = opositeDir(paths[i].beginDir);
  391.       cities[p.first.second].pathBegin[i].first = p.second[(int)p.second.size() -1] + paths[i].endDir;
  392.       cities[p.first.second].pathBegin[i].second = opositeDir(paths[i].endDir);
  393.       //cerr << "Debug: " << p.second[0] << "+" << paths[i].beginDir << "=" << cities[p.first.first].pathBegin[i].first << endl;
  394.       //cerr << "Debug: City " << p.first.first << " connected to path " << i << " pos=" << cities[p.first.first].pathBegin[i].first << " dir=" << dirName(cities[p.first.first].pathBegin[i].second) << endl;
  395.       //cerr << "Debug: " << p.second[(int)p.second.size() -1] << "+" << paths[i].endDir << "=" << cities[p.first.second].pathBegin[i].first << endl;
  396.       //cerr << "Debug: City " << p.first.second << " connected to path " << i << " pos=" << cities[p.first.second].pathBegin[i].first << " dir=" << dirName(cities[p.first.second].pathBegin[i].second) << endl;
  397.     }
  398.   }
  399.  
  400.   void say(const vector<int>& v){
  401.     cerr << "{ ";
  402.     for (int i = 0; i < (int)v.size(); i++) {
  403.       cerr << "(id=" << v[i] << " pos=" << unit(v[i]).pos << " hp=" << unit(v[i]).health << " target={type=" << orkBrain[v[i]].target.type << " pos=" << targetPos(orkBrain[v[i]].target) << " id=" << orkBrain[v[i]].target.id << " isCity=" << targetIsACity(v[i]) << " isPath=" << targetIsAPath(v[i]) << "})";
  404.     }
  405.     cerr << "}" << endl;
  406.   }
  407.  
  408.   bool isNotMyOrk(const int& orkId){
  409.     auto myOrks = orks(me());
  410.     return orkId>=0 and find(myOrks.begin(), myOrks.end(), orkId) == myOrks.end();
  411.   }
  412.  
  413.   bool isMyOrk(const int& orkId){
  414.     auto myOrks = orks(me());
  415.     return orkId>=0 and find(myOrks.begin(), myOrks.end(), orkId) != myOrks.end();
  416.   }
  417.  
  418.   void findEnemies(const int& orkId, const int& stepsAway){
  419.     orkBrain[orkId].enemyAtStepsAway.clear();
  420.     orkBrain[orkId].enemyAtStepsAway.resize(stepsAway + 1);
  421.     //cerr << "Debug : Finding enemies closer than " << stepsAway << " from ork " << orkId << endl;
  422.     for (int i = -stepsAway; i < stepsAway; i++) {
  423.       for (int j = -stepsAway; j < stepsAway; j++) {
  424.         Pos p(i,j);
  425.         Pos enemyPos = p + unit(orkId).pos;
  426.         if(pos_ok(enemyPos) and distanceLength(p) <= stepsAway){
  427.           int enemyId = cell(enemyPos).unit_id;
  428.           if(isNotMyOrk(enemyId)){ //if has a ork and is not mine
  429.             orkBrain[orkId].enemyAtStepsAway[distanceLength(p)].push_back(unit(enemyId));
  430.             //cerr << "Debug: Found one enemy at " << enemyPos << " with id=" << enemyId << " and " << distanceLength(p) << " steps away in direction " << p << endl;
  431.           }
  432.         }
  433.         //cerr << "Debug: Not found enemy at " << enemyPos << " in " << distanceLength(p) << " steps away in direction " << p << " with pos_ok=" << pos_ok(enemyPos) << " and enemyId=" << cell(enemyPos).unit_id  << " notMine=" << isNotMyOrk(cell(enemyPos).unit_id) << endl;
  434.       }
  435.     }
  436.   }
  437.  
  438.   vector<Unit> enemiesCloserThanWithMoreHealth(const int& orkId, const int& stepsAway){
  439.     vector<Unit> p(0);
  440.     vector< vector<Unit> > enemies = orkBrain[orkId].enemyAtStepsAway;
  441.     for (int i=1; i < stepsAway; i++) {
  442.       for(int j=0; j<(int)enemies[i].size(); j++){
  443.         if(enemies[i][j].health >= unit(orkId).health) {
  444.           p.push_back(enemies[i][j]);
  445.           //cerr << "Debug: Ork " << orkId << " has enemy " << enemies[i].second[i].id << " at " << i << " steps away, with less health" << endl;
  446.         }
  447.       }
  448.     }
  449.     return p;
  450.   }
  451.  
  452.   vector<Unit> enemiesCloserThanWithLessHealth(const int& orkId, const int& stepsAway){
  453.     vector<Unit> p(0);
  454.     vector< vector<Unit> > enemies = orkBrain[orkId].enemyAtStepsAway;
  455.     for (int i=1; i < stepsAway; i++) {
  456.       for(int j=0; j<(int)enemies[i].size(); j++){
  457.         if(enemies[i][j].health < unit(orkId).health) {
  458.           p.push_back(enemies[i][j]);
  459.           //cerr << "Debug: Ork " << orkId << " has enemy " << enemies[i].second[i].id << " at " << i << " steps away, with less health" << endl;
  460.         }
  461.       }
  462.     }
  463.     return p;
  464.   }
  465.  
  466.   void updateOrksMine(){
  467.     for(int i = 0; i < (int)cities.size(); ++i) cities[i].orksMine.clear();
  468.     for(int i = 0; i < (int)paths.size(); ++i) paths[i].orksMine.clear();
  469.  
  470.     for (int i = 0; i < (int) orks(me()).size(); i++) {
  471.       int orkId = orks(me())[i];
  472.       if (isInACity(orkId)) cities[currentCity(orkId)].orksMine.insert(orkId);
  473.       if (isInAPath(orkId)) paths[currentPath(orkId)].orksMine.insert(orkId);
  474.     }
  475.   }
  476.  
  477.   void deleteDeadOrks(){
  478.     auto it = orkBrain.begin();
  479.     while(it != orkBrain.end()){
  480.       if(isNotMyOrk(it->first)){
  481.         for(int i = 0; i < (int)cities.size(); ++i) {
  482.           cities[i].orksMine.erase(it->first);
  483.         }
  484.         for(int i = 0; i < (int)paths.size(); ++i) {
  485.           paths[i].orksMine.erase(it->first);
  486.         }
  487.         //cerr << "Debug: Ork " << it->first << " died" << endl;
  488.         it = orkBrain.erase(it);
  489.       }else ++it;
  490.     }
  491.   }
  492.  
  493.   void updateOrksAlive(){
  494.     set<int> deadOrks(aliveOrks);
  495.     aliveOrks.clear();
  496.     for (int playerId = 0; playerId < nb_players(); playerId++) {
  497.       for (int i = 0; i < (int)orks(playerId).size(); i++) {
  498.         aliveOrks.insert(orks(playerId)[i]);
  499.         deadOrks.erase(orks(playerId)[i]);
  500.       }
  501.     }
  502.     for (auto it = deadOrks.begin(); it != deadOrks.end(); ++it) {
  503.       //cerr << "Debug: Enemy ork " << *it << " died" << endl;
  504.       for (auto it2 = orkBrain.begin(); it2 != orkBrain.end(); it2++) {
  505.         if((it2->second).target.type == T_ENEMY and (it2->second).target.id == (*it)){
  506.           //cerr << "Debug: Ork " << it2->first << " was following enemy ork " << *it << " but now he's dead" << endl;
  507.           (it2->second).target.type = T_NONE;
  508.           (it2->second).target.id = -1;
  509.           (it2->second).target.pos = Pos(0,0);
  510.         }
  511.       }
  512.     }
  513.   }
  514.  
  515.   void updateVariables(){
  516.     deleteDeadOrks();
  517.     updateOrksAlive();
  518.     orksPerCityAndPath =  max((nb_cities() + nb_paths()) / max((int)orks(me()).size(),1),2) ; //TODO implement
  519.     updateOrksMine();
  520.     for (int i = 0; i < (int) orks(me()).size(); i++){
  521.       int orkId = orks(me())[i];
  522.       findEnemies(orkId,5);
  523.       if(orkBrain[orkId].target.type == T_ENEMY){
  524.         if(isNotMyOrk(orkBrain[orkId].target.id)){
  525.           orkBrain[orkId].target.pos = unit(orkBrain[orkId].target.id).pos;
  526.         }else{
  527.           orkBrain[orkId].target.type = T_NONE;
  528.           orkBrain[orkId].target.id = -1;
  529.           orkBrain[orkId].target.pos = Pos(35,35);
  530.           //cerr << "Debug: ork followed died -----------------------------------------" << endl;
  531.         }
  532.       }
  533.     }
  534.   }
  535.  
  536.   void setTargetClosestSafeCell(const int& orkId){ //normally from a non safe cell
  537.     vector<Pos> closestSafeCells;
  538.     int closestSafeCellsIsStepsAway = cols() + rows() + 1;
  539.  
  540.     for(auto cit : cities){
  541.       for(auto pos : cit.positions){
  542.         int dist = distanceLength(distance(unit(orkId).pos,pos));
  543.  
  544.         if(dist < closestSafeCellsIsStepsAway){
  545.           closestSafeCellsIsStepsAway = dist;
  546.           closestSafeCells.clear();
  547.           closestSafeCells.push_back(pos);
  548.         }else{
  549.           if(dist == closestSafeCellsIsStepsAway){
  550.             closestSafeCells.push_back(pos);
  551.           }
  552.         }
  553.       }
  554.     }
  555.  
  556.     for(auto pa : paths){
  557.       for(auto pos : pa.positions){
  558.         int dist = distanceLength(distance(unit(orkId).pos,pos));
  559.  
  560.         if(dist < closestSafeCellsIsStepsAway){
  561.           closestSafeCellsIsStepsAway = dist;
  562.           closestSafeCells.clear();
  563.           closestSafeCells.push_back(pos);
  564.         }else{
  565.           if(dist == closestSafeCellsIsStepsAway){
  566.             closestSafeCells.push_back(pos);
  567.           }
  568.         }
  569.       }
  570.     }
  571.  
  572.     Pos randomClosestSafeCell = closestSafeCells[random(0, (int)closestSafeCells.size()-1)];
  573.  
  574.     if (cell(randomClosestSafeCell).type == CITY) {
  575.       orkBrain[orkId].target.id = cell(randomClosestSafeCell).city_id;
  576.       orkBrain[orkId].target.type = T_CITY;
  577.       orkBrain[orkId].target.pos = randomClosestSafeCell;
  578.     }else{
  579.       orkBrain[orkId].target.id = cell(randomClosestSafeCell).path_id;
  580.       orkBrain[orkId].target.type = T_PATH;
  581.       orkBrain[orkId].target.pos = randomClosestSafeCell;
  582.     }
  583.  
  584.     // cerr << "Debug: Ork " << orkId << " closest safe cells are: ";
  585.     // for (int i = 0; i < (int)closestSafeCells.size(); i++) {
  586.     //   cerr << "(type=" << cell(closestSafeCells[i]).type << " pos=" << targetPos(orkBrain[orkId].target) << " idC=" << cell(closestSafeCells[i]).city_id << " idP=" << cell(closestSafeCells[i]).path_id << ") " ;
  587.     // }
  588.     // cerr << endl;
  589.     // cerr << "Debug: Ork " << orkId << " decided to go to the cell " << randomClosestSafeCell << " because is one of the closest safe cells" << endl; //debug
  590.  
  591.   }
  592.  
  593.   void setTarget(const int& orkId, const targetType& type, const int& id, const Pos& pos){
  594.     orkBrain[orkId].target.type = type;
  595.     orkBrain[orkId].target.id = id;
  596.     orkBrain[orkId].target.pos = pos;
  597.   }
  598.  
  599.   void setTargetCenter(const int& orkId){
  600.     orkBrain[orkId].target.type = T_CELL;
  601.     orkBrain[orkId].target.id = -1;
  602.     orkBrain[orkId].target.pos = Pos(30,30);
  603.   }
  604.  
  605.   void decideCityOrPathToGo(const int& orkId){ //normaly from a safe cell, chose where to go //TODO if a near city dosen't have any coming and is from other team a go there fast
  606.     if (isInACity(orkId)) {
  607.       CityInfo city = cities[currentCity(orkId)];
  608.       int currentCityOrks = city.orksMine.size() ;
  609.  
  610.       for (int i=0; i < (int) city.path.size(); i++) {
  611.         int pathId = city.path[i];
  612.         int targetPathOrks = paths[pathId].orksMine.size();
  613.         if( me() != path_owner(pathId) or (targetPathOrks < (currentCityOrks-1))){
  614.           orkBrain[orkId].target.type = T_PATH;
  615.           orkBrain[orkId].target.id = pathId;
  616.           orkBrain[orkId].target.pos = city.pathBegin[pathId].first + city.pathBegin[pathId].second;
  617.           //cerr << "Debug: Ork " << orkId << " in city " << currentCity(orkId) << " decided to go to path " << pathId << endl;
  618.           return;
  619.         }
  620.         //cerr << "Debug: Ork " << orkId << " in city " << currentCity(orkId) << " won't go the path " << pathId << endl;
  621.       }
  622.       //cerr << "Debug: Ork " << orkId << " in city " << currentCity(orkId) << " decided to stay" << endl;
  623.     }else{
  624.       int currentPathOrks = paths[currentPath(orkId)].orksMine.size() ;
  625.       int cityBegin = paths[currentPath(orkId)].cityBegin;
  626.       int cityEnd = paths[currentPath(orkId)].cityEnd;
  627.  
  628.       vector<int> ci(2,cityBegin);
  629.       ci[1]=cityEnd;
  630.       for (int i=0; i < (int) ci.size(); i++){
  631.         if ( (int)cities[ci[i]].orksMine.size() < (currentPathOrks-1) or city_owner(ci[i])!=me()) {
  632.           orkBrain[orkId].target.type = T_CITY;
  633.           orkBrain[orkId].target.id = ci[i];
  634.           orkBrain[orkId].target.pos = cities[ci[i]].pathBegin[currentPath(orkId)].first;
  635.           //cerr << "Debug: Ork " << orkId << " in path " << currentPath(orkId) << " decided to go to city " << ci[i] << " because it has " << currentPathOrks - (int)cities[ci[i]].orksMine.size() << " orks less than his path" << endl;
  636.           return;
  637.         }
  638.       }
  639.       //if (currentPathOrks>orksPerCityAndPath) setTargetCenter(orkId);
  640.     }
  641.   }
  642.  
  643.   void improvePositionInCityOrPath(const int& orkId){ //TODO add interaction with enemies
  644.     Pos pos = unit(orkId).pos;
  645.  
  646.     if (isInACity(orkId)) { //if it's in a city
  647.       //cerr << "Debug: Ork " << orkId << " at " << pos << " is improving his position by going to the center " << cities[currentCity(orkId)].posCenter << " of the city " << currentCity(orkId) << endl; //debug
  648.       move(orkId,dominantDir( distance( pos, cities[currentCity(orkId)].posCenter)));
  649.     } else if(isInAPath(orkId)){ //if it's in a path
  650.       int orksBeforeInPath = 0;
  651.       int orkIndex = 0;
  652.       PathInfo path = paths[currentPath(orkId)];
  653.  
  654.       for (int i = 0; i < path.length and cell(path.positions[i]).unit_id != orkId ; i++) {
  655.         if(isMyOrk(cell(path.positions[i]).unit_id)) ++orksBeforeInPath;
  656.         ++orkIndex;
  657.       }
  658.       int segment = path.length / ((int) path.orksMine.size() +1);
  659.       int pathIndex = segment * orksBeforeInPath;
  660.       Dir d = NONE;
  661.       if(orkIndex<pathIndex){
  662.         d = dominantDir( distance( pos, path.positions[orkIndex+1]));
  663.       }else if(orkIndex>pathIndex){
  664.         d = dominantDir( distance( pos, path.positions[orkIndex-1]));
  665.       }
  666.       //cerr << "Debug: Ork " << orkId << " at " << pos << " is improving his position by going " << dirName(d) << " to " << pos+d << ",that is the " << pathIndex << "/" << path.length << " cell of the path " << currentPath(orkId) << " because he is the " << orksBeforeInPath << "th ork, and each of the " << path.orksMine.size() << " orks is " << segment << " steps away" << endl; //debug
  667.       move(orkId,d);
  668.     }
  669.   }
  670.  
  671.   void advanceTowardsCityOrPathToGo(const int& orkId){
  672.     Pos pos = unit(orkId).pos;
  673.     int targetId = orkBrain[orkId].target.id;
  674.  
  675.     if (isInACity(orkId)) {//if in a city going to path
  676.       Pos pathBeginPos = cities[currentCity(orkId)].pathBegin[targetId].first;
  677.       Dir pathBeginDir = cities[currentCity(orkId)].pathBegin[targetId].second;
  678.       //cerr << "Debug: Ork " << orkId << " is going to path " << targetId << " begin at " << pathBeginPos << " to " << dirName(pathBeginDir) << endl;
  679.       if(pos == pathBeginPos){//if is next to the path
  680.         move(orkId, pathBeginDir);
  681.       }else {//if is in the city
  682.         move(orkId,dominantDir(distance(pos,pathBeginPos)));
  683.       }
  684.     } else{
  685.       PathInfo path = paths[currentPath(orkId)];
  686.       auto it = find(path.positions.begin(), path.positions.end(), pos);
  687.       if (targetId == path.cityEnd) {
  688.         if(pos == path.positions[path.length - 1]) {
  689.           move(orkId,path.endDir);
  690.         }else{
  691.           move(orkId,dominantDir( distance( pos, *(++it) )));
  692.         }
  693.       }else{
  694.         if(pos == path.positions[0]) {
  695.           move(orkId,path.beginDir);
  696.         }else {
  697.           move(orkId,dominantDir( distance( pos, *(--it) )));
  698.         }
  699.       }
  700.     }
  701.   }
  702.  
  703.   bool followed(const int& enemyId){
  704.     for (auto it = orkBrain.begin(); it != orkBrain.end(); it++) {
  705.       if((it->second.target.type == T_ENEMY) and (it->second.target.id == enemyId)) return true;
  706.     }
  707.     return false;
  708.   }
  709.  
  710.   void setTargetClosestEnemyWithLessHealth(const int& orkId, const int& stepsAway){
  711.     vector< vector<Unit> > enemies = orkBrain[orkId].enemyAtStepsAway;
  712.     for (int i = 1; i < stepsAway; i++) {
  713.       for (int j = 0; j < (int)enemies[i].size(); j++) {
  714.         if (enemies[i][j].health < unit(orkId).health and (not followed(enemies[i][j].id))) {
  715.           orkBrain[orkId].target.type = T_ENEMY;
  716.           orkBrain[orkId].target.id = enemies[i][j].id;
  717.           orkBrain[orkId].target.pos = enemies[i][j].pos;
  718.           return;
  719.         }
  720.       }
  721.     }
  722.   }
  723.  
  724.   void setTargetClosestEnemyWithLessHealthAndInASafeCell(const int& orkId, const int& stepsAway){
  725.     vector< vector<Unit> > enemies = orkBrain[orkId].enemyAtStepsAway;
  726.     for (int i = 1; i < stepsAway; i++) {
  727.       for (int j = 0; j < (int)enemies[i].size(); j++) {
  728.         if (enemies[i][j].health < unit(orkId).health and isSafe(enemies[i][j].pos) and (not followed(enemies[i][j].id))) {
  729.           orkBrain[orkId].target.type = T_ENEMY;
  730.           orkBrain[orkId].target.id = enemies[i][j].id;
  731.           orkBrain[orkId].target.pos = enemies[i][j].pos;
  732.           return;
  733.         }
  734.       }
  735.     }
  736.   }
  737.  
  738.   bool isInTarget(const int& orkId){
  739.     return orkBrain[orkId].target.pos == unit(orkId).pos;
  740.   }
  741.  
  742.   void goStraightLineToTarget(const int& orkId){
  743.     //cerr << "Debug: Ork " << orkId << " at " << unit(orkId).pos << " is going in a straight line to the target, which is at " << targetPos(orkBrain[orkId].target) << endl; //debug
  744.     move(orkId,dominantDir( distance( unit(orkId).pos, targetPos(orkBrain[orkId].target))));
  745.   }
  746.  
  747.   /**
  748.    * Play method, invoked once per each round.
  749.    */
  750.   virtual void play () {
  751.     //cerr << "Player " << me() << " has " << orks(me()).size() <<" orks in round " << round() << endl;
  752.     //cerr << "Debug: Player " << me() << " orks: " << endl; //debug
  753.     //say(orks(me())); //debug
  754.  
  755.     if (round() == 0) {
  756.       cities.resize(nb_cities());
  757.       paths.resize(nb_paths());
  758.       getTerrainInfo();
  759.     }
  760.     updateVariables();
  761.     //cerr << "Debug: variables updated" << endl; //debug
  762.  
  763.     for (int i = 0; i < (int) orks(me()).size(); i++) { //for each of my orks
  764.       int orkId = orks(me())[i];
  765.  
  766.       //if(isInTarget(orkId)) cerr << "Debug: Ork " << orkId << " is in target " << orkBrain[orkId].target.pos << endl;
  767.  
  768.       if(orkBrain[orkId].target.type == T_NONE){ //if ork's first round
  769.         //cerr << "Debug: Ork " << orkId << " is lost in position " << unit(orkId).pos << endl; //debug
  770.         setTargetClosestSafeCell(orkId);
  771.       }
  772.  
  773.       if(isSafe(orkId)){
  774.         setTargetClosestEnemyWithLessHealthAndInASafeCell(orkId,5);
  775.       }else{
  776.         setTargetClosestEnemyWithLessHealth(orkId,2);
  777.       }
  778.  
  779.       if(orkBrain[orkId].target.type == T_ENEMY){
  780.         goStraightLineToTarget(orkId);
  781.       }
  782.  
  783.       if(targetIsACity(orkId) or targetIsAPath(orkId) or targetIsACell(orkId)){
  784.         if (isSafe(orkId)) {
  785.           decideCityOrPathToGo(orkId);
  786.           if (isInTarget(orkId)) {
  787.             improvePositionInCityOrPath(orkId);
  788.           }else{
  789.             advanceTowardsCityOrPathToGo(orkId);
  790.           }
  791.         }else{
  792.           //cerr << "Debug: Ork " << orkId << " is not safe" << endl;
  793.           goStraightLineToTarget(orkId);
  794.         }
  795.       }
  796.  
  797.  
  798.       //cerr << endl;
  799.     }
  800.   }
  801. };
  802.  
  803.  
  804. /**
  805.  * Do not modify the following line.
  806.  */
  807. RegisterPlayer(PLAYER_NAME);
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×