Advertisement
MauriJefe

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

Jan 9th, 2018
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.73 KB | None | 0 0
  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);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement