Engine.java
package org.microcol.ai;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.microcol.model.Location;
import org.microcol.model.Model;
import org.microcol.model.ModelAdapter;
import org.microcol.model.Path;
import org.microcol.model.Player;
import org.microcol.model.Ship;
import org.microcol.model.event.TurnStartedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Engine {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Model model;
private final Random random;
private final Map<Ship, Location> lastDirections;
public Engine(final Model model) {
this.model = model;
this.random = new Random();
this.lastDirections = new HashMap<>();
}
public void start() {
model.addListener(new ModelAdapter() {
@Override
public void turnStarted(TurnStartedEvent event) {
if (event.getPlayer().isComputer()) {
turn(event.getPlayer());
}
}
});
logger.info("AI engine started.");
}
void turn(final Player player) {
player.getShips().forEach(ship -> move(ship));
player.endTurn();
}
void move(final Ship ship) {
if (lastDirections.get(ship) == null) {
lastDirections.put(ship, Location.DIRECTIONS.get(random.nextInt(Location.DIRECTIONS.size())));
}
showDebug(ship);
final List<Location> directions = new ArrayList<>(Location.DIRECTIONS);
final List<Location> locations = new ArrayList<>();
Location lastLocation = ship.getLocation();
outerloop:
while (locations.size() < ship.getAvailableMoves()) {
for (final Location location : lastLocation.getNeighbors()) {
if (!ship.getOwner().getEnemyShipsAt(location).isEmpty()) {
break outerloop;
}
}
final Location lastDirection = lastDirections.get(ship);
final Location newLocation = lastLocation.add(lastDirection);
if (ship.isMoveable(newLocation)) {
locations.add(newLocation);
lastLocation = newLocation;
} else {
directions.remove(lastDirection);
if (directions.isEmpty()) {
break;
}
lastDirections.put(ship, directions.get(random.nextInt(directions.size())));
}
}
if (!locations.isEmpty()) {
ship.moveTo(Path.of(locations));
}
for (final Location location : ship.getLocation().getNeighbors()) {
final List<Ship> enemies = ship.getOwner().getEnemyShipsAt(location);
if (!enemies.isEmpty()) {
ship.attack(enemies.get(0));
break;
}
}
}
void showDebug(final Ship ship) {
final List<Location> locations = new ArrayList<>();
for (final Ship enemy : ship.getOwner().getEnemyShips()) {
locations.addAll(ship.getPath(enemy.getLocation(), true));
}
model.requestDebug(locations);
}
}