refactor: split ai into client and "brain"
This commit is contained in:
parent
2cbd86b725
commit
aa1d2c48df
@ -2,61 +2,40 @@ package uulm.teamname.marvelous.gamelibrary.ai;
|
|||||||
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.ArrayTools;
|
import uulm.teamname.marvelous.gamelibrary.ArrayTools;
|
||||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||||
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.Character;
|
||||||
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.events.Event;
|
import uulm.teamname.marvelous.gamelibrary.gamelogic.GameStateView;
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.EventType;
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.gamelogic.*;
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||||
import uulm.teamname.marvelous.gamelibrary.requests.RequestBuilder;
|
import uulm.teamname.marvelous.gamelibrary.requests.RequestBuilder;
|
||||||
import uulm.teamname.marvelous.gamelibrary.requests.RequestType;
|
import uulm.teamname.marvelous.gamelibrary.requests.RequestType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class AI {
|
/** Represents an AI instance for calculations. */
|
||||||
private final GameInstance game;
|
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;
|
private final EntityType player;
|
||||||
|
|
||||||
public AI(EntityType player, PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) {
|
/** Constructs a new {@link AI} playing the given player based on the given config values. */
|
||||||
this.game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
public AI(GameStateView state, EntityType player) {
|
||||||
|
this.state = state;
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<List<Request>> handle(Event... events) {
|
/**
|
||||||
|
* 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<Request> performTurn(EntityID turn) {
|
||||||
ArrayList<Request> result = new ArrayList<>();
|
ArrayList<Request> result = new ArrayList<>();
|
||||||
|
|
||||||
game.applyEvents(events);
|
Character character = (Character)state.getEntities().findEntity(turn);
|
||||||
|
|
||||||
boolean containsTurn = false;
|
|
||||||
for(Event event: events) {
|
|
||||||
if(event.type == EventType.TurnEvent) {
|
|
||||||
containsTurn = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(containsTurn && game.state.getActiveCharacter() != null && game.state.getActiveCharacter().type == player) {
|
|
||||||
result.addAll(handleTurn(game.state.getActiveCharacter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!result.isEmpty()) {
|
|
||||||
return Optional.of(result);
|
|
||||||
}else {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ArrayList<Request> handleTurn(EntityID turn) {
|
|
||||||
ArrayList<Request> result = new ArrayList<>();
|
|
||||||
|
|
||||||
Character character = (Character)game.state.getEntities().findEntity(turn);
|
|
||||||
|
|
||||||
ArrayList<IntVector2> options = ArrayTools.toArrayList(IntVector2.CardinalDirections.clone());
|
ArrayList<IntVector2> options = ArrayTools.toArrayList(IntVector2.CardinalDirections.clone());
|
||||||
Collections.shuffle(options);
|
Collections.shuffle(options);
|
||||||
@ -64,12 +43,12 @@ public class AI {
|
|||||||
for(IntVector2 dir: options) {
|
for(IntVector2 dir: options) {
|
||||||
IntVector2 target = character.getPosition().add(dir);
|
IntVector2 target = character.getPosition().add(dir);
|
||||||
if(
|
if(
|
||||||
target.getX() < 0 || target.getX() >= game.state.getMapSize().getX() ||
|
target.getX() < 0 || target.getX() >= state.getMapSize().getX() ||
|
||||||
target.getY() < 0 || target.getY() >= game.state.getMapSize().getY()
|
target.getY() < 0 || target.getY() >= state.getMapSize().getY()
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(game.state.getEntities().findByPosition(target).isEmpty()) {
|
if(state.getEntities().findByPosition(target).isEmpty()) {
|
||||||
result.add(new RequestBuilder(RequestType.MoveRequest)
|
result.add(new RequestBuilder(RequestType.MoveRequest)
|
||||||
.withOriginEntity(turn)
|
.withOriginEntity(turn)
|
||||||
.withOriginField(character.getPosition())
|
.withOriginField(character.getPosition())
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<List<Request>> handle(Event... events) {
|
||||||
|
ArrayList<Request> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@ package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import uulm.teamname.marvelous.gamelibrary.ai.AI;
|
import uulm.teamname.marvelous.gamelibrary.ai.AIClient;
|
||||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
|
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.JSON;
|
import uulm.teamname.marvelous.gamelibrary.json.JSON;
|
||||||
@ -20,8 +20,8 @@ class AITest extends BaseGameLogicTest {
|
|||||||
private static ExecutorService executor;
|
private static ExecutorService executor;
|
||||||
|
|
||||||
private static GameInstance server;
|
private static GameInstance server;
|
||||||
private static AI clientA;
|
private static AIClient clientA;
|
||||||
private static AI clientB;
|
private static AIClient clientB;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void setUp() {
|
static void setUp() {
|
||||||
@ -31,8 +31,8 @@ class AITest extends BaseGameLogicTest {
|
|||||||
executor = new SimpleErrorSensitiveThreadPoolExecutor();
|
executor = new SimpleErrorSensitiveThreadPoolExecutor();
|
||||||
|
|
||||||
server = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
server = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
||||||
clientA = new AI(EntityType.P1, partyConfig, characterConfig, scenarioConfig);
|
clientA = new AIClient(EntityType.P1, partyConfig, characterConfig, scenarioConfig);
|
||||||
clientB = new AI(EntityType.P2, partyConfig, characterConfig, scenarioConfig);
|
clientB = new AIClient(EntityType.P2, partyConfig, characterConfig, scenarioConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user