quantum.game.Bot.java Source code

Java tutorial

Introduction

Here is the source code for quantum.game.Bot.java

Source

//
// Copyright (c) 2009 Mario Zechner.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the GNU Lesser Public License v2.1
// which accompanies this distribution, and is available at
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
// 
// Contributors:
//     Mario Zechner - initial API and implementation
//

package quantum.game;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;

//import bsh.EvalError;
//import bsh.Interpreter;
import quantum.net.Client;
import quantum.net.messages.Message;
import quantum.net.messages.PlayerMessage;

public class Bot {
    //   Interpreter interpreter = new Interpreter();
    int id = 0;
    Simulation sim;
    List<Integer> planets = new ArrayList<Integer>();
    HashMap<Integer, Integer> planets_lookup = new HashMap<Integer, Integer>();

    int[] friendly;
    int[] enemy;
    int[] moveable;
    int total_creatures = 0;

    int last_taken_turn = 0;
    boolean wait = false;
    Player player;

    public Bot(String file, int id) {
        //      interpreter.source(file);
        //      interpreter.set("simulation", this);
        this.id = id;
    }

    public Bot(String file, String name, Client client) throws Exception {
        //      interpreter.source(file);
        PlayerMessage msg = new PlayerMessage(name);
        client.sendMessage(msg);
        msg = null;
        while (msg == null) {
            Message m = client.readMessage();
            if (m != null && m instanceof PlayerMessage)
                msg = (PlayerMessage) m;
        }

        player = new Player(msg.getName(), msg.getId());

        this.id = msg.getId();

        //      interpreter.set("simulation", this);
    }

    public void dispose(Client client) {
        PlayerMessage msg = new PlayerMessage(player.getName(), player.getId(), true);
        try {
            client.sendMessage(msg);
        } catch (Exception e) {
            Gdx.app.log("[Bot]", "couldn't send PlayerMessage: ", e);
            e.printStackTrace();
        }
    }

    public void update(Simulation sim) {
        if (sim.getTurn() == last_taken_turn)
            return;

        if (sim.getTurn() == sim.getNextCommandTurn()) {
            if (wait) {
                wait = !wait;
                last_taken_turn = sim.getTurn();
                return;
            } else {
                last_taken_turn = sim.getTurn();
                wait = !wait;

                if (this.sim == null) {
                    this.sim = sim;
                    planets.clear();
                    for (Planet planet : sim.getPlanets()) {
                        planets_lookup.put(planet.id, planets.size());
                        planets.add(planet.id);
                    }

                    this.enemy = new int[planets.size()];
                    this.friendly = new int[planets.size()];
                    this.moveable = new int[planets.size()];
                }

                gatherStatistics();

                defaultBotUpdate();
                //            try {
                //               interpreter.eval("update();");
                //            } catch (EvalError e) {
                //               Gdx.app.log("[Bot]", "error calling update method of bot: " + e.getErrorSourceFile() + ":" + e.getErrorLineNumber()
                //                  + " - " + e.getErrorText());
                //            }
            }
        }
    }

