wip: backbone for the game logic package
This commit is contained in:
parent
90aad32b92
commit
0f7109d41a
15
src/uulm/teamname/marvelous/gamelibrary/Tuple.java
Normal file
15
src/uulm/teamname/marvelous/gamelibrary/Tuple.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary;
|
||||||
|
|
||||||
|
/** Represents a pair of two objects.
|
||||||
|
*/
|
||||||
|
public class Tuple<X, Y> {
|
||||||
|
public final X item1;
|
||||||
|
public final Y item2;
|
||||||
|
|
||||||
|
/** Constructs a new {@link Tuple} based on the given objects.
|
||||||
|
*/
|
||||||
|
public Tuple(X item1, Y item2) {
|
||||||
|
this.item1 = item1;
|
||||||
|
this.item2 = item2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.events;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.json.MessageStructure;
|
||||||
|
|
||||||
|
/** Represents an abstract event sent inside a {@link MessageStructure} between client and server.
|
||||||
|
*/
|
||||||
|
public abstract class Event {
|
||||||
|
//TODO: implement Event
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
/** Contains checksum calculations.
|
||||||
|
*/
|
||||||
|
class ChecksumCalculator {
|
||||||
|
/** Compares a checksum to the checksum of a {@link GameState}.
|
||||||
|
* @param state The state to check.
|
||||||
|
* @param input the checksum to compare to.
|
||||||
|
* @return Whether or not the checksum matches the state's checksum.
|
||||||
|
*/
|
||||||
|
public static boolean checkChecksum(GameState state, long input) {
|
||||||
|
return calculateChecksum(state) == input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculates the corresponding checksum to a {@link GameState}.
|
||||||
|
* @param state The state to check.
|
||||||
|
* @return The checksum.
|
||||||
|
*/
|
||||||
|
public static long calculateChecksum(GameState state) {
|
||||||
|
//TODO: implement ChecksumCalculator.calculateChecksum
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import java.util.Observable;
|
||||||
|
|
||||||
|
/** Represents an event emitter for game events fired by a game instance.
|
||||||
|
*/
|
||||||
|
class EventEmitter extends Observable {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||||
|
|
||||||
|
import java.util.Observer;
|
||||||
|
|
||||||
|
/** Represents a game instance.
|
||||||
|
*/
|
||||||
|
public class GameInstance {
|
||||||
|
/** The private {@link GameState} of the instance.
|
||||||
|
*/
|
||||||
|
private final GameState _state;
|
||||||
|
|
||||||
|
/** The public view for the underlying {@link GameState} of the instance.
|
||||||
|
*/
|
||||||
|
public final GameStateView state;
|
||||||
|
|
||||||
|
/** The {@link GameStateManager} managing the {@link GameState} of the instance.
|
||||||
|
*/
|
||||||
|
private final GameStateManager manager;
|
||||||
|
|
||||||
|
/** The {@link EventEmitter} for {@link Event}s resulting from {@link Request}s.
|
||||||
|
*/
|
||||||
|
private final EventEmitter emitter = new EventEmitter();
|
||||||
|
|
||||||
|
/** Constructs a new {@link GameInstance}.
|
||||||
|
*/
|
||||||
|
public GameInstance(IntVector2 mapSize) {
|
||||||
|
_state = new GameState(mapSize);
|
||||||
|
this.state = new GameStateView(_state);
|
||||||
|
manager = new GameStateManager(_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks a checksum with the current one.
|
||||||
|
* @param input The checksum to compare to.
|
||||||
|
* @return Whether or not the checksum matches.
|
||||||
|
*/
|
||||||
|
public boolean checkChecksum(long input) {
|
||||||
|
return ChecksumCalculator.checkChecksum(_state, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculates the current checksum of the game state.
|
||||||
|
* @return The calculated checksum.
|
||||||
|
*/
|
||||||
|
public long calculateChecksum() {
|
||||||
|
return ChecksumCalculator.calculateChecksum(_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks an array of {@link Request}s for validity and automatically applies them if valid.
|
||||||
|
* @param requests The requests to check.
|
||||||
|
* @return Whether or not the given set of requests was valid.
|
||||||
|
*/
|
||||||
|
public boolean checkRequestsAndApply(Request... requests) {
|
||||||
|
if(manager.processRequests(requests, true)) {
|
||||||
|
emit(manager.apply());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks an array of {@link Request}s for validity without applying it.
|
||||||
|
* @param requests The requests to check.
|
||||||
|
* @return Whether or not the given set of requests is valid.
|
||||||
|
*/
|
||||||
|
public boolean checkRequestsSilent(Request... requests) {
|
||||||
|
return manager.processRequests(requests, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies an array of {@link Event}s to the game state.
|
||||||
|
* @param events The events to apply.
|
||||||
|
*/
|
||||||
|
public void applyEvents(Event... events) {
|
||||||
|
manager.applyEvents(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds an {@link Observer} for events.
|
||||||
|
* @param observer The observer to add.
|
||||||
|
*/
|
||||||
|
public void addObserver(Observer observer) {
|
||||||
|
emitter.addObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emits an array of {@link Event}s.
|
||||||
|
* @param events The events to emit.
|
||||||
|
*/
|
||||||
|
private void emit(Event... events) {
|
||||||
|
emitter.notifyObservers(events);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.Tuple;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/** Contains game logic handling.
|
||||||
|
*/
|
||||||
|
class GameLogic {
|
||||||
|
/** Produces resulting {@link Event}s from a given {@link Request} independently of any {@link GameState}.
|
||||||
|
* @return The list of resulting events.
|
||||||
|
*/
|
||||||
|
public static ArrayList<Event> executeRequest(Request request) {
|
||||||
|
ArrayList<Event> result = new ArrayList<Event>();
|
||||||
|
|
||||||
|
//TODO: implement GameLogic.executeRequest
|
||||||
|
|
||||||
|
/* Example Code:
|
||||||
|
switch (event.type) {
|
||||||
|
case EventType.MeleeAttack:
|
||||||
|
result.add(Event.Construct(EventType.APReduced, event.sourceEntity, event.ap));
|
||||||
|
result.add(Event.Construct(EventType.DamageTaken, event.targetEntity, event.value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks a {@link Request} for validity for a {@link GameState}.
|
||||||
|
* @param state The game state to check on.
|
||||||
|
* @param request The request to validate.
|
||||||
|
* @return Whether or not the request is valid
|
||||||
|
*/
|
||||||
|
public static boolean checkRequest(GameState state, Request request) {
|
||||||
|
//TODO: implement GameLogic.checkRequest
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies an {@link Event} to a {@link GameState}.
|
||||||
|
* @param state The game state to apply to.
|
||||||
|
* @param event The event to apply.
|
||||||
|
*/
|
||||||
|
public static void applyEvent(GameState state, Event event) {
|
||||||
|
//TODO: implement GameLogic.applyEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks a {@link GameState} for the current overtime win condition.
|
||||||
|
* @param state The game state to check.
|
||||||
|
* @return The {@link ParticipantType} that is currently winning the game according to overtime ruling.
|
||||||
|
*/
|
||||||
|
public static ParticipantType checkWinConditions(GameState state) {
|
||||||
|
//TODO: GameLogic.checkWinConditions is kind of ugly
|
||||||
|
|
||||||
|
Tuple<ParticipantType, WinCondition> player1;
|
||||||
|
Tuple<ParticipantType, WinCondition> player2;
|
||||||
|
int value1;
|
||||||
|
int value2;
|
||||||
|
for(WinCondition condition: WinCondition.values()) {
|
||||||
|
player1 = new Tuple<ParticipantType, WinCondition>(ParticipantType.Player1, condition);
|
||||||
|
player2 = new Tuple<ParticipantType, WinCondition>(ParticipantType.Player2, 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 ParticipantType.Player1;
|
||||||
|
}
|
||||||
|
if(value2 > value1) {
|
||||||
|
return ParticipantType.Player2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParticipantType.None;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
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.StoneType;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.Tuple;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/** Represents the state of a game instance.
|
||||||
|
*/
|
||||||
|
class GameState {
|
||||||
|
/** The size of the map.
|
||||||
|
*/
|
||||||
|
public final IntVector2 mapSize;
|
||||||
|
|
||||||
|
/** The list of {@link Entity}'s inside the game.
|
||||||
|
*/
|
||||||
|
public ArrayList<Entity> entities;
|
||||||
|
|
||||||
|
/** The total amount of full turn cycles that occurred.
|
||||||
|
*/
|
||||||
|
public int roundNumber = 0;
|
||||||
|
|
||||||
|
/** The turn order of every character.
|
||||||
|
*/
|
||||||
|
public ArrayList<EntityID> turnOrder;
|
||||||
|
|
||||||
|
/** The total amount of turns that occurred.
|
||||||
|
*/
|
||||||
|
public int turnNumber = 0;
|
||||||
|
|
||||||
|
/** The {@link EntityID} of the active character.
|
||||||
|
*/
|
||||||
|
public EntityID activeCharacter;
|
||||||
|
|
||||||
|
/** Whether or not the game was won.
|
||||||
|
*/
|
||||||
|
public boolean won = false;
|
||||||
|
|
||||||
|
/** The global cooldown of every infinity stone.
|
||||||
|
*/
|
||||||
|
public HashMap<StoneType, Float> stoneCooldown;
|
||||||
|
|
||||||
|
/** The store of the {@link WinCondition} data for every win condition for each player.
|
||||||
|
*/
|
||||||
|
public HashMap<Tuple<ParticipantType, WinCondition>, Integer> winConditions;
|
||||||
|
|
||||||
|
/** Constructs a new {@link GameState}.
|
||||||
|
* @param mapSize The size of the map.
|
||||||
|
*/
|
||||||
|
public GameState(IntVector2 mapSize) {
|
||||||
|
this.mapSize = mapSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clones the state into a new {@link GameState} object.
|
||||||
|
* @return The cloned game state.
|
||||||
|
*/
|
||||||
|
public GameState snapshot() {
|
||||||
|
//TODO: implement GameState.snapshot
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/** Represents manager for a game state.
|
||||||
|
*/
|
||||||
|
class GameStateManager {
|
||||||
|
/** The managed {@link GameState}.
|
||||||
|
*/
|
||||||
|
private final GameState state;
|
||||||
|
|
||||||
|
/** The queue of {@link Event}s to be applied during {@link Request} processing.
|
||||||
|
*/
|
||||||
|
private final ArrayDeque<Event> queue = new ArrayDeque<Event>();
|
||||||
|
|
||||||
|
/** Constructs a new {@link GameStateManager}.
|
||||||
|
* @param state A reference to the state to be managed.
|
||||||
|
*/
|
||||||
|
public GameStateManager(GameState state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks a list of {@link Request}s for validity and optionally produces resulting {@link Event}s.
|
||||||
|
* @param requests The requests to check.
|
||||||
|
* @param apply True if resulting events should be stored for later application.
|
||||||
|
*/
|
||||||
|
public boolean processRequests(Request[] requests, boolean apply) {
|
||||||
|
GameState snapshot = state.snapshot();
|
||||||
|
|
||||||
|
for(Request request: requests) {
|
||||||
|
if (GameLogic.checkRequest(snapshot, request)) {
|
||||||
|
ArrayList<Event> result = GameLogic.executeRequest(request);
|
||||||
|
if(apply) {
|
||||||
|
queue.addAll(result);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
queue.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies an array of {@link Event}s to the game state.
|
||||||
|
* @param events The events to apply.
|
||||||
|
*/
|
||||||
|
public void applyEvents(Event[] events) {
|
||||||
|
for(Event event: events) {
|
||||||
|
GameLogic.applyEvent(state, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies the result of the last processRequests call.
|
||||||
|
* @return A list of applied events.
|
||||||
|
*/
|
||||||
|
public Event[] apply() {
|
||||||
|
Event[] toReturn = new Event[queue.size()];
|
||||||
|
Event current;
|
||||||
|
int i = 0;
|
||||||
|
while ((current = queue.poll()) != null) {
|
||||||
|
GameLogic.applyEvent(state, current);
|
||||||
|
toReturn[i++] = current;
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.entities.Entity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/** Represents a game state view containing getters for all the properties of a {@link GameState}.
|
||||||
|
*/
|
||||||
|
public class GameStateView {
|
||||||
|
/** The managed {@link GameState}.
|
||||||
|
*/
|
||||||
|
private final GameState state;
|
||||||
|
|
||||||
|
/** Constructs a new {@link GameStateView}.
|
||||||
|
* @param state A reference to the state to be viewable.
|
||||||
|
*/
|
||||||
|
public GameStateView(GameState state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: add immutable getters for all state properties
|
||||||
|
|
||||||
|
public ArrayList<Entity> getEntities() {
|
||||||
|
return new ArrayList<>(state.entities);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
/** Specifies a participant type.
|
||||||
|
*/
|
||||||
|
public enum ParticipantType {
|
||||||
|
None,
|
||||||
|
Player1,
|
||||||
|
Player2,
|
||||||
|
Spectator
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
/** Specifies a win condition. The order is important here.
|
||||||
|
*/
|
||||||
|
enum WinCondition {
|
||||||
|
/** The maximum amount of total infinity stones the player had at a time.
|
||||||
|
*/
|
||||||
|
MaxStones,
|
||||||
|
/** The total amount of enemy characters the player knocked out.
|
||||||
|
*/
|
||||||
|
TotalKnockouts,
|
||||||
|
/** The total amount of damage the player did to enemy characters.
|
||||||
|
*/
|
||||||
|
TotalDamage
|
||||||
|
}
|
@ -7,6 +7,8 @@ import java.util.HashMap;
|
|||||||
/** Represents a message sent between client and server and contains all possible data.
|
/** Represents a message sent between client and server and contains all possible data.
|
||||||
*/
|
*/
|
||||||
public class MessageStructure {
|
public class MessageStructure {
|
||||||
|
//TODO: revise MessageStructure according to actual standard document
|
||||||
|
|
||||||
/** The list of {@link Event}s sent inside the message.
|
/** The list of {@link Event}s sent inside the message.
|
||||||
*/
|
*/
|
||||||
public Event[] events;
|
public Event[] events;
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.requests;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.json.MessageStructure;
|
||||||
|
|
||||||
|
/** Represents an abstract request sent inside a {@link MessageStructure} between client and server.
|
||||||
|
*/
|
||||||
|
public abstract class Request {
|
||||||
|
//TODO: implement Request
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user