diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/entities/Inventory.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/entities/Inventory.java index 420cbc4..1b6a2ce 100644 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/entities/Inventory.java +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/entities/Inventory.java @@ -40,6 +40,11 @@ public class Inventory implements Iterable { return size - content.size(); } + /** Returns the number stones the inventory has. */ + public int getSize() { + return content.size(); + } + /** * Checks if the inventory contains the given stone. * @param stone The {@link StoneType} to check for diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameInstance.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameInstance.java index 02b1736..8cfb2f6 100644 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameInstance.java +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameInstance.java @@ -5,7 +5,6 @@ import uulm.teamname.marvelous.gamelibrary.events.Event; import uulm.teamname.marvelous.gamelibrary.events.EventType; import uulm.teamname.marvelous.gamelibrary.requests.Request; -import java.util.ArrayList; import java.util.Observer; /** Represents a game instance. */ diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameLogic.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameLogic.java index f9c81fb..692b2b0 100644 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameLogic.java +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameLogic.java @@ -1,7 +1,6 @@ package uulm.teamname.marvelous.gamelibrary.gamelogic; import uulm.teamname.marvelous.gamelibrary.IntVector2; -import uulm.teamname.marvelous.gamelibrary.Tuple; import uulm.teamname.marvelous.gamelibrary.entities.*; import uulm.teamname.marvelous.gamelibrary.entities.Character; import uulm.teamname.marvelous.gamelibrary.events.*; @@ -494,7 +493,14 @@ class GameLogic { state.entities.removeEntity(((EntityEvent)event).targetEntity); } case TakenDamageEvent -> { - ((Character)state.entities.findEntity(((CharacterEvent)event).targetEntity)).hp.decreaseValue(((CharacterEvent)event).amount); + Character target = (Character)state.entities.findEntity(((CharacterEvent)event).targetEntity); + target.hp.decreaseValue(((CharacterEvent)event).amount); + + EntityType opposing = target.id.type == EntityType.P1 ? EntityType.P2 : EntityType.P1; + state.winConditions.increaseValue(opposing, WinCondition.TotalDamage, ((CharacterEvent)event).amount); + if(target.hp.getValue() == 0) { + state.winConditions.increaseValue(opposing, WinCondition.TotalKnockouts, 1); + } } case ConsumedAPEvent -> { ((Character)state.entities.findEntity(((CharacterEvent)event).targetEntity)).ap.decreaseValue(((CharacterEvent)event).amount); @@ -513,6 +519,8 @@ class GameLogic { for(Entity entity: state.entities.findByPosition(((CharacterEvent)event).targetField)) { if(entity instanceof InfinityStone) { target.inventory.addStone(((InfinityStone)entity).type); + + state.winConditions.updateValue(target.id.type, WinCondition.MaxStones, target.inventory.getSize()); } } target.setPosition(((CharacterEvent)event).targetField); @@ -522,7 +530,10 @@ class GameLogic { } case ExchangeInfinityStoneEvent -> { ((Character)state.entities.findEntity(((CharacterEvent)event).originEntity)).inventory.removeStone(((CharacterEvent)event).stoneType); - ((Character)state.entities.findEntity(((CharacterEvent)event).targetEntity)).inventory.addStone(((CharacterEvent)event).stoneType); + Character target = (Character)state.entities.findEntity(((CharacterEvent)event).targetEntity); + target.inventory.addStone(((CharacterEvent)event).stoneType); + + state.winConditions.updateValue(target.id.type, WinCondition.MaxStones, target.inventory.getSize()); } } } @@ -567,7 +578,11 @@ class GameLogic { } if(alive.isEmpty()) { - result.addAll(handlePlayerWin(state, checkWinConditions(state))); + EntityType winner = state.winConditions.getWinner(); + if(winner == EntityType.None) { + winner = rand.nextBoolean() ? EntityType.P1 : EntityType.P2; + } + result.addAll(handlePlayerWin(state, winner)); return result; } @@ -602,6 +617,8 @@ class GameLogic { result.addAll(handleStan(state, revived)); } + //TODO: add handling for thanos + Collections.shuffle(state.turnOrder); for (EntityID id: state.turnOrder) { @@ -770,40 +787,4 @@ class GameLogic { return result; } - - /** - * Checks a {@link GameState} for the current overtime win condition. - * @param state The game state to check - * @return The {@link EntityType} that is currently winning the game according to overtime ruling - */ - public static EntityType checkWinConditions(GameState state) { - //TODO: GameLogic.checkWinConditions is kind of ugly - - Tuple player1; - Tuple player2; - int value1; - int value2; - for(WinCondition condition: WinCondition.values()) { - player1 = new Tuple(EntityType.P1, condition); - player2 = new Tuple(EntityType.P2, condition); - value1 = 0; - value2 = 0; - - if(state.winConditions.containsKey(player1)) { - value1 = state.winConditions.get(player1); - } - if(state.winConditions.containsKey(player2)) { - value2 = state.winConditions.get(player2); - } - - if(value1 > value2) { - return EntityType.P1; - } - if(value2 > value1) { - return EntityType.P2; - } - } - - return EntityType.None; - } } diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameState.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameState.java index 9e75b2d..ee36b63 100644 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameState.java +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameState.java @@ -2,11 +2,9 @@ package uulm.teamname.marvelous.gamelibrary.gamelogic; import uulm.teamname.marvelous.gamelibrary.IntVector2; import uulm.teamname.marvelous.gamelibrary.entities.*; -import uulm.teamname.marvelous.gamelibrary.Tuple; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; /** Represents the state of a game instance. */ @@ -38,8 +36,8 @@ class GameState { /** The global cooldown of every infinity stone */ public final StoneCooldownManager stoneCooldown = new StoneCooldownManager(); - /** The store of the {@link WinCondition} data for every win condition for each player */ - public final HashMap, Integer> winConditions = new HashMap<>(); + /** The data for every win condition for each player */ + public final WinConditionManager winConditions = new WinConditionManager(); /** * Constructs a new {@link GameState}. @@ -73,9 +71,7 @@ class GameState { clone.stoneCooldown.cloneFrom(stoneCooldown); - for(Tuple condition: winConditions.keySet()) { - clone.winConditions.put(condition, winConditions.get(condition)); - } + clone.winConditions.cloneFrom(winConditions); return clone; } @@ -104,8 +100,6 @@ class GameState { stoneCooldown.cloneFrom(state.stoneCooldown); - for(Tuple condition: state.winConditions.keySet()) { - winConditions.put(condition, state.winConditions.get(condition)); - } + winConditions.cloneFrom(state.winConditions); } } diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameStateView.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameStateView.java index 95ac621..d3c618a 100644 --- a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameStateView.java +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameStateView.java @@ -1,13 +1,11 @@ package uulm.teamname.marvelous.gamelibrary.gamelogic; import uulm.teamname.marvelous.gamelibrary.IntVector2; -import uulm.teamname.marvelous.gamelibrary.entities.Entity; import uulm.teamname.marvelous.gamelibrary.entities.EntityID; import uulm.teamname.marvelous.gamelibrary.entities.EntityType; import uulm.teamname.marvelous.gamelibrary.entities.StoneType; import java.util.ArrayList; -import java.util.Iterator; /** Represents a game state view containing getters for all the properties of a {@link GameState}. */ public class GameStateView { @@ -54,7 +52,7 @@ public class GameStateView { return state.stoneCooldown.getCooldown(stone); } - public EntityType getWinnerAccordingToWinConditions() { - return GameLogic.checkWinConditions(state); + public EntityType getCurrentOvertimeWinner() { + return state.winConditions.getWinner(); } } diff --git a/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/WinConditionManager.java b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/WinConditionManager.java new file mode 100644 index 0000000..2a8814e --- /dev/null +++ b/src/main/java/uulm/teamname/marvelous/gamelibrary/gamelogic/WinConditionManager.java @@ -0,0 +1,76 @@ +package uulm.teamname.marvelous.gamelibrary.gamelogic; + +import uulm.teamname.marvelous.gamelibrary.Tuple; +import uulm.teamname.marvelous.gamelibrary.entities.EntityType; + +import java.util.HashMap; + +/** Represents a manager for win conditions. */ +public class WinConditionManager { + /** The store of the {@link WinCondition} data for every win condition for each player */ + private final HashMap, Integer> winConditions = new HashMap<>(); + + /** + * Returns the current winner + * @return The {@link EntityType} that is currently winning the game according to overtime ruling + */ + public EntityType getWinner() { + int value1; + int value2; + for(WinCondition condition: WinCondition.values()) { + value1 = getValue(EntityType.P1, condition); + value2 = getValue(EntityType.P2, condition); + + if(value1 > value2) { + return EntityType.P1; + } + if(value2 > value1) { + return EntityType.P2; + } + } + + return EntityType.None; + } + + /** + * Updates the value for a win condition for a specific player if the new value is greater than the old one. + * @param player The player to use + * @param condition The {@link WinCondition} to use + * @param value The new value + */ + public void updateValue(EntityType player, WinCondition condition, Integer value) { + Integer old = getValue(player, condition); + if(old < value) { + winConditions.put(new Tuple<>(player, condition), value); + } + } + + /** + * Increases the value for a win condition for a specific player. + * @param player The player to use + * @param condition The {@link WinCondition} to use + * @param value The new value + */ + public void increaseValue(EntityType player, WinCondition condition, Integer value) { + winConditions.put(new Tuple<>(player, condition), getValue(player, condition) + value); + } + + /** + * Gets the value for a specific player and win condition. + * @param player The player to use + * @param condition The {@link WinCondition} to use + * @return The value of the condition or 0 if it doesn't exist + */ + private Integer getValue(EntityType player, WinCondition condition) { + return winConditions.getOrDefault(new Tuple<>(player, condition), 0); + } + + /** + * Takes over all the win conditions from a different {@link WinConditionManager}. + * @param other The win condition manager to take the data from + */ + public void cloneFrom(WinConditionManager other) { + winConditions.clear(); + winConditions.putAll(other.winConditions); + } +}