    public void defaultBotUpdate() {

        Bot simulation = this;
        List<Integer> planets2 = simulation.getPlanets();
        Iterator<Integer> iterator = planets2.iterator();
        while (iterator.hasNext()) {
            Integer planet = iterator.next();
            if (simulation.isOwnedPlanet(planet) == false)
                continue;

            if (simulation.isOwnedPlanet(planet) && simulation.numberOfTrees(planet) < 2
                    && simulation.numberOfFriendlyCreatures(planet) >= 10
                    && simulation.numberOfEnemyCreatures(planet) == 0) {
                simulation.plantTree(planet);
                continue;
            }

            if (simulation.numberAvailableResources(planet) == 0 || simulation.creatureLimitReached()
                    || simulation.numberOfFriendlyCreatures(planet) > 200) {
                simulation.moveCreatures(planet, simulation.getNearestNeighbourToEnemy(planet),
                        simulation.numberOfFriendlyCreatures(planet));
                continue;
            }

            if (simulation.numberOfFriendlyCreatures(planet) != 0) {
                Set<Integer> planetNeighbours = simulation.getPlanetNeighbours(planet);
                Iterator<Integer> iterator2 = planetNeighbours.iterator();
                while (iterator2.hasNext()) {
                    Integer neighbour = iterator2.next();
                    if ((simulation.isEnemyPlanet(neighbour) && simulation
                            .numberOfEnemyCreatures(neighbour) < simulation.numberOfFriendlyCreatures(planet))
                            || (simulation.isOwnedPlanet(neighbour)
                                    && simulation.numberOfEnemyCreatures(neighbour) > 0
                                    && simulation.numberOfEnemyCreatures(neighbour) < simulation
                                            .numberOfFriendlyCreatures(planet))) {
                        simulation.moveCreatures(planet, neighbour, simulation.numberOfFriendlyCreatures(planet));
                        break;
                    }

                    if (simulation.isFreePlanet(neighbour) && simulation.numberOfMoveableCreatures(planet) >= 25
                            && !simulation.hasCreatureMovingTo(planet, neighbour)) {
                        int numberOfCreatures = simulation.numberOfCreatures(planet);
                        simulation.moveCreatures(planet, neighbour, (int) (numberOfCreatures * 0.25f));
                        break;
                    }

                    if (simulation.isOwnedPlanet(neighbour) && simulation.numberOfTrees(neighbour) == 0
                            && simulation.numberOfFriendlyCreatures(neighbour) < 10
                            && simulation.numberOfFriendlyCreatures(neighbour)
                                    + simulation.numberOfMoveableCreatures(planet) > 10) {
                        simulation.moveCreatures(planet, neighbour,
                                10 - simulation.numberOfFriendlyCreatures(neighbour));
                        break;
                    }
                }
            }
        }
    }

    private void gatherStatistics() {
        for (int i = 0; i < planets.size(); i++) {
            enemy[i] = 0;
            friendly[i] = 0;
            moveable[i] = 0;
        }

        total_creatures = 0;

        for (int planet : planets) {
            Planet p = sim.getPlanet(planet);

            int idx = planets_lookup.get(planet);
            for (Creature creature : p.getCreatures()) {
                if (creature.getOwner() != this.id)
                    enemy[idx]++;
                else {
                    friendly[idx]++;
                    total_creatures++;
                    if (creature.isBorn() && !creature.isDying()
                            && (creature.isOrbiting() || creature.isAttacking()))
                        moveable[idx]++;
                }
            }
        }

        gatherConnectedPlanets(sim);

    }

    HashSet<Planet> visited = new HashSet<Planet>();
    List<Planet> unvisited = new ArrayList<Planet>();
    HashSet<Vector2> components = new HashSet<Vector2>();
    int component_size = 0;

    private void gatherConnectedPlanets(Simulation sim) {
        visited.clear();
        unvisited.clear();
        components.clear();

        for (Planet planet : sim.getPlanets()) {
            if (planet.getOwner() != -1 && planet.getOwner() != this.id) {
                unvisited.add(planet);
            }
        }

        while (unvisited.size() != 0) {
            component_size = 0;
            Planet planet = unvisited.remove(0);
            Vector2 center = new Vector2();
            components.add(center);
            int num_planets = gatherConnectedPlanetsRecursive(sim, planet, center);
            center.scl(1.0f / num_planets);
        }
    }

    private int gatherConnectedPlanetsRecursive(Simulation sim, Planet planet, Vector2 center) {
        center.add(planet.getPosition());
        visited.add(planet);
        unvisited.remove(planet);
        int num_planets = 1;
        component_size++;
        if (component_size > 3)
            return num_planets;

        for (int neighbour : planet.getReachablePlanets()) {
            Planet neighbour_planet = sim.getPlanet(neighbour);
            if (neighbour_planet.getOwner() == planet.getOwner() && visited.contains(neighbour_planet) == false)
                num_planets += gatherConnectedPlanetsRecursive(sim, neighbour_planet, center);
        }

        return num_planets;
    }

