Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.*;
- import java.io.*;
- import java.math.*;
- /**
- * Auto-generated code below aims at helping you parse
- * the standard input according to the problem statement.
- **/
- class Player {
- public static Factory[] factory;
- public static int[][] distance;
- public static int factoryCount;
- public static Factory[] factoryByPriority;
- public static int balance;
- public static int rounds;
- public static void main(String args[]) {
- HashSet<Integer> troops = new HashSet();
- Scanner in = new Scanner(System.in);
- factoryCount = in.nextInt(); // the number of factories
- int linkCount = in.nextInt(); // the number of links between factories
- distance = new int[Player.factoryCount][Player.factoryCount]; // distance between two factories
- factory = new Factory[factoryCount]; // factories container
- for (int i = 0; i < linkCount; i++) {
- int factory1 = in.nextInt();
- int factory2 = in.nextInt();
- int distance = in.nextInt();
- Player.distance[factory1][factory2] = distance;
- Player.distance[factory2][factory1] = distance;
- }
- for (int i = 0; i < factoryCount; i++) {
- Player.distance[i][i] = 0;
- }
- // game loop
- rounds = 0;
- while (true) {
- long millis = System.currentTimeMillis();
- Player.balance = 0;
- int entityCount = in.nextInt(); // the number of entities (e.g. factories and troops)
- for (int i = 0; i < entityCount; i++) {
- int entityId = in.nextInt();
- String entityType = in.next();
- int arg1 = in.nextInt();
- int arg2 = in.nextInt();
- int arg3 = in.nextInt();
- int arg4 = in.nextInt();
- int arg5 = in.nextInt();
- if (entityType.equals("FACTORY")) {
- if (rounds == 0) { // on game start create factory objects
- factory[entityId] = new Factory(entityId, arg1, arg2, arg3);
- } else { // on all other rounds update factories
- factory[entityId].update(arg1, arg2, arg3);
- }
- } else if (entityType.equals("TROOP")) {
- if (arg1 == -1 && !troops.contains(entityId)) { // only add new enemy troops once on laucnh
- factory[arg3].addTroop(arg1, arg4, arg5);
- troops.add(entityId);
- }
- } else if (entityType.equals("BOMB")) {
- // TODO?
- }
- }
- if (rounds == 0) {
- factoryByPriority = factory.clone();
- for (Factory f : factory) {
- f.initNeighbors();
- }
- }
- updatePriorities();
- for (Factory f: factory) {
- f.debug();
- }
- String commands = "";
- for (int i = 0; i < factoryByPriority.length; i++) {
- commands += factoryByPriority[i].getCommands(i);
- }
- if (commands.equals(""))
- commands = "WAIT;";
- rounds++;
- millis = System.currentTimeMillis() - millis;
- commands += "MSG " + millis + "ms;";
- System.out.println(commands.substring(0,commands.length()-1));
- // To debug: System.err.println("Debug messages...");
- }
- }
- public static void updatePriorities() {
- for (Factory f : Player.factory) {
- double p = 0;
- for (Factory f2 : Player.factory) {
- if (f2.getOwner() == -1) {
- p += Player.distance[f.getId()][f2.getId()];
- //p += Math.pow(Player.distance[f.getId()][f2.getId()],0.5);
- }
- }
- f.setPriority(p);
- }
- Arrays.sort(factoryByPriority, new Comparator<Factory>() {
- @Override
- public int compare(Factory f1, Factory f2) {
- return new Double(f2.getPriority()).compareTo(new Double(f1.getPriority()));
- }
- });
- }
- }
- enum Role {
- PROVIDER, // factory produces for attack
- ATTACKER // attacker manages attacks
- }
- enum Mode {
- SEND, // always sends all produced units to nearest ally factory which is closer to the enemy
- ATTACK, // attack with units available (production and provided)
- DEFEND, // stop sending units to prevent factory takeover by incomming enemy units
- REQUEST, // stop sending units and request additional units to survive
- UPGRADE, // stop sending units to upgrade production as soon as possible
- SLOWUPGRADE, // provide 'production-1' to save one unit for later upgrade (only possible if production is 2 or 3)
- 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)
- }
- class Factory {
- private int id; // unique factory id
- private Role role; // current role (only updates if a factory changed owner)
- private Mode mode; // current mode (changes based on role and situation)
- private int sendToId; // factory id to provide with units each round
- private int doActionFor; // do task for 'doActionFor' rounds
- private Neighbors neighbors; // manages nearby factories data
- private double priority;
- // index ß is current round, index 1 is next round, index 2 is the round after, ect. to 21 because 20 is max distance
- private int[] incommingUnits;
- private int[] production;
- private int[] units;
- private int[] owner;
- // init new factory
- public Factory(int id, int owner, int units, int production) {
- this.id = id;
- this.incommingUnits = new int[21];
- this.production = new int[21];
- this.units = new int[21];
- this.owner = new int[21];
- this.mode = Mode.SEND;
- for (int i = 0; i < 21; i++) {
- //this.units[i] = units*owner + production*owner*i;
- this.incommingUnits[i] = 0;
- this.production[i] = production;
- this.owner[i] = owner;
- }
- update(owner, units, production);
- }
- // set and update factory values at round start
- public void update(int owner, int units, int production) {
- this.owner[0] = owner;
- this.units[0] = (owner == 0) ? -units : units*owner;
- Player.balance += this.units[0];
- this.production[0] = production;
- // update
- for (int i = 0; i < 20; i++) {
- incommingUnits[i] = incommingUnits[i+1];
- this.production[i] = this.production[i+1];
- //this.units[i] = this.units[i+1];
- }
- this.incommingUnits[20] = 0;
- this.production[20] = this.production[19];
- // detect bomb and set production to 0 for 5 rounds
- /*if (gotBombed()) {
- System.err.println("Factory " + id + " got bombed!");
- for (int i = 0; i < 6; i++) {
- this.production[i] = 0;
- }
- }*/
- // TODO simulate the whole game? dont set values, just check?
- calculateUnits();
- }
- // calculates and predicts factory values for the next 20 rounds
- private void calculateUnits() {
- for (int i = 1; i < 21; i++) {
- owner[i] = owner[i-1]; // factory may be taken over by a player in the previous round
- if (owner[i] == 0 && incommingUnits[i] < 0)
- units[i] = -1*units[i-1] + incommingUnits[i];
- else
- units[i] = units[i-1] + incommingUnits[i] + production[i]*owner[i]; // new units produced before battle
- if (incommingUnits[i] > 0 && units[i] > 0) // if battle is won, player (still) owns the factory
- owner[i] = 1;
- else if (incommingUnits[i] < 0 && units[i] < 0) // if battle is lost, enemy (still) owns the factory
- owner[i] = -1;
- }
- }
- // adds troop to keep track of future battles and their outcome
- public void addTroop(int owner, int units, int distance) {
- incommingUnits[distance] += units*owner;
- calculateUnits();
- }
- //checks if the factory got bombed
- private boolean gotBombed() {
- if (units[1] <= 10 && units[0] == 0)
- return true;
- else if (units[0] == Math.floor(units[1]/2))
- return true;
- else
- return false;
- }
- // inits Neighbors object (see class)
- public void initNeighbors() {
- this.neighbors = new Neighbors(this);
- }
- public void setPriority(double priority) {
- this.priority = priority;
- }
- public double getPriority() {
- return priority;
- }
- // returns the unique factory id
- public int getId() {
- return id;
- }
- // returns current production
- public int getProduction() {
- return production[0];
- }
- // returns current units
- public int getUnits() {
- return units[0];
- }
- // returns units in 'distance' rounds
- public int getUnits(int distance) {
- return Math.abs(units[distance]);
- }
- // returns current owner
- public int getOwner() {
- return owner[0];
- }
- // evaluates strategy and returns commands for actions to perform this round
- public String getCommands(int pos) {
- if (owner[0] != 1) // factory is not under player control; ignore
- return "";
- String commands = "";
- if (Player.rounds == 0) { // FIRST ROUND
- int count = (int) Math.floor((Player.factory.length-1)/2);
- ArrayList<Factory>[] nearbyFactories = neighbors.getNeighborsByDistance();
- for (int i = 0; i < Math.floor(nearbyFactories.length); i++) {
- for (Factory factory : nearbyFactories[i]) {
- if (count == 0 ||this.getUnits() == 0)
- break;
- if (factory.getOwner() == 0 && factory.getProduction() > 0 && factory.getUnits(i) < units[0]) {
- commands += sendTo(factory, factory.getUnits(0)+1, i+1);
- }
- count--;
- }
- }
- if (production[0] < 3 && units[0] >= 10) {
- commands += "INC " + id + ";";
- }
- return commands;
- }
- if (isUnderAttack()) {
- mode = isUnderCriticalAttack();
- } else if (mode == Mode.DEFEND) {
- mode = Mode.SEND;
- } else if (mode == Mode.REQUEST) {
- mode = Mode.SEND;
- }
- if (mode == Mode.SEND) {
- if (units[0] == 0)
- return "";
- if (Player.rounds > 10) {
- if (production[0] < 3 && units[0] >= 10) {
- units[0] -= 10;
- production[0] += 1;
- commands += "INC " + id + ";";
- }
- }
- Factory[] factoryByPriority = Player.factoryByPriority.clone();
- int index = pos+1;
- for (int i = 0; i < Player.factoryCount; i++) {
- if (index >= Player.factoryCount)
- index = 0;
- factoryByPriority[i] = Player.factoryByPriority[index++];
- }
- factoryByPriority[Player.factoryCount-1] = factoryByPriority[0];
- if (Player.balance < 100) {
- for (int i = 0; i < factoryByPriority.length; i++) {
- if (factoryByPriority[i].getProduction() > 0 && factoryByPriority[i].getProduction() < units[0]) {
- commands += sendTo(factoryByPriority[i], units[0], Player.distance[id][factoryByPriority[i].getId()]);
- return commands;
- }
- }
- }
- commands += sendTo(factoryByPriority[1], units[0], Player.distance[id][Player.factoryByPriority[0].getId()]);
- return commands;
- } else if (mode == Mode.UPGRADE) {
- if (units[0] >= 10) {
- mode = Mode.SEND;
- units[0] -= 10;
- production[0] += 1;
- commands += "INC " + id + ";";
- }
- } else if (mode == Mode.SLOWUPGRADE) {
- if (units[0] >= 10) {
- mode = Mode.SEND;
- units[0] -= 10;
- production[0] += 1;
- commands += "INC " + id + ";";
- }
- if (pos+1 != Player.factoryByPriority.length)
- commands += sendTo(Player.factoryByPriority[pos+1], production[0]-1, Player.distance[id][Player.factoryByPriority[pos+1].getId()]);
- } else if (mode == Mode.DEFEND) {
- // wait
- } else if (mode == Mode.REQUEST) {
- // TODO request other factory
- }
- return commands;
- }
- // if factory is about to be under attack
- private boolean isUnderAttack() {
- for (int i = 1; i < 21; i++) {
- if (incommingUnits[i] < 0)
- return true;
- }
- return false;
- }
- // if factory is about to be under attack and loses in the current mode TODOD: REQUESTUPGRADE and REQUEST
- private Mode isUnderCriticalAttack() {
- //Mode[] aMode;
- //if (role == Role.PROVIDER)
- Mode[] aMode = {Mode.SEND, Mode.SLOWUPGRADE, Mode.UPGRADE, Mode.DEFEND};
- //else
- // aMode = [Mode.ATTACK, Mode.DEFEND];
- for (Mode mode : aMode) {
- /* START */
- int[] u = new int[21];
- u[0] = units[0];
- int[] p = production.clone();
- for (int i = 1; i < 21; i++) {
- if ((mode == Mode.UPGRADE || mode == Mode.SLOWUPGRADE) && production[0] == 3) // already fully upgraded
- break;
- u[i] = u[i-1] + incommingUnits[i];
- if (mode == Mode.DEFEND) {
- u[i] += p[i];
- } else if (mode == Mode.UPGRADE) {
- u[i] += p[i];
- if (u[i] >= 10) {
- u[i] -= 10;
- for (int j = i+1; j<21; j++) {
- p[j] = p[i]+1;
- }
- mode = Mode.DEFEND; // TODO if upgraded and under attack set to defend ?!
- }
- } else if (mode == Mode.SEND || mode == Mode.ATTACK) {
- u[i] = p[i] + incommingUnits[i]; // new units produced, battle happens, then new units are produced
- } else if (mode == Mode.SLOWUPGRADE) {
- u[i] +=p[i]-1;
- if (u[i] >= 10) {
- u[i] -= 10;
- for (int j = i+1; j<21; j++) {
- p[j] = p[i]+1;
- }
- }
- }
- if (u[i] < 0) // factory loses attack in 'i' rounds
- break;
- else if (u[20] > 0) // if factory is NOT taken over in 'tMode' mode
- return mode;
- }
- }
- return Mode.REQUEST;
- }
- private String sendTo(Factory factory, int units, int distance) {
- if (units < 0) {
- System.err.println("NEGATIVE UNIT VALUE for " + "'MOVE " + id + " " + factory.getId() + " " + units + ";'");
- units = Math.abs(units); // no negative values
- }
- if (units > this.units[0]) // cant send more than available
- units = this.units[0];
- this.units[0] -= units;
- this.calculateUnits();
- factory.addTroop(1, units, distance);
- return "MOVE " + id + " " + factory.getId() + " " + units + ";";
- }
- public void debug() {
- //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] + ")");
- }
- }
- class Command {
- private Mode action;
- }
- class Neighbors {
- private Factory factory;
- private Factory[] neighbors;
- private double[] priorities;
- private ArrayList<Factory>[] nDistance;
- private ArrayList<Factory>[] nDistanceSimple;
- public Neighbors(Factory factory) {
- this.factory = factory;
- int thisFactoryId = this.factory.getId();
- neighbors = new Factory[Player.factoryCount-1];
- nDistance = new ArrayList[20];
- priorities = new double[Player.factoryCount];
- // get all other factories
- int id = 0;
- for (int i = 0; i < Player.factoryCount; i++) {
- if (i != thisFactoryId) {
- neighbors[id++] = Player.factory[i];
- }
- }
- // save neighbor factories by distance
- // init
- for (int i = 0; i < 20; i++) {
- nDistance[i] = new ArrayList<Factory>();
- }
- // save
- for (Factory f : neighbors) {
- nDistance[ Player.distance[thisFactoryId][f.getId()] ].add(f);
- }
- // init nDistanceSimple
- // determine amount of different distances
- int distancesAmount = 0;
- for (ArrayList<Factory> factories : nDistance) {
- if (factories.size() > 0)
- distancesAmount++;
- }
- // save factories
- nDistanceSimple = new ArrayList[distancesAmount];
- int index = 0;
- for (ArrayList<Factory> factories : nDistance) {
- if (factories.size() > 0) {
- nDistanceSimple[index++] = factories;
- }
- }
- //init priorities
- updatePriorities();
- }
- public ArrayList<Factory>[] getNeighborsByDistance() {
- return nDistance;
- }
- public ArrayList<Factory>[] getNeighborsByDistanceSimple() {
- return nDistanceSimple;
- }
- public void updatePriorities() {
- int thisFactoryId = factory.getId();
- for (int i = 0; i < Player.factoryCount; i++) {
- priorities[i] = Player.factory[i].getProduction()*10*Player.distance[thisFactoryId][i];
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement