package planetwars; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Objects; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; /********************************************** * ______ _ _______ _____ * |___ / | | | | ___ \_ _| * / / ___ _ _ ___ | | | | |_/ / | | * / / / _ \ | | / __| | |/\| | __/ | | * ./ /__| __/ |_| \__ \ \ /\ / | _| |_ * \_____/\___|\__,_|___/ \/ \/\_| \___/ * *********************************************/ /** * Klasse die het staat van het spel bijhoudt. * * Je doet dit door een instance aan te maken en bij elke keer als je input * krijgt van het spel dit door te geven aan de klasse met de functie update(). * * Deze functie zal de input verwerken zodat je alle data in variabelen hebt namelijk * - myPlanets * - neutralPlanets * - ... * - enemyExpeditions * * De data wordt opgeslagen als een bepaalde klasse. * Deze zijn allemaal record klassen wat wilt zeggen dat ze alleen maar dienen om * data in op te slaan. * Je kan de data ervan niet bewerken. * Meer informatie over hoe elke klasse zijn data bijhoudt kan je zien in * de file van die klasse. * * Je kan dan door middel van de functie addMove() zetten toevoegen. * Wanneer je al je zetten hebt toegevoegd en je ze effectief wilt spelen * kan je de functie Move() oproepen. * Daarna kan je geen extra moves meer spelen tot de volgende beurt waarbij je * de functie update() oproept. * * Tenslotte heb je nog de variabele currentTurn. * Die wordt momenteel voor niets gebruikt maar houd bij aan welke turn we zitten. * * * je kan in de file Example.java een voorbeeld implementatie vinden. */ public class PlanetWars { public List myPlanets; public List neutralPlanets; public List enemyPlanets; public List myExpeditions; public List enemyExpeditions; public int currentTurn; private List queuedMoves; private boolean moved; private DateTimeFormatter dateFormatter; public PlanetWars() { this.myPlanets = new ArrayList<>(); this.neutralPlanets = new ArrayList<>(); this.enemyPlanets = new ArrayList<>(); this.myExpeditions = new ArrayList<>(); this.enemyExpeditions = new ArrayList<>(); this.currentTurn = 0; this.queuedMoves = new ArrayList<>(); this.dateFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); } /** * Roep dit iedere beurt op met de input die je krijgt van het spel. * Gaat over de data en maakt er de juiste objecten van. * * @param input | De data die je krijgt van het spel. Zie Main.java hoe je dit het best krijgt * * @return | Geeft aan of opgegeven data klopt en of je iets kan doen. */ public boolean update(String input) { // Maak alle lijsten leeg. this.nextTurn(); // Vorm de input om tot een JsonObject. JsonObject state; try { state = new Gson().fromJson(input, JsonObject.class); } catch (JsonSyntaxException e) { this.log("Error: Converting input to json"); this.log(input); return false; } // Krijg een lijst van alle planeten. List planets = new ArrayList<>(); try { JsonArray planetsJson = state.getAsJsonArray("planets"); for (int i = 0; i < planetsJson.size(); i++) { planets.add(new Planet(planetsJson.get(i).getAsJsonObject())); } } catch (Exception e) { this.log("Error: Parsing planet input"); this.log(input); return false; } if (planets.isEmpty()) { this.log("Error: No planets"); this.log(input); return false; } // Voeg de planeten toe tot de juiste lijst. for (Planet planet : planets) { if (planet.owner() == null) { neutralPlanets.add(planet); } else if (planet.owner() == 1) { myPlanets.add(planet); } else { enemyPlanets.add(planet); } } // Doe hetzelfde met de expedities. try { JsonArray expeditionsJson = state.getAsJsonArray("expeditions"); for (int i = 0; i < expeditionsJson.size(); i++) { JsonObject expedition = expeditionsJson.get(i).getAsJsonObject(); // Zoek naar de planeet object vanwaar ze komen en naar toe gaan. String originString = expedition.get("origin").getAsString(); String destinationString = expedition.get("destination").getAsString(); Planet originPlanet = null; Planet destinationPlanet = null; for (Planet planet: planets) { if (planet.name().equals(originString)) { // Planeet van waar ze komen is gevonden originPlanet = planet; } if (planet.name().equals(destinationString)) { // Planeet waar ze naar toe gaan is ook gevonden destinationPlanet = planet; } } // Maak nieuwe expeditie aan en voeg het toe bij de juiste lijst Expedition exp = new Expedition(expedition, originPlanet, destinationPlanet); if (exp.owner() == 1) { myExpeditions.add(exp); } else { enemyExpeditions.add(exp); } } } catch (Exception e) { this.log("Error: Parsing expedition input"); this.log(input); return false; } this.moved = false; return true; } /** * Voeg een zet toe. * Je kan zoveel zetten toevoegen als je wilt en ze worden pas doorgegeven wanneer je move() aanroept. * * @param origin | De planeet van waar de schepen moeten komen. * @param destination | De planeet waar de schepen moeten toekomen. * @param ships | De hoeveelheid schepen die je wilt versturen * * @return | Geeft weer indien het een geldige zet is. Let op er worden maar een paar basis checks gedaan hiervoor */ public boolean addMove(Planet origin, Planet destination, int ships) { // Je kan maar 1 keer al je moves versturen per buurt. // Je kan daarin wel meerdere moves zetten. // Je kan dit doen door meerdere keren add_move op te roepen voor je move() oproept. if (this.moved) { return false; } // Je kan alleen schepen sturen die komen van je eigen planeet. if (origin.owner() != 1) { return false; } // Je kan geen schepen sturen naar dezelfde planeet als van waar ze komen. if (origin.equals(destination)) { return false; } // Je kan niet meer schepen versturen dan er zijn op de oorsprong planeet. int totalShips = ships; for (Move move: this.queuedMoves) { if (move.origin().equals(origin)) { totalShips += move.shipCount(); } } if (totalShips > origin.shipCount()) { return false; } this.queuedMoves.add(new Move(origin, destination, ships)); return true; } /** * Verwijder de moves die je al had toegevoegd. */ public void clearMoves() { this.queuedMoves.clear(); } /** * Voer alle zetten uit en ga naar de volgende beurt. */ public void move() { // Je kan maar 1 keer al je moves versturen per beurt. // Je kan daarin wel meerdere moves zetten. // Je kan dit doen door meerdere keren add_move op te roepen voor je move() oproept. if (this.moved) { return; } List movesJson = new ArrayList<>(); for (Move move : queuedMoves) { movesJson.add(move.toJson()); } JsonObject movesObj = new JsonObject(); movesObj.add("moves", new Gson().toJsonTree(movesJson)); this.moved = true; System.out.println(movesObj); } /** * Print een bericht met een tijdstip ervoor. * * @param message | Het bericht dat je wilt printen. */ public void log(String message) { LocalDateTime timestamp = LocalDateTime.now(); String formattedTimestamp = timestamp.format(this.dateFormatter); System.err.println("[" + formattedTimestamp + "] " + message); } /** * Maakt variabelen klaar voor de volgende beurt. */ private void nextTurn() { this.myPlanets.clear(); this.neutralPlanets.clear(); this.enemyPlanets.clear(); this.myExpeditions.clear(); this.enemyExpeditions.clear(); this.currentTurn += 1; this.queuedMoves.clear(); } } /** * Weet je niet hoe je nu verder moet? * * Kijk naar example.py hoe de klasse te implementeren. * * Nog enkele tips hoe je je bot beter kan maken: * * - Maak een nieuwe functie aan in de klasse PlanetWars `predict`. * Deze probeert te voorspellen hoeveel schepen van je tegenstander er op een bepaalde * planeet toekomen na x aantal beurten. * * - Maak een onderscheid tussen de gevallen waarbij jouw tegenstander geen extra schepen meer * verstuurd naar een bepaalde planeet en al zijn schepen ernaar heeft verstuurd. * Welke planeten kan je met de minste effort makkelijk pakken? * * - Indien je al meerdere planeten hebt probeer schepen van de achterliggende planeten naar * de frontline te sturen. * * - ... * * Wees creatief, de mogelijkheden zijn eindeloos :D */