    public boolean isOwnedPlanet(int id) {
        Planet planet = sim.getPlanet(id);
        int owner = planet.getOwner();
        return owner == this.id;
    }

    public boolean isEnemyPlanet(int id) {
        return sim.getPlanet(id).getOwner() != this.id && sim.getPlanet(id).getOwner() != -1;
    }

    public boolean isFreePlanet(int id) {
        return sim.getPlanet(id).getOwner() == -1;
    }

    public boolean hasCreatureMovingTo(int id, int id2) {
        for (Creature creature : sim.getPlanet(id).getCreatures()) {
            if (creature.getOwner() == this.id && creature.isMoving() && creature.getTarget() == id2)
                return true;
        }

        return false;
    }

    public int numberOfTrees(int id) {
        return sim.getPlanet(id).getTrees().size();
    }

    public int numberOfCreatures(int id) {
        return sim.getPlanet(id).getCreatures().size();
    }

    public int numberOfFriendlyCreatures(int id) {
        return friendly[planets_lookup.get(id)];
    }

    public int numberOfMoveableCreatures(int id) {
        return moveable[planets_lookup.get(id)];
    }

    public int numberOfEnemyCreatures(int id) {
        return enemy[planets_lookup.get(id)];
    }

    public int numberAvailableResources(int id) {
        return sim.getPlanet(id).getResources();
    }

    public int numberMaximumResources(int id) {
        return sim.getPlanet(id).getResources();
    }

    public void plantTree(int id) {
        sim.plantTree(this.id, id);
    }

    public void moveCreatures(Integer from_id, Integer to_id, Integer units) {
        sim.moveCreatures(this.id, from_id, to_id, units);
    }

    @SuppressWarnings("unchecked")
    public List getPlanets() {
        return planets;
    }

    Vector2 tmp = new Vector2();

    public int getNearestNeighbourToEnemy(int id) {
        float min_dist = Float.MAX_VALUE;
        int planet = -1;

        for (Vector2 center : components) {
            tmp.set(center);

            for (int n : sim.getPlanet(id).getReachablePlanets()) {
                float dst = tmp.dst2(sim.getPlanet(n).getPosition());

                if (min_dist > dst) {
                    min_dist = dst;
                    planet = n;
                }
            }
        }

        if (planet == -1)
            return sim.getPlanet(id).getReachablePlanets().iterator().next();
        else
            return planet;
    }

    public boolean creatureLimitReached() {
        return total_creatures >= Constants.MAX_CREATURES;
    }

    @SuppressWarnings("unchecked")
    public Set getPlanetNeighbours(int id) {
        return sim.getPlanet(id).getReachablePlanets();
    }

    public float getHealth(int id) {
        return sim.getPlanet(id).getHealth();
    }

    public float getStrength(int id) {
        return sim.getPlanet(id).getStrength();
    }

    public float getSpeed(int id) {
        return sim.getPlanet(id).getSpeed();
    }

    public int getNearestEnemyPlanet(int id) {
        Planet src = sim.getPlanet(id);
        Planet dst = null;
        float min_dist = Float.MAX_VALUE;

        for (Planet planet : sim.getPlanets()) {
            if (planet.getOwner() == this.id)
                continue;
            if (planet.getOwner() == -1)
                continue;

            float dist = planet.getPosition().dst2(src.getPosition());
            if (dist < min_dist) {
                min_dist = dist;
                dst = planet;
            }
        }

        if (dst == null)
            return id;
        else
            return dst.getId();
    }

    HashSet<Planet> open_list = new HashSet<Planet>();
    HashSet<Planet> closed_list = new HashSet<Planet>();
    HashMap<Planet, Planet> parent = new HashMap<Planet, Planet>();
    HashMap<Planet, Float> g_cost = new HashMap<Planet, Float>();
    HashMap<Planet, Float> f_cost = new HashMap<Planet, Float>();

