Advertisement
UNOBTANIUM

GhostInTheCell Old Bot

Dec 27th, 2018
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.02 KB | None | 0 0
  1. import java.util.*;
  2. import java.io.*;
  3. import java.math.*;
  4.  
  5. /**
  6.  * Auto-generated code below aims at helping you parse
  7.  * the standard input according to the problem statement.
  8.  **/
  9. class Player {
  10.    
  11.     public static Factory[] factory;
  12.     public static int[][] distance;
  13.     public static int factoryCount;
  14.     public static Factory[] factoryByPriority;
  15.     public static int balance;
  16.     public static int rounds;
  17.    
  18.     public static void main(String args[]) {
  19.        
  20.         HashSet<Integer> troops = new HashSet();
  21.        
  22.         Scanner in = new Scanner(System.in);
  23.         factoryCount = in.nextInt(); // the number of factories
  24.         int linkCount = in.nextInt(); // the number of links between factories
  25.        
  26.         distance = new int[Player.factoryCount][Player.factoryCount]; // distance between two factories
  27.         factory = new Factory[factoryCount]; // factories container
  28.        
  29.         for (int i = 0; i < linkCount; i++) {
  30.             int factory1 = in.nextInt();
  31.             int factory2 = in.nextInt();
  32.             int distance = in.nextInt();
  33.             Player.distance[factory1][factory2] = distance;
  34.             Player.distance[factory2][factory1] = distance;
  35.         }
  36.        
  37.         for (int i = 0; i < factoryCount; i++) {
  38.             Player.distance[i][i] = 0;
  39.         }
  40.  
  41.         // game loop
  42.         rounds = 0;
  43.         while (true) {
  44.             long millis = System.currentTimeMillis();
  45.             Player.balance = 0;
  46.            
  47.             int entityCount = in.nextInt(); // the number of entities (e.g. factories and troops)
  48.             for (int i = 0; i < entityCount; i++) {
  49.                 int entityId = in.nextInt();
  50.                 String entityType = in.next();
  51.                 int arg1 = in.nextInt();
  52.                 int arg2 = in.nextInt();
  53.                 int arg3 = in.nextInt();
  54.                 int arg4 = in.nextInt();
  55.                 int arg5 = in.nextInt();
  56.                 if (entityType.equals("FACTORY")) {
  57.                     if (rounds == 0) { // on game start create factory objects
  58.                         factory[entityId] = new Factory(entityId, arg1, arg2, arg3);
  59.                     } else { // on all other rounds update factories
  60.                         factory[entityId].update(arg1, arg2, arg3);
  61.                     }
  62.                 } else if (entityType.equals("TROOP")) {
  63.                     if (arg1 == -1 && !troops.contains(entityId)) { // only add new enemy troops once on laucnh
  64.                         factory[arg3].addTroop(arg1, arg4, arg5);
  65.                         troops.add(entityId);
  66.                     }
  67.                 } else if (entityType.equals("BOMB")) {
  68.                     // TODO?
  69.                 }
  70.             }
  71.  
  72.             if (rounds == 0) {
  73.                 factoryByPriority = factory.clone();
  74.                 for (Factory f : factory) {
  75.                     f.initNeighbors();
  76.                 }
  77.             }
  78.            
  79.             updatePriorities();
  80.            
  81.             for (Factory f: factory) {
  82.                 f.debug();
  83.             }
  84.            
  85.             String commands = "";
  86.            
  87.             for (int i = 0; i < factoryByPriority.length; i++) {
  88.                 commands += factoryByPriority[i].getCommands(i);
  89.             }
  90.            
  91.             if (commands.equals(""))
  92.                 commands = "WAIT;";
  93.                
  94.             rounds++;
  95.             millis = System.currentTimeMillis() - millis;
  96.             commands += "MSG " + millis + "ms;";
  97.             System.out.println(commands.substring(0,commands.length()-1));
  98.  
  99.             // To debug: System.err.println("Debug messages...");
  100.         }
  101.     }
  102.    
  103.     public static void updatePriorities() {
  104.         for (Factory f : Player.factory) {
  105.             double p = 0;
  106.             for (Factory f2 : Player.factory) {
  107.                 if (f2.getOwner() == -1) {
  108.                     p += Player.distance[f.getId()][f2.getId()];
  109.                     //p += Math.pow(Player.distance[f.getId()][f2.getId()],0.5);
  110.                 }
  111.             }
  112.             f.setPriority(p);
  113.         }
  114.         Arrays.sort(factoryByPriority, new Comparator<Factory>() {
  115.             @Override
  116.             public int compare(Factory f1, Factory f2) {
  117.                 return new Double(f2.getPriority()).compareTo(new Double(f1.getPriority()));
  118.             }
  119.         });
  120.     }
  121. }
  122.  
  123. enum Role {
  124.     PROVIDER,   // factory produces for attack
  125.     ATTACKER    // attacker manages attacks
  126. }
  127.  
  128. enum Mode {
  129.     SEND,    // always sends all produced units to nearest ally factory which is closer to the enemy
  130.     ATTACK,     // attack with units available (production and provided)
  131.     DEFEND,     // stop sending units to prevent factory takeover by incomming enemy units
  132.     REQUEST,    // stop sending units and request additional units to survive
  133.     UPGRADE,    // stop sending units to upgrade production as soon as possible
  134.     SLOWUPGRADE, // provide 'production-1' to save one unit for later upgrade (only possible if production is 2 or 3)
  135.     REQUESTUPGRADE // stop production and ask other factory to provide units to upgrade as fast as possible (e.g. if strategy rrequires it or production is 0)
  136. }
  137.  
  138. class Factory {
  139.    
  140.     private int id;     // unique factory id
  141.    
  142.     private Role role;      // current role (only updates if a factory changed owner)
  143.     private Mode mode;      // current mode (changes based on role and situation)
  144.     private int sendToId;   // factory id to provide with units each round
  145.     private int doActionFor;  // do task for 'doActionFor' rounds
  146.    
  147.     private Neighbors neighbors; // manages nearby factories data
  148.     private double priority;
  149.    
  150.     // index ß is current round, index 1 is next round, index 2 is the round after, ect. to 21 because 20 is max distance
  151.     private int[] incommingUnits;
  152.     private int[] production;
  153.     private int[] units;
  154.     private int[] owner;
  155.  
  156.     // init new factory
  157.     public Factory(int id, int owner, int units, int production) {
  158.         this.id = id;
  159.         this.incommingUnits = new int[21];
  160.         this.production = new int[21];
  161.         this.units = new int[21];
  162.         this.owner = new int[21];
  163.         this.mode = Mode.SEND;
  164.         for (int i = 0; i < 21; i++) {
  165.             //this.units[i] = units*owner + production*owner*i;
  166.             this.incommingUnits[i] = 0;
  167.             this.production[i] = production;
  168.             this.owner[i] = owner;
  169.         }
  170.         update(owner, units, production);
  171.     }
  172.    
  173.     // set and update factory values at round start
  174.     public void update(int owner, int units, int production) {
  175.        
  176.         this.owner[0] = owner;
  177.         this.units[0] = (owner == 0) ? -units : units*owner;
  178.         Player.balance += this.units[0];
  179.         this.production[0] = production;
  180.        
  181.         // update
  182.         for (int i = 0; i < 20; i++) {
  183.             incommingUnits[i] = incommingUnits[i+1];
  184.             this.production[i] = this.production[i+1];
  185.             //this.units[i] = this.units[i+1];
  186.         }
  187.         this.incommingUnits[20] = 0;
  188.         this.production[20] = this.production[19];
  189.        
  190.         // detect bomb and set production to 0 for 5 rounds
  191.         /*if (gotBombed()) {
  192.             System.err.println("Factory " + id + " got bombed!");
  193.             for (int i = 0; i < 6; i++) {
  194.                 this.production[i] = 0;
  195.             }
  196.         }*/
  197.                                             // TODO simulate the whole game? dont set values, just check?
  198.                                            
  199.         calculateUnits();
  200.     }
  201.    
  202.     // calculates and predicts factory values for the next 20 rounds
  203.     private void calculateUnits() {
  204.         for (int i = 1; i < 21; i++) {
  205.             owner[i] = owner[i-1]; // factory may be taken over by a player in the previous round
  206.             if (owner[i] == 0 && incommingUnits[i] < 0)
  207.                 units[i] = -1*units[i-1] + incommingUnits[i];
  208.             else
  209.                 units[i] = units[i-1] + incommingUnits[i] + production[i]*owner[i]; // new units produced before battle
  210.             if (incommingUnits[i] > 0 && units[i] > 0) // if battle is won, player (still) owns the factory
  211.                 owner[i] = 1;
  212.             else if (incommingUnits[i] < 0 && units[i] < 0) // if battle is lost, enemy (still) owns the factory
  213.                 owner[i] = -1;
  214.         }
  215.     }
  216.    
  217.     // adds troop to keep track of future battles and their outcome
  218.     public void addTroop(int owner, int units, int distance) {
  219.         incommingUnits[distance] += units*owner;
  220.         calculateUnits();
  221.     }
  222.    
  223.     //checks if the factory got bombed
  224.     private boolean gotBombed() {
  225.         if (units[1] <= 10 && units[0] == 0)
  226.             return true;
  227.         else if (units[0] == Math.floor(units[1]/2))
  228.             return true;
  229.         else
  230.             return false;
  231.     }
  232.    
  233.     // inits Neighbors object (see class)
  234.     public void initNeighbors() {
  235.         this.neighbors = new Neighbors(this);
  236.     }
  237.  
  238.     public void setPriority(double priority) {
  239.         this.priority = priority;
  240.     }
  241.    
  242.     public double getPriority() {
  243.         return priority;
  244.     }
  245.    
  246.     // returns the unique factory id
  247.     public int getId() {
  248.         return id;
  249.     }
  250.    
  251.     // returns current production
  252.     public int getProduction() {
  253.         return production[0];
  254.     }
  255.    
  256.     // returns current units
  257.     public int getUnits() {
  258.         return units[0];
  259.     }
  260.    
  261.     // returns units in 'distance' rounds
  262.     public int getUnits(int distance) {
  263.         return Math.abs(units[distance]);
  264.     }
  265.    
  266.     // returns current owner
  267.     public int getOwner() {
  268.         return owner[0];
  269.     }
  270.  
  271.     // evaluates strategy and returns commands for actions to perform this round
  272.     public String getCommands(int pos) {
  273.         if (owner[0] != 1) // factory is not under player control; ignore
  274.             return "";
  275.        
  276.         String commands = "";
  277.        
  278.         if (Player.rounds == 0) { // FIRST ROUND
  279.             int count = (int) Math.floor((Player.factory.length-1)/2);
  280.             ArrayList<Factory>[] nearbyFactories = neighbors.getNeighborsByDistance();
  281.             for (int i = 0; i < Math.floor(nearbyFactories.length); i++) {
  282.                 for (Factory factory : nearbyFactories[i]) {
  283.                     if (count == 0 ||this.getUnits() == 0)
  284.                         break;
  285.                     if (factory.getOwner() == 0 && factory.getProduction() > 0 && factory.getUnits(i) < units[0]) {
  286.                         commands += sendTo(factory, factory.getUnits(0)+1, i+1);
  287.                     }
  288.                     count--;
  289.                 }
  290.             }
  291.             if (production[0] < 3 && units[0] >= 10) {
  292.                 commands += "INC " + id + ";";
  293.             }
  294.             return commands;
  295.         }
  296.        
  297.         if (isUnderAttack()) {
  298.             mode = isUnderCriticalAttack();
  299.         } else if (mode == Mode.DEFEND) {
  300.             mode = Mode.SEND;
  301.         } else if (mode == Mode.REQUEST) {
  302.             mode = Mode.SEND;
  303.         }
  304.        
  305.        
  306.         if (mode == Mode.SEND) {
  307.            
  308.             if (units[0] == 0)
  309.                 return "";
  310.            
  311.             if (Player.rounds > 10) {
  312.                 if (production[0] < 3 && units[0] >= 10) {
  313.                     units[0] -= 10;
  314.                     production[0] += 1;
  315.                     commands += "INC " + id + ";";
  316.                 }
  317.             }
  318.            
  319.             Factory[] factoryByPriority = Player.factoryByPriority.clone();
  320.             int index = pos+1;
  321.             for (int i = 0; i < Player.factoryCount; i++) {
  322.                 if (index >= Player.factoryCount)
  323.                     index = 0;
  324.                 factoryByPriority[i] = Player.factoryByPriority[index++];
  325.             }
  326.             factoryByPriority[Player.factoryCount-1] = factoryByPriority[0];
  327.            
  328.             if (Player.balance < 100) {
  329.                 for (int i = 0; i < factoryByPriority.length; i++) {
  330.                     if (factoryByPriority[i].getProduction() > 0 && factoryByPriority[i].getProduction() < units[0]) {
  331.                         commands += sendTo(factoryByPriority[i], units[0], Player.distance[id][factoryByPriority[i].getId()]);
  332.                         return commands;
  333.                     }
  334.                 }
  335.             }
  336.             commands += sendTo(factoryByPriority[1], units[0], Player.distance[id][Player.factoryByPriority[0].getId()]);
  337.             return commands;
  338.            
  339.         } else if (mode == Mode.UPGRADE) {
  340.            
  341.             if (units[0] >= 10) {
  342.                 mode = Mode.SEND;
  343.                 units[0] -= 10;
  344.                 production[0] += 1;
  345.                 commands += "INC " + id + ";";
  346.             }
  347.            
  348.         } else if (mode == Mode.SLOWUPGRADE) {
  349.            
  350.             if (units[0] >= 10) {
  351.                 mode = Mode.SEND;
  352.                 units[0] -= 10;
  353.                 production[0] += 1;
  354.                 commands += "INC " + id + ";";
  355.             }
  356.             if (pos+1 != Player.factoryByPriority.length)
  357.                 commands += sendTo(Player.factoryByPriority[pos+1], production[0]-1, Player.distance[id][Player.factoryByPriority[pos+1].getId()]);
  358.            
  359.            
  360.         } else if (mode == Mode.DEFEND) {
  361.            
  362.             // wait
  363.            
  364.         } else if (mode == Mode.REQUEST) {
  365.            
  366.             // TODO request other factory
  367.            
  368.         }
  369.        
  370.        
  371.        
  372.         return commands;
  373.        
  374.     }
  375.    
  376.     // if factory is about to be under attack
  377.     private boolean isUnderAttack() {
  378.         for (int i = 1; i < 21; i++) {
  379.             if (incommingUnits[i] < 0)
  380.                 return true;
  381.         }
  382.         return false;
  383.     }
  384.    
  385.     // if factory is about to be under attack and loses in the current mode TODOD: REQUESTUPGRADE and REQUEST
  386.     private Mode isUnderCriticalAttack() {
  387.         //Mode[] aMode;
  388.         //if (role == Role.PROVIDER)
  389.             Mode[] aMode = {Mode.SEND, Mode.SLOWUPGRADE, Mode.UPGRADE, Mode.DEFEND};
  390.         //else
  391.         //    aMode = [Mode.ATTACK, Mode.DEFEND];
  392.         for (Mode mode : aMode) {
  393.             /* START */
  394.             int[] u = new int[21];
  395.             u[0] = units[0];
  396.             int[] p = production.clone();
  397.             for (int i = 1; i < 21; i++) {
  398.                 if ((mode == Mode.UPGRADE || mode == Mode.SLOWUPGRADE) && production[0] == 3) // already fully upgraded
  399.                     break;
  400.                 u[i] = u[i-1] + incommingUnits[i];
  401.                 if (mode == Mode.DEFEND) {
  402.                     u[i] += p[i];
  403.                 } else if (mode == Mode.UPGRADE) {
  404.                     u[i] += p[i];
  405.                     if (u[i] >= 10) {
  406.                         u[i] -= 10;
  407.                         for (int j = i+1; j<21; j++) {
  408.                             p[j] = p[i]+1;
  409.                         }
  410.                         mode = Mode.DEFEND; // TODO if upgraded and under attack set to defend ?!
  411.                     }
  412.                 } else if (mode == Mode.SEND || mode == Mode.ATTACK) {
  413.                     u[i] = p[i] + incommingUnits[i]; // new units produced, battle happens, then new units are produced
  414.                 } else if (mode == Mode.SLOWUPGRADE) {
  415.                     u[i] +=p[i]-1;
  416.                     if (u[i] >= 10) {
  417.                         u[i] -= 10;
  418.                         for (int j = i+1; j<21; j++) {
  419.                             p[j] = p[i]+1;
  420.                         }
  421.                     }
  422.                 }
  423.                
  424.                 if (u[i] < 0) // factory loses attack in 'i' rounds
  425.                     break;
  426.                 else if (u[20] > 0) // if factory is NOT taken over in 'tMode' mode
  427.                     return mode;
  428.             }
  429.         }
  430.         return Mode.REQUEST;
  431.     }
  432.    
  433.     private String sendTo(Factory factory, int units, int distance) {
  434.         if (units < 0) {
  435.             System.err.println("NEGATIVE UNIT VALUE for " + "'MOVE " + id + " " + factory.getId() + " " + units + ";'");
  436.             units = Math.abs(units); // no negative values
  437.         }
  438.         if (units > this.units[0]) // cant send more than available
  439.             units = this.units[0];
  440.         this.units[0] -= units;
  441.         this.calculateUnits();
  442.         factory.addTroop(1, units, distance);
  443.         return "MOVE " + id + " " + factory.getId() + " " + units + ";";
  444.     }
  445.    
  446.     public void debug() {
  447.         //System.err.println("ID: " + id + " Mode: " + mode + " Owner: " + owner[0] + " Production: " + production[0] + " Units: " + units[0] + "(" + incommingUnits[0] + ")||" + units[1] + "(" + incommingUnits[1] + ")||" + units[2] + "(" + incommingUnits[2] + ")||" + units[3] + "(" + incommingUnits[3] + ")||" + units[4] + "(" + incommingUnits[4] + ")");
  448.     }
  449. }
  450.  
  451.  
  452. class Command {
  453.    
  454.     private Mode action;
  455.    
  456. }
  457.  
  458. class Neighbors {
  459.    
  460.     private Factory factory;
  461.     private Factory[] neighbors;
  462.     private double[] priorities;
  463.     private ArrayList<Factory>[] nDistance;
  464.     private ArrayList<Factory>[] nDistanceSimple;
  465.    
  466.    
  467.     public Neighbors(Factory factory) {
  468.         this.factory = factory;
  469.         int thisFactoryId = this.factory.getId();
  470.         neighbors = new Factory[Player.factoryCount-1];
  471.         nDistance = new ArrayList[20];
  472.         priorities = new double[Player.factoryCount];
  473.        
  474.         // get all other factories
  475.         int id = 0;
  476.         for (int i = 0; i < Player.factoryCount; i++) {
  477.             if (i != thisFactoryId) {
  478.                 neighbors[id++] = Player.factory[i];
  479.             }
  480.         }
  481.        
  482.         // save neighbor factories by distance
  483.         // init
  484.         for (int i = 0; i < 20; i++) {
  485.             nDistance[i] = new ArrayList<Factory>();
  486.         }
  487.         // save
  488.         for (Factory f : neighbors) {
  489.             nDistance[ Player.distance[thisFactoryId][f.getId()] ].add(f);
  490.         }
  491.        
  492.         // init nDistanceSimple
  493.         // determine amount of different distances
  494.         int distancesAmount = 0;
  495.         for (ArrayList<Factory> factories : nDistance) {
  496.             if (factories.size() > 0)
  497.                 distancesAmount++;
  498.         }
  499.         // save factories
  500.         nDistanceSimple = new ArrayList[distancesAmount];
  501.         int index = 0;
  502.         for (ArrayList<Factory> factories : nDistance) {
  503.             if (factories.size() > 0) {
  504.                 nDistanceSimple[index++] = factories;
  505.             }
  506.         }
  507.        
  508.         //init priorities
  509.         updatePriorities();
  510.     }
  511.    
  512.     public ArrayList<Factory>[] getNeighborsByDistance() {
  513.         return nDistance;
  514.     }
  515.    
  516.     public ArrayList<Factory>[] getNeighborsByDistanceSimple() {
  517.         return nDistanceSimple;
  518.     }
  519.    
  520.     public void updatePriorities() {
  521.         int thisFactoryId = factory.getId();
  522.         for (int i = 0; i < Player.factoryCount; i++) {
  523.             priorities[i] = Player.factory[i].getProduction()*10*Player.distance[thisFactoryId][i];
  524.         }
  525.     }
  526. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement