feat/refactor: actually track win conditions

This commit is contained in:
punchready 2021-05-27 17:58:44 +02:00
parent 7f7459e7a7
commit 830ef22997
6 changed files with 108 additions and 55 deletions

View File

@ -40,6 +40,11 @@ public class Inventory implements Iterable<StoneType> {
return size - content.size(); 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. * Checks if the inventory contains the given stone.
* @param stone The {@link StoneType} to check for * @param stone The {@link StoneType} to check for

View File

@ -5,7 +5,6 @@ import uulm.teamname.marvelous.gamelibrary.events.Event;
import uulm.teamname.marvelous.gamelibrary.events.EventType; import uulm.teamname.marvelous.gamelibrary.events.EventType;
import uulm.teamname.marvelous.gamelibrary.requests.Request; import uulm.teamname.marvelous.gamelibrary.requests.Request;
import java.util.ArrayList;
import java.util.Observer; import java.util.Observer;
/** Represents a game instance. */ /** Represents a game instance. */

View File

@ -1,7 +1,6 @@
package uulm.teamname.marvelous.gamelibrary.gamelogic; package uulm.teamname.marvelous.gamelibrary.gamelogic;
import uulm.teamname.marvelous.gamelibrary.IntVector2; import uulm.teamname.marvelous.gamelibrary.IntVector2;
import uulm.teamname.marvelous.gamelibrary.Tuple;
import uulm.teamname.marvelous.gamelibrary.entities.*; import uulm.teamname.marvelous.gamelibrary.entities.*;
import uulm.teamname.marvelous.gamelibrary.entities.Character; import uulm.teamname.marvelous.gamelibrary.entities.Character;
import uulm.teamname.marvelous.gamelibrary.events.*; import uulm.teamname.marvelous.gamelibrary.events.*;
@ -494,7 +493,14 @@ class GameLogic {
state.entities.removeEntity(((EntityEvent)event).targetEntity); state.entities.removeEntity(((EntityEvent)event).targetEntity);
} }
case TakenDamageEvent -> { 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 -> { case ConsumedAPEvent -> {
((Character)state.entities.findEntity(((CharacterEvent)event).targetEntity)).ap.decreaseValue(((CharacterEvent)event).amount); ((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)) { for(Entity entity: state.entities.findByPosition(((CharacterEvent)event).targetField)) {
if(entity instanceof InfinityStone) { if(entity instanceof InfinityStone) {
target.inventory.addStone(((InfinityStone)entity).type); target.inventory.addStone(((InfinityStone)entity).type);
state.winConditions.updateValue(target.id.type, WinCondition.MaxStones, target.inventory.getSize());
} }
} }
target.setPosition(((CharacterEvent)event).targetField); target.setPosition(((CharacterEvent)event).targetField);
@ -522,7 +530,10 @@ class GameLogic {
} }
case ExchangeInfinityStoneEvent -> { case ExchangeInfinityStoneEvent -> {
((Character)state.entities.findEntity(((CharacterEvent)event).originEntity)).inventory.removeStone(((CharacterEvent)event).stoneType); ((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()) { 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; return result;
} }
@ -602,6 +617,8 @@ class GameLogic {
result.addAll(handleStan(state, revived)); result.addAll(handleStan(state, revived));
} }
//TODO: add handling for thanos
Collections.shuffle(state.turnOrder); Collections.shuffle(state.turnOrder);
for (EntityID id: state.turnOrder) { for (EntityID id: state.turnOrder) {
@ -770,40 +787,4 @@ class GameLogic {
return result; 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<EntityType, WinCondition> player1;
Tuple<EntityType, WinCondition> player2;
int value1;
int value2;
for(WinCondition condition: WinCondition.values()) {
player1 = new Tuple<EntityType, WinCondition>(EntityType.P1, condition);
player2 = new Tuple<EntityType, WinCondition>(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;
}
} }

View File

@ -2,11 +2,9 @@ package uulm.teamname.marvelous.gamelibrary.gamelogic;
import uulm.teamname.marvelous.gamelibrary.IntVector2; import uulm.teamname.marvelous.gamelibrary.IntVector2;
import uulm.teamname.marvelous.gamelibrary.entities.*; import uulm.teamname.marvelous.gamelibrary.entities.*;
import uulm.teamname.marvelous.gamelibrary.Tuple;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
/** Represents the state of a game instance. */ /** Represents the state of a game instance. */
@ -38,8 +36,8 @@ class GameState {
/** The global cooldown of every infinity stone */ /** The global cooldown of every infinity stone */
public final StoneCooldownManager stoneCooldown = new StoneCooldownManager(); public final StoneCooldownManager stoneCooldown = new StoneCooldownManager();
/** The store of the {@link WinCondition} data for every win condition for each player */ /** The data for every win condition for each player */
public final HashMap<Tuple<EntityType, WinCondition>, Integer> winConditions = new HashMap<>(); public final WinConditionManager winConditions = new WinConditionManager();
/** /**
* Constructs a new {@link GameState}. * Constructs a new {@link GameState}.
@ -73,9 +71,7 @@ class GameState {
clone.stoneCooldown.cloneFrom(stoneCooldown); clone.stoneCooldown.cloneFrom(stoneCooldown);
for(Tuple<EntityType, WinCondition> condition: winConditions.keySet()) { clone.winConditions.cloneFrom(winConditions);
clone.winConditions.put(condition, winConditions.get(condition));
}
return clone; return clone;
} }
@ -104,8 +100,6 @@ class GameState {
stoneCooldown.cloneFrom(state.stoneCooldown); stoneCooldown.cloneFrom(state.stoneCooldown);
for(Tuple<EntityType, WinCondition> condition: state.winConditions.keySet()) { winConditions.cloneFrom(state.winConditions);
winConditions.put(condition, state.winConditions.get(condition));
}
} }
} }

View File

@ -1,13 +1,11 @@
package uulm.teamname.marvelous.gamelibrary.gamelogic; package uulm.teamname.marvelous.gamelibrary.gamelogic;
import uulm.teamname.marvelous.gamelibrary.IntVector2; 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.EntityID;
import uulm.teamname.marvelous.gamelibrary.entities.EntityType; import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
import uulm.teamname.marvelous.gamelibrary.entities.StoneType; import uulm.teamname.marvelous.gamelibrary.entities.StoneType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
/** Represents a game state view containing getters for all the properties of a {@link GameState}. */ /** Represents a game state view containing getters for all the properties of a {@link GameState}. */
public class GameStateView { public class GameStateView {
@ -54,7 +52,7 @@ public class GameStateView {
return state.stoneCooldown.getCooldown(stone); return state.stoneCooldown.getCooldown(stone);
} }
public EntityType getWinnerAccordingToWinConditions() { public EntityType getCurrentOvertimeWinner() {
return GameLogic.checkWinConditions(state); return state.winConditions.getWinner();
} }
} }

View File

@ -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<Tuple<EntityType, WinCondition>, 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);
}
}