    public int findPath(int from, int to) {
        if (from == to)
            return from;

        Planet start = sim.getPlanet(from);
        Planet end = sim.getPlanet(to);

        open_list.clear();
        closed_list.clear();
        parent.clear();
        g_cost.clear();
        f_cost.clear();

        open_list.add(start);
        f_cost.put(start, start.getPosition().dst2(end.getPosition()));
        g_cost.put(start, 0.0f);

        boolean found_end = false;

        while (open_list.size() > 0) {
            Planet p = getLowestFScorePlanet(end);
            open_list.remove(p);
            closed_list.add(p);
            if (p == end) {
                found_end = true;
                break;
            }

            for (int neighbour : p.getReachablePlanets()) {
                Planet n = sim.getPlanet(neighbour);
                if (closed_list.contains(n))
                    continue;

                if (open_list.contains(n) == false) {
                    open_list.add(n);
                    float g = g_cost.get(p) + n.getPosition().dst2(n.getPosition());
                    g_cost.put(n, g);
                    f_cost.put(n, n.getPosition().dst2(end.getPosition()) + g);
                    parent.put(n, p);
                } else {
                    float g = g_cost.get(p) + n.getPosition().dst2(n.getPosition());
                    if (g < g_cost.get(n)) {
                        g_cost.put(n, g);
                        f_cost.put(n, n.getPosition().dst2(end.getPosition()) + g);
                        parent.put(n, p);
                    }
                }
            }
        }

        if (found_end == false)
            return from;

        Planet cur = end;
        while (true) {
            Planet p = parent.get(cur);
            if (p == start)
                return cur.getId();

            cur = p;
        }
    }

    public int findSafePath(int from, int to) {
        if (from == to)
            return from;

        Planet start = sim.getPlanet(from);
        Planet end = sim.getPlanet(to);

        open_list.clear();
        closed_list.clear();
        parent.clear();
        g_cost.clear();
        f_cost.clear();

        open_list.add(start);
        f_cost.put(start, start.getPosition().dst2(end.getPosition()));
        g_cost.put(start, 0.0f);

        boolean found_end = false;

        while (open_list.size() > 0) {
            Planet p = getLowestFScorePlanet(end);
            open_list.remove(p);
            closed_list.add(p);
            if (p == end) {
                found_end = true;
                break;
            }

            for (int neighbour : p.getReachablePlanets()) {
                Planet n = sim.getPlanet(neighbour);
                if (closed_list.contains(n) || (n.getOwner() != -1 && n.getOwner() != this.id && n != end))
                    continue;

                if (open_list.contains(n) == false) {
                    open_list.add(n);
                    float g = g_cost.get(p) + n.getPosition().dst2(n.getPosition());
                    g_cost.put(n, g);
                    f_cost.put(n, n.getPosition().dst2(end.getPosition()) + g);
                    parent.put(n, p);
                } else {
                    float g = g_cost.get(p) + n.getPosition().dst2(n.getPosition());
                    if (g < g_cost.get(n)) {
                        g_cost.put(n, g);
                        f_cost.put(n, n.getPosition().dst2(end.getPosition()) + g);
                        parent.put(n, p);
                    }
                }
            }
        }

        if (found_end == false)
            return from;

        Planet cur = end;
        while (true) {
            Planet p = parent.get(cur);
            if (p == start)
                return cur.getId();

            cur = p;
        }
    }

    private Planet getLowestFScorePlanet(Planet end) {
        Planet lowest = null;
        float score = Float.MAX_VALUE;

        for (Planet planet : open_list) {
            float f = f_cost.get(planet);
            if (score > f_cost.get(planet)) {
                lowest = planet;
                score = f;
            }
        }

        return lowest;
    }

    public int getId() {
        return id;
    }
}