package com.cardshifter.server.commands; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import net.zomis.aiscores.FieldScore; import net.zomis.aiscores.FieldScores; import net.zomis.aiscores.Scorer; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.cardshifter.ai.FakeAIClientTCG; import com.cardshifter.ai.IdleAI; import com.cardshifter.ai.ScoringAI; import com.cardshifter.api.ClientIO; import com.cardshifter.modapi.actions.ECSAction; import com.cardshifter.modapi.ai.AIComponent; import com.cardshifter.modapi.ai.AISystem; import com.cardshifter.modapi.base.ECSGame; import com.cardshifter.modapi.base.Entity; import com.cardshifter.modapi.base.PlayerComponent; import com.cardshifter.server.commands.AICommand.AICommandParameters; import com.cardshifter.server.model.CommandHandler.CommandHandle; public class AICommand implements CommandHandle<AICommandParameters> { @Parameters(commandNames = "ai", commandDescription = "Control AIs within a game") public static class AICommandParameters { @Parameter(names = "-g", description = "Gameid", required = true) private int gameId; @Parameter(names = "-e", description = "Entity ID") private int entity; @Parameter(names = "-delay", description = "Change the delay") private int delay; @Parameter(names = "-ai", description = "Change the AI") private String aiName; @Parameter(names = "-call", description = "Call the AI") private boolean call; @Parameter(names = "-pause", description = "Pause all AIs in the game") private boolean pause; @Parameter(names = "-continue", description = "Unpause all AIs in the game") private boolean cont; @Parameter(names = "-score", description = "Score (Useful for AI debugging)") private boolean score; } @Override public void handle(CommandContext command, AICommandParameters parameters) { ECSGame game = command.getServer().getGames().get(parameters.gameId).getGameModel(); Set<Entity> players = game.getEntitiesWithComponent(PlayerComponent.class); Set<Entity> ais = game.getEntitiesWithComponent(AIComponent.class); players.stream().forEach(e -> command.sendChatResponse("Player " + e + ": " + e.getComponent(AIComponent.class))); ais.stream().forEach(e -> command.sendChatResponse("AI " + e + ": " + e.getComponent(AIComponent.class))); Entity entity = game.getEntity(parameters.entity); if (parameters.call) { command.sendChatResponse("Calling AIs in game..."); AISystem.call(game); return; } if (parameters.pause) { command.sendChatResponse("AIs paused"); ais.forEach(e -> e.getComponent(AIComponent.class).setPaused(true)); return; } if (parameters.cont) { command.sendChatResponse("AIs unpaused"); ais.forEach(e -> e.getComponent(AIComponent.class).setPaused(false)); return; } if (entity == null) { command.sendChatResponse("No entity specified"); return; } AIComponent ai = entity.getComponent(AIComponent.class); command.sendChatResponse("Chosen entity is " + entity); if (parameters.aiName != null) { parameters.aiName = parameters.aiName.replace("_", " "); Optional<ClientIO> client = command.getServer().getClients().values().stream().filter(cl -> cl.getName().equals(parameters.aiName)).findAny(); if (client.isPresent()) { FakeAIClientTCG aiClient = (FakeAIClientTCG) client.get(); ai = createIfNotExists(ai, entity); ai.setAI(aiClient.getAI()); command.sendChatResponse("Changing AI to " + aiClient.getAI()); } else { entity.removeComponent(AIComponent.class); command.sendChatResponse("Removing AI"); } } if (parameters.delay != 0) { ai = createIfNotExists(ai, entity); ai.setDelay(parameters.delay); command.sendChatResponse("Changing delay to " + parameters.delay); } if (parameters.score) { ai = createIfNotExists(ai, entity); if (ai.getAI() instanceof ScoringAI) { ScoringAI scorer = (ScoringAI) ai.getAI(); outputScore(command, scorer, entity); } } } private void outputScore(CommandContext command, ScoringAI scorer, Entity entity) { FieldScores<Entity, ECSAction> results = scorer.calculateFullScore(entity); List<FieldScore<ECSAction>> scores = results.getScores().values().stream() .sorted(Comparator.<FieldScore<ECSAction>>comparingDouble(key -> key.getScore()).reversed()) .collect(Collectors.toList()); for (FieldScore<ECSAction> score : scores) { command.sendChatResponse("Scored field: " + score.getField() + " rank " + score.getRank() + " / " + results.getRankCount()); Map<Scorer, Double> detailed = score.getScoreMap(); for (Entry<Scorer, Double> ee : detailed.entrySet()) { command.sendChatResponse(ee.getKey() + ": " + ee.getValue()); } } } private AIComponent createIfNotExists(AIComponent obj, Entity entity) { if (obj == null) { AIComponent comp = new AIComponent(new IdleAI()); comp.setDelay(10000); entity.addComponent(comp); return comp; } return obj; } }