From 7fffe2efbb926ba33c7290feb39c02c10f81e3c7 Mon Sep 17 00:00:00 2001 From: punchready Date: Thu, 1 Jul 2021 15:02:39 +0200 Subject: [PATCH] cleanup: remove moved code --- .../teamname/marvelous/gamelibrary/ai/AI.java | 177 -------- .../marvelous/gamelibrary/ai/AIClient.java | 64 --- .../marvelous/gamelibrary/ai/Action.java | 58 --- .../marvelous/gamelibrary/ai/ActionType.java | 11 - .../marvelous/gamelibrary/ai/Board.java | 395 ------------------ .../gamelibrary/ai/BoardAnalyzer.java | 157 ------- .../marvelous/gamelibrary/ai/Node.java | 60 --- .../marvelous/gamelibrary/ai/Piece.java | 91 ---- .../marvelous/gamelibrary/ai/PieceType.java | 11 - .../gamelibrary/gamelogic/AITest.java | 95 ----- ...impleErrorSensitiveThreadPoolExecutor.java | 30 -- 11 files changed, 1149 deletions(-) delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AIClient.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Action.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/ActionType.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Board.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/BoardAnalyzer.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Node.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Piece.java delete mode 100644 src/main/java/uulm/teamname/marvelous/gamelibrary/ai/PieceType.java delete mode 100644 src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/AITest.java delete mode 100644 src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/SimpleErrorSensitiveThreadPoolExecutor.java diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java deleted file mode 100644 index 71ceed0..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java +++ /dev/null @@ -1,177 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig; -import uulm.teamname.marvelous.gamelibrary.config.PartyConfig; -import uulm.teamname.marvelous.gamelibrary.config.ScenarioConfig; -import uulm.teamname.marvelous.gamelibrary.entities.Character; -import uulm.teamname.marvelous.gamelibrary.entities.EntityID; -import uulm.teamname.marvelous.gamelibrary.entities.EntityType; -import uulm.teamname.marvelous.gamelibrary.gamelogic.GameStateView; -import uulm.teamname.marvelous.gamelibrary.requests.Request; -import uulm.teamname.marvelous.gamelibrary.requests.RequestBuilder; -import uulm.teamname.marvelous.gamelibrary.requests.RequestType; - -import java.util.ArrayList; - -/** Represents an AI instance for calculations. */ -class AI { - /** The {@link GameStateView} the AI is playing on. */ - private final GameStateView state; - - /** The Player the AI is playing for. */ - private final EntityType player; - - /** The config data. */ - private final PartyConfig partyConfig; - private final CharacterConfig characterConfig; - private final ScenarioConfig scenarioConfig; - - /** Constructs a new {@link AI} playing the given player based on the given config values. */ - public AI(GameStateView state, EntityType player, PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) { - this.state = state; - this.player = player; - this.partyConfig = partyConfig; - this.characterConfig = characterConfig; - this.scenarioConfig = scenarioConfig; - } - - /** - * Calculates the appropriate actions for a turn of any of the characters the AI is playing for. - * @param turn The {@link EntityID} that currently has the turn - * @return A list of {@link Request Requests} with the actions the AI wants to perform - */ - public ArrayList performTurn(EntityID turn) { - System.out.println("[AI] Handling Character " + turn + " for Player " + player + ":"); - - ArrayList result = new ArrayList<>(); - - Character character = (Character)state.getEntities().findEntity(turn); - - BoardAnalyzer analyzer = new BoardAnalyzer(state, turn); - Action action = analyzer.analyze(state); - - switch(action.type) { - case None -> { - System.out.println(" Result: doing nothing"); - result.add(new RequestBuilder(RequestType.EndRoundRequest) - .buildGameRequest()); - } - case Move -> { - System.out.println(" Result: moving to " + action.target); - result.add(new RequestBuilder(RequestType.MoveRequest) - .withOriginEntity(turn) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .buildCharacterRequest()); - } - case MeleeAttack -> { - System.out.println(" Result: melee attacking " + action.targetEntity); - Character target = (Character)state.getEntities().findEntity(action.targetEntity); - if(target != null) { - result.add(new RequestBuilder(RequestType.MeleeAttackRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withValue(character.meleeDamage) - .buildCharacterRequest()); - } - } - case RangedAttack -> { - System.out.println(" Result: ranged attacking " + action.targetEntity); - Character target = (Character)state.getEntities().findEntity(action.targetEntity); - if(target != null) { - result.add(new RequestBuilder(RequestType.RangedAttackRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withValue(character.rangedDamage) - .buildCharacterRequest()); - } - } - case UseStone -> { - switch(action.stone) { - case SpaceStone -> { - System.out.println(" Result: using space stone to " + action.target); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - case MindStone -> { - System.out.println(" Result: using mind stone to " + action.target); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withValue(partyConfig.mindStoneDMG) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - case RealityStone -> { - System.out.println(" Result: using reality stone at " + action.target); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - case PowerStone -> { - System.out.println(" Result: using power stone against " + action.targetEntity); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withValue(character.rangedDamage * 2) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - case TimeStone -> { - System.out.println(" Result: using time stone"); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withOriginField(character.getPosition()) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - case SoulStone -> { - System.out.println(" Result: using soul stone on " + action.targetEntity); - result.add(new RequestBuilder(RequestType.UseInfinityStoneRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - } - } - case GiveStone -> { - System.out.println(" Result: giving stone to " + action.targetEntity); - Character target = (Character)state.getEntities().findEntity(action.targetEntity); - if(target != null) { - result.add(new RequestBuilder(RequestType.ExchangeInfinityStoneRequest) - .withOriginEntity(turn) - .withTargetEntity(action.targetEntity) - .withOriginField(character.getPosition()) - .withTargetField(action.target) - .withStoneType(action.stone) - .buildCharacterRequest()); - } - } - case EndTurn -> { - System.out.println(" Result: ending turn"); - result.add(new RequestBuilder(RequestType.EndRoundRequest) - .buildGameRequest()); - } - } - - return result; - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AIClient.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AIClient.java deleted file mode 100644 index 67eac3c..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AIClient.java +++ /dev/null @@ -1,64 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig; -import uulm.teamname.marvelous.gamelibrary.config.PartyConfig; -import uulm.teamname.marvelous.gamelibrary.config.ScenarioConfig; -import uulm.teamname.marvelous.gamelibrary.entities.EntityType; -import uulm.teamname.marvelous.gamelibrary.events.Event; -import uulm.teamname.marvelous.gamelibrary.events.EventType; -import uulm.teamname.marvelous.gamelibrary.gamelogic.GameInstance; -import uulm.teamname.marvelous.gamelibrary.requests.Request; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** Represents an AI player. */ -public class AIClient { - /** The {@link GameInstance} the AI is playing on. */ - private final GameInstance game; - - /** The Player the AI is playing for. */ - private final EntityType player; - - /** The actual {@link AI} instance. */ - private final AI ai; - - /** Constructs a new {@link AIClient} playing the given player based on the given config values. */ - public AIClient(EntityType player, PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) { - this.game = new GameInstance(partyConfig, characterConfig, scenarioConfig); - this.player = player; - this.ai = new AI(game.state, player, partyConfig, characterConfig, scenarioConfig); - } - - /** - * Handles incoming {@link Event Events} and optionally returns a list of response {@link Request Requests}. - * @param events The incoming events - * @return Optionally resulting requests - */ - public Optional> handle(Event... events) { - ArrayList result = new ArrayList<>(); - - game.applyEvents(events); - - boolean containsTurn = false; - for(Event event: events) { - if(event.type == EventType.TurnEvent) { - containsTurn = true; - break; - } - } - - //detect turn - if(containsTurn && game.state.getActiveCharacter() != null && game.state.getActiveCharacter().type == player) { - //let ai calculate requests - result.addAll(this.ai.performTurn(game.state.getActiveCharacter())); - } - - if(!result.isEmpty()) { - return Optional.of(result); - }else { - return Optional.empty(); - } - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Action.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Action.java deleted file mode 100644 index fdc2f50..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Action.java +++ /dev/null @@ -1,58 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.IntVector2; -import uulm.teamname.marvelous.gamelibrary.entities.EntityID; -import uulm.teamname.marvelous.gamelibrary.entities.StoneType; - -class Action { - public final ActionType type; - public final IntVector2 target; - public final EntityID targetEntity; - public final StoneType stone; - - public Action(ActionType type) { - this.type = type; - this.target = null; - this.targetEntity = null; - this.stone = null; - } - - public Action(ActionType type, IntVector2 target) { - this.type = type; - this.target = target; - this.targetEntity = null; - this.stone = null; - } - - public Action(ActionType type, IntVector2 target, EntityID targetEntity) { - this.type = type; - this.target = target; - this.targetEntity = targetEntity; - this.stone = null; - } - - public Action(ActionType type, StoneType stone) { - this.type = type; - this.target = null; - this.targetEntity = null; - this.stone = stone; - } - - public Action(ActionType type, IntVector2 target, StoneType stone) { - this.type = type; - this.target = target; - this.targetEntity = null; - this.stone = stone; - } - - public Action(ActionType type, IntVector2 target, EntityID targetEntity, StoneType stone) { - this.type = type; - this.target = target; - this.targetEntity = targetEntity; - this.stone = stone; - } - - public String toString() { - return this.type.toString(); - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/ActionType.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/ActionType.java deleted file mode 100644 index f089f1a..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/ActionType.java +++ /dev/null @@ -1,11 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -enum ActionType { - None, - Move, - MeleeAttack, - RangedAttack, - UseStone, - GiveStone, - EndTurn -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Board.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Board.java deleted file mode 100644 index 9483cbe..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Board.java +++ /dev/null @@ -1,395 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.IntVector2; -import uulm.teamname.marvelous.gamelibrary.entities.*; -import uulm.teamname.marvelous.gamelibrary.entities.Character; -import uulm.teamname.marvelous.gamelibrary.gamelogic.GameLogic; -import uulm.teamname.marvelous.gamelibrary.gamelogic.GameStateView; - -import java.util.ArrayList; -import java.util.Objects; - -class Board { - private final Piece[][] data; - public final EntityType origin; - public final EntityID turn; - public final boolean ended; - - private Board(Piece[][] data, EntityType origin, EntityID turn) { - this.data = data; - this.origin = origin; - this.turn = turn; - this.ended = false; - } - - private Board(Piece[][] data, EntityType origin, EntityID turn, boolean ended) { - this.data = data; - this.origin = origin; - this.turn = turn; - this.ended = ended; - } - - public static Board generate(GameStateView state, EntityID turn) { - Piece[][] data = new Piece[state.getMapSize().getY()][state.getMapSize().getX()]; - for(int x = 0; x < state.getMapSize().getX(); x++) { - for(int y = 0; y < state.getMapSize().getY(); y++) { - IntVector2 pos = new IntVector2(x, y); - ArrayList entities = state.getEntities().findByPosition(pos); - if(entities.isEmpty()) { - data[y][x] = new Piece(PieceType.Empty); - }else { - Entity entity = entities.get(0); - switch(entity.id.type) { - case NPC -> { - if(entity.id.id == NPCType.Thanos.getID()) { - data[y][x] = new Piece(PieceType.Thanos); - }else { - data[y][x] = new Piece(PieceType.NPC); - } - } - case P1, P2 -> { - Character character = (Character)entity; - data[y][x] = new Piece( - PieceType.Character, - entity.id, - character.hp.getValue(), - character.hp.getMax(), - character.mp.getValue(), - character.mp.getMax(), - character.ap.getValue(), - character.ap.getMax(), - character.inventory.getStonesAsArray() - ); - } - case Rocks -> { - Rock rock = (Rock)entity; - data[y][x] = new Piece(PieceType.Rock, entity.id, rock.getHp(), rock.maxHP); - } - case Portals -> { - data[y][x] = new Piece(PieceType.Portal, entity.id); - } - case InfinityStones -> { - InfinityStone stone = (InfinityStone)entity; - data[y][x] = new Piece(PieceType.InfinityStone, entity.id, stone.type); - } - case None -> { - data[y][x] = new Piece(PieceType.Empty); - } - } - } - } - } - return new Board(data, turn.type, turn); - } - - protected ArrayList generateActions(GameStateView state) { - ArrayList result = new ArrayList<>(); - - EntityType opposite = turn.type == EntityType.P1 ? EntityType.P2 : EntityType.P1; - - Character character = (Character)state.getEntities().findEntity(turn); - - Piece current = null; - IntVector2 position = null; - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - if(this.data[y][x].type == PieceType.Character && this.data[y][x].id.equals(turn)) { - current = this.data[y][x]; - position = new IntVector2(x, y); - } - } - } - - if(current == null) { - return result; - } - - for(ActionType action: ActionType.values()) { - switch(action) { - case Move -> { - if(current.mp.getValue() <= 0) { - continue; - } - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if( - target.getX() < 0 || target.getX() >= state.getMapSize().getX() || - target.getY() < 0 || target.getY() >= state.getMapSize().getY() - ) { - continue; - } - if( - this.data[target.getY()][target.getX()].type == PieceType.Empty || - this.data[target.getY()][target.getX()].type == PieceType.Character - ) { - result.add(new Action(ActionType.Move, target)); - } - } - } - case MeleeAttack -> { - if(current.ap.getValue() <= 0) { - continue; - } - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if(target.getX() < 0 || target.getX() >= state.getMapSize().getX() || target.getY() < 0 || target.getY() >= state.getMapSize().getY()) { - continue; - } - Piece targetPiece = this.data[target.getY()][target.getX()]; - if(targetPiece.type == PieceType.Character && targetPiece.id.type == opposite) { - result.add(new Action(ActionType.MeleeAttack, target, targetPiece.id)); - } - } - } - case RangedAttack -> { - if(current.ap.getValue() <= 0) { - continue; - } - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - IntVector2 pos = new IntVector2(x, y); - float dist = pos.distanceChebyshev(position); - if(this.data[y][x].type == PieceType.Character && this.data[y][x].id.type == opposite && dist > 1 && dist <= character.attackRange && lineOfSight(position, pos)) { - result.add(new Action(ActionType.RangedAttack, pos, this.data[y][x].id)); - } - } - } - } - case UseStone -> { - if(current.ap.getValue() <= 0) { - continue; - } - for(StoneType stone: StoneType.values()) { - if(state.getStoneCooldown(stone) > 0) { - continue; - } - if(!character.inventory.hasStone(stone)) { - continue; - } - switch(stone) { - case SpaceStone -> { - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - if(this.data[y][x].type == PieceType.Empty) { - result.add(new Action(ActionType.UseStone, new IntVector2(x, y), stone)); - } - } - } - } - case MindStone -> { - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - result.add(new Action(ActionType.UseStone, new IntVector2(x, y), stone)); - } - } - } - case RealityStone -> { - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if(target.getX() < 0 || target.getX() >= state.getMapSize().getX() || target.getY() < 0 || target.getY() >= state.getMapSize().getY()) { - continue; - } - Piece targetPiece = this.data[target.getY()][target.getX()]; - if(targetPiece.type == PieceType.Empty) { - result.add(new Action(ActionType.UseStone, target, turn, stone)); - }else if(targetPiece.type == PieceType.Rock) { - result.add(new Action(ActionType.UseStone, target, targetPiece.id, stone)); - } - } - } - case PowerStone -> { - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if(target.getX() < 0 || target.getX() >= state.getMapSize().getX() || target.getY() < 0 || target.getY() >= state.getMapSize().getY()) { - continue; - } - Piece targetPiece = this.data[target.getY()][target.getX()]; - if(targetPiece.type == PieceType.Character && targetPiece.id.type == opposite) { - result.add(new Action(ActionType.UseStone, target, targetPiece.id, stone)); - } - } - } - case TimeStone -> { - result.add(new Action(ActionType.UseStone, stone)); - } - case SoulStone -> { - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if(target.getX() < 0 || target.getX() >= state.getMapSize().getX() || target.getY() < 0 || target.getY() >= state.getMapSize().getY()) { - continue; - } - Piece targetPiece = this.data[target.getY()][target.getX()]; - if(targetPiece.type == PieceType.Character && targetPiece.id.type == turn.type && targetPiece.hp.getValue() <= 0) { - result.add(new Action(ActionType.UseStone, target, targetPiece.id, stone)); - } - } - } - } - } - } - case GiveStone -> { - if(current.ap.getValue() <= 0) { - continue; - } - for(StoneType stone: current.inventory) { - for(IntVector2 dir: IntVector2.CardinalDirections) { - IntVector2 target = position.add(dir); - if(target.getX() < 0 || target.getX() >= state.getMapSize().getX() || target.getY() < 0 || target.getY() >= state.getMapSize().getY()) { - continue; - } - Piece targetPiece = this.data[target.getY()][target.getX()]; - if(targetPiece.type == PieceType.Character && targetPiece.id.type == turn.type) { - result.add(new Action(ActionType.GiveStone, target, targetPiece.id, stone)); - } - } - } - } - case EndTurn -> { - result.add(new Action(ActionType.EndTurn)); - } - } - } - - return result; - } - - protected Board applyAction(GameStateView state, Action action) { - Piece[][] clone = new Piece[this.data.length][this.data[0].length]; - - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - clone[y][x] = this.data[y][x].clone(); - } - } - - Character character = (Character)state.getEntities().findEntity(turn); - - Piece current = null; - IntVector2 position = null; - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - if(this.data[y][x].type == PieceType.Character && this.data[y][x].id.equals(turn)) { - current = this.data[y][x]; - position = new IntVector2(x, y); - } - } - } - - boolean ended = false; - - //TODO: finalize action applying - - switch(action.type) { - case Move -> { - clone[position.getY()][position.getX()] = clone[action.target.getY()][action.target.getX()]; - clone[action.target.getY()][action.target.getX()] = current; - current.mp.decreaseValue(1); - } - case MeleeAttack -> { - clone[action.target.getY()][action.target.getX()].hp.decreaseValue(character.meleeDamage); - current.ap.decreaseValue(1); - //todo: drop stones........ - } - case RangedAttack -> { - clone[action.target.getY()][action.target.getX()].hp.decreaseValue(character.rangedDamage); - current.ap.decreaseValue(1); - } - case UseStone -> { - switch(action.stone) { - case SpaceStone -> { - - } - case MindStone -> { - - } - case RealityStone -> { - - } - case PowerStone -> { - - } - case TimeStone -> { - - } - case SoulStone -> { - - } - } - } - case GiveStone -> { - - } - case EndTurn -> { - ended = true; - } - } - - if(ended || (current.mp.getValue() == 0 && current.ap.getValue() == 0)) { - ArrayList alive = new ArrayList<>(); - for(EntityID next: state.getTurnOrder()) { - if(next.type == EntityType.NPC && next.id == NPCType.Thanos.getID()) { - alive.add(next); - }else if(next.type == EntityType.P1 || next.type == EntityType.P2) { - if(((Character)state.getEntities().findEntity(next)).isAlive()) { - alive.add(next); - } - } - } - int index = alive.indexOf(turn); - if(index == alive.size() - 1) { - return new Board(clone, origin, turn, true); - }else { - return new Board(clone, origin, alive.get(index + 1)); - } - }else { - return new Board(clone, origin, turn); - } - } - - protected float calculateScore() { - float score = 0; - - for(int x = 0; x < this.data[0].length; x++) { - for(int y = 0; y < this.data.length; y++) { - IntVector2 current = new IntVector2(x, y); - Piece piece = this.data[y][x]; - switch(piece.type) { - case Empty, Rock, NPC, InfinityStone, Thanos -> { - score += 0; - } - case Character -> { - float nearby = 0; - for(int x2 = 0; x2 < this.data[0].length; x2++) { - for(int y2 = 0; y2 < this.data.length; y2++) { - if(this.data[y2][x2].type == PieceType.InfinityStone) { - nearby += (1f / new IntVector2(x2, y2).distance(current)) * 3f; - } - } - } - float result = nearby + piece.inventory.size() + ((float)piece.hp.getValue() / (float)piece.hp.getMax()) * 2f; - if(piece.id.type == origin) { - score += result; - }else { - score -= result; - } - } - } - } - } - - return score; - } - - protected int calculateHash() { - return Objects.hash(super.hashCode(), data); - } - - private boolean lineOfSight(IntVector2 a, IntVector2 b) { - for(IntVector2 pos: GameLogic.rasterize(a, b, false, false)) { - if(this.data[pos.getY()][pos.getX()].type != PieceType.Empty) { - return false; - } - } - return true; - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/BoardAnalyzer.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/BoardAnalyzer.java deleted file mode 100644 index 6a25f2a..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/BoardAnalyzer.java +++ /dev/null @@ -1,157 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.entities.EntityID; -import uulm.teamname.marvelous.gamelibrary.entities.EntityType; -import uulm.teamname.marvelous.gamelibrary.gamelogic.GameStateView; - -import java.util.ArrayList; -import java.util.HashMap; - -class BoardAnalyzer { - private final Board origin; - private final EntityType player; - private final HashMap scoreCache = new HashMap<>(); - private final HashMap> actionCache = new HashMap<>(); - private Action bestAction = null; - - public BoardAnalyzer(GameStateView state, EntityID turn) { - this.origin = Board.generate(state, turn); - this.player = turn.type; - } - - public Action analyze(GameStateView state) { - Node tree = new Node(origin, new Action(ActionType.None)); - - int maxDepth = 2; - int depth = 0; - long startTime = System.nanoTime(); - while(System.nanoTime() - startTime <= 1000 * 1000 * 1000) { - expandTree(tree, state); - depth++; - if(depth > maxDepth) { - break; - } - } - - alphaBetaMax(tree, Float.MIN_VALUE, Float.MAX_VALUE, true); - - if(bestAction != null) { - return bestAction; - } - - return new Action(ActionType.None); - } - - private Float alphaBetaMax(Node root, Float a, Float b, boolean main) { - if(!root.hasChildren()) { - return calculateScore(root.board); - } - Float w = a; - for(Node child: root.getChildren()) { - Float v; - if(child.board.turn.type == child.board.origin) { - v = alphaBetaMax(child, a, w, false); - }else { - v = alphaBetaMin(child, w, b); - } - if(v > w) { - w = v; - } - if(w >= b) { - if(main) { - bestAction = child.action; - } - return w; - } - if(main) { - bestAction = child.action; - } - } - return w; - } - - private Float alphaBetaMin(Node root, Float a, Float b) { - if(!root.hasChildren()) { - return calculateScore(root.board); - } - Float w = b; - for(Node child: root.getChildren()) { - Float v; - if(child.board.turn.type == child.board.origin) { - v = alphaBetaMax(child, a, w, false); - }else { - v = alphaBetaMin(child, w, b); - } - if(v < w) { - w = v; - } - if(w <= a) { - return w; - } - } - return w; - } - - private ArrayList getLeaves(Node root) { - return getLeaves(root, new ArrayList<>()); - } - - private ArrayList getLeaves(Node root, ArrayList accumulator) { - for(Node child: root.getChildren()) { - if(child.hasChildren()) { - getLeaves(child, accumulator); - }else { - accumulator.add(child); - } - } - return accumulator; - } - - private void expandTree(Node root, GameStateView state) { - if(!root.hasChildren()) { - expandNode(root, state); - return; - } - for(Node child: root.getChildren()) { - if(child.board.ended) { - continue; - } - if(child.hasChildren()) { - expandTree(child, state); - }else { - expandNode(child, state); - } - } - } - - private void expandNode(Node origin, GameStateView state) { - ArrayList actions = generateActions(origin.board, state); - for(Action action: actions) { - Board result = origin.board.applyAction(state, action); - scoreCache.put(result.hashCode(), result.calculateScore()); - origin.addChild(result, action, result.calculateScore()); - } - } - - private ArrayList generateActions(Board board, GameStateView state) { - int hash = board.hashCode(); - if(actionCache.containsKey(hash)) { - return actionCache.get(hash); - }else { - ArrayList result = board.generateActions(state); - actionCache.put(hash, result); - return result; - } - } - - private Float calculateScore(Board board) { - int hash = board.hashCode(); - if(scoreCache.containsKey(hash)) { - return scoreCache.get(hash); - }else { - Float result = board.calculateScore(); - scoreCache.put(hash, result); - return result; - } - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Node.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Node.java deleted file mode 100644 index 3db2116..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Node.java +++ /dev/null @@ -1,60 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import java.util.ArrayList; -import java.util.List; - -public class Node { - public final Board board; - public final Action action; - public final Float score; - private final List children = new ArrayList<>(); - private Node parent = null; - - public Node(Board board, Action action) { - this.board = board; - this.action = action; - this.score = 0f; - } - - public Node(Board board, Action action, Float score) { - this.board = board; - this.action = action; - this.score = score; - } - - public void addChild(Node child) { - child.setParent(this); - this.children.add(child); - } - - public void addChild(Board board, Action action) { - this.addChild(new Node(board, action)); - } - - public void addChild(Board board, Action action, Float score) { - this.addChild(new Node(board, action, score)); - } - - public void addChildren(List children) { - for(Node t : children) { - t.setParent(this); - } - this.children.addAll(children); - } - - public List getChildren() { - return children; - } - - public boolean hasChildren() { - return !children.isEmpty(); - } - - private void setParent(Node parent) { - this.parent = parent; - } - - public Node getParent() { - return parent; - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Piece.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Piece.java deleted file mode 100644 index 2aef2a8..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/Piece.java +++ /dev/null @@ -1,91 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -import uulm.teamname.marvelous.gamelibrary.entities.*; - -import java.util.Arrays; -import java.util.HashSet; - -class Piece { - public final PieceType type; - - public EntityID id; - - public Stat hp; - public Stat mp; - public Stat ap; - - public HashSet inventory; - - public StoneType stone; - - public Piece(PieceType type) { - this.type = type; - this.id = null; - this.hp = null; - this.mp = null; - this.ap = null; - this.inventory = null; - this.stone = null; - } - - public Piece(PieceType type, EntityID id) { - this.type = type; - this.id = id; - this.hp = null; - this.mp = null; - this.ap = null; - this.inventory = null; - this.stone = null; - } - - public Piece(PieceType type, EntityID id, int hp, int maxHP) { - this.type = type; - this.id = id; - this.hp = new Stat(StatType.HP, hp, maxHP); - this.mp = null; - this.ap = null; - this.inventory = null; - this.stone = null; - } - - public Piece(PieceType type, EntityID id, StoneType stone) { - this.type = type; - this.id = id; - this.hp = null; - this.mp = null; - this.ap = null; - this.inventory = null; - this.stone = stone; - } - - public Piece(PieceType type, EntityID id, int hp, int maxHP, int mp, int maxMP, int ap, int maxAP, StoneType[] inventory) { - this.type = type; - this.id = id; - this.hp = new Stat(StatType.HP, hp, maxHP); - this.mp = new Stat(StatType.MP, mp, maxMP); - this.ap = new Stat(StatType.AP, ap, maxAP); - this.inventory = new HashSet<>(Arrays.asList(inventory)); - this.stone = null; - } - - private Piece(PieceType type, EntityID id, int hp, int maxHP, int mp, int maxMP, int ap, int maxAP, StoneType[] inventory, StoneType stone) { - this.type = type; - this.id = id; - this.hp = new Stat(StatType.HP, hp, maxHP); - this.mp = new Stat(StatType.MP, mp, maxMP); - this.ap = new Stat(StatType.AP, ap, maxAP); - this.inventory = new HashSet<>(Arrays.asList(inventory)); - this.stone = stone; - } - - public Piece clone() { - Piece clone = new Piece(type); - clone.id = this.id != null ? this.id.clone() : null; - clone.hp = this.hp != null ? new Stat(StatType.HP, this.hp.getValue(), this.hp.getMax()) : null; - clone.mp = this.mp != null ? new Stat(StatType.MP, this.mp.getValue(), this.mp.getMax()) : null; - clone.ap = this.ap != null ? new Stat(StatType.AP, this.ap.getValue(), this.ap.getMax()) : null; - clone.inventory = this.inventory != null ? (HashSet)this.inventory.clone() : null; - clone.stone = this.stone; - return clone; - } -} diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/PieceType.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/PieceType.java deleted file mode 100644 index 2d92a40..0000000 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/ai/PieceType.java +++ /dev/null @@ -1,11 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.ai; - -enum PieceType { - Empty, - Rock, - Character, - InfinityStone, - Thanos, - NPC, - Portal -} diff --git a/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/AITest.java b/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/AITest.java deleted file mode 100644 index 8d9a716..0000000 --- a/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/AITest.java +++ /dev/null @@ -1,95 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.gamelogic; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import uulm.teamname.marvelous.gamelibrary.ai.AIClient; -import uulm.teamname.marvelous.gamelibrary.entities.EntityType; -import uulm.teamname.marvelous.gamelibrary.events.Event; -import uulm.teamname.marvelous.gamelibrary.json.JSON; -import uulm.teamname.marvelous.gamelibrary.messages.*; -import uulm.teamname.marvelous.gamelibrary.messages.client.*; -import uulm.teamname.marvelous.gamelibrary.messages.server.*; -import uulm.teamname.marvelous.gamelibrary.requests.*; - -import java.util.List; -import java.util.Optional; -import java.util.concurrent.*; - -class AITest extends BaseGameLogicTest { - private static JSON json; - private static ExecutorService executor; - - private static GameInstance server; - private static AIClient clientA; - private static AIClient clientB; - - @BeforeAll - static void setUp() { - generate(); - - json = new JSON(characterConfig); - executor = new SimpleErrorSensitiveThreadPoolExecutor(); - - server = new GameInstance(partyConfig, characterConfig, scenarioConfig); - clientA = new AIClient(EntityType.P1, partyConfig, characterConfig, scenarioConfig); - clientB = new AIClient(EntityType.P2, partyConfig, characterConfig, scenarioConfig); - } - - @Test - void main() throws InterruptedException { - serverSend(server.startGame(player1Selection, player2Selection).toArray(new Event[0])); - - Thread.sleep(2000); - } - - private void clientSend(Request[] requests) { - RequestMessage message = new RequestMessage(); - message.messages = requests; - - Optional data = json.stringify(message); - - if(data.isPresent()) { - executor.submit(() -> serverReceive(data.get())); - } - } - - private void clientReceive(String data) { - Optional message = json.parse(data); - - if(message.isPresent()) { - Optional> resultA = clientA.handle(((EventMessage)message.get()).messages); - Optional> resultB = clientB.handle(((EventMessage)message.get()).messages); - - if(resultA.isPresent()) { - executor.submit(() -> clientSend(resultA.get().toArray(new Request[0]))); - } - - if(resultB.isPresent()) { - executor.submit(() -> clientSend(resultB.get().toArray(new Request[0]))); - } - } - } - - private void serverSend(Event[] events) { - EventMessage message = new EventMessage(); - message.messages = events; - - Optional data = json.stringify(message); - - if(data.isPresent()) { - executor.submit(() -> clientReceive(data.get())); - } - } - - private void serverReceive(String data) { - Optional message = json.parse(data); - - if(message.isPresent()) { - Optional> result = server.checkRequestsAndApply(((RequestMessage)message.get()).messages); - - if(result.isPresent()) { - executor.submit(() -> serverSend(result.get().toArray(new Event[0]))); - } - } - } -} diff --git a/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/SimpleErrorSensitiveThreadPoolExecutor.java b/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/SimpleErrorSensitiveThreadPoolExecutor.java deleted file mode 100644 index 21e6714..0000000 --- a/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/SimpleErrorSensitiveThreadPoolExecutor.java +++ /dev/null @@ -1,30 +0,0 @@ -package uulm.teamname.marvelous.gamelibrary.gamelogic; - -import java.util.concurrent.*; - -public final class SimpleErrorSensitiveThreadPoolExecutor extends ThreadPoolExecutor { - public SimpleErrorSensitiveThreadPoolExecutor() { - super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); - } - - protected void afterExecute(Runnable r, Throwable t) { - super.afterExecute(r, t); - if (t == null && r instanceof Future) { - try { - Future future = (Future) r; - if (future.isDone()) { - future.get(); - } - } catch (CancellationException ce) { - t = ce; - } catch (ExecutionException ee) { - t = ee.getCause(); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } - } - if (t != null) { - t.printStackTrace(); - } - } -}