wip: add simple ai and a full game test with ai
This commit is contained in:
parent
0eaa0c5ea1
commit
dce1aed9ad
87
src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java
Normal file
87
src/main/java/uulm/teamname/marvelous/gamelibrary/ai/AI.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.ai;
|
||||||
|
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.ArrayTools;
|
||||||
|
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.EntityID;
|
||||||
|
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.*;
|
||||||
|
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;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class AI {
|
||||||
|
private final GameInstance game;
|
||||||
|
private final EntityType player;
|
||||||
|
|
||||||
|
public AI(EntityType player, PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) {
|
||||||
|
this.game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
Collections.shuffle(options);
|
||||||
|
|
||||||
|
for(IntVector2 dir: options) {
|
||||||
|
IntVector2 target = character.getPosition().add(dir);
|
||||||
|
if(
|
||||||
|
target.getX() < 0 || target.getX() >= game.state.getMapSize().getX() ||
|
||||||
|
target.getY() < 0 || target.getY() >= game.state.getMapSize().getY()
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(game.state.getEntities().findByPosition(target).isEmpty()) {
|
||||||
|
result.add(new RequestBuilder(RequestType.MoveRequest)
|
||||||
|
.withOriginEntity(turn)
|
||||||
|
.withOriginField(character.getPosition())
|
||||||
|
.withTargetField(character.getPosition().add(dir))
|
||||||
|
.buildCharacterRequest());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(new RequestBuilder(RequestType.EndRoundRequest)
|
||||||
|
.buildGameRequest());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.ai.AI;
|
||||||
|
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 AI clientA;
|
||||||
|
private static AI clientB;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setUp() {
|
||||||
|
generate();
|
||||||
|
|
||||||
|
json = new JSON(characterConfig);
|
||||||
|
executor = new SimpleErrorSensitiveThreadPoolExecutor();
|
||||||
|
|
||||||
|
server = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
||||||
|
clientA = new AI(EntityType.P1, partyConfig, characterConfig, scenarioConfig);
|
||||||
|
clientB = new AI(EntityType.P2, partyConfig, characterConfig, scenarioConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void main() throws InterruptedException {
|
||||||
|
serverSend(server.startGame(player1Selection, player2Selection).toArray(new Event[0]));
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
System.out.println(server.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clientSend(Request[] requests) {
|
||||||
|
RequestMessage message = new RequestMessage();
|
||||||
|
message.messages = requests;
|
||||||
|
|
||||||
|
Optional<String> data = json.stringify(message);
|
||||||
|
|
||||||
|
if(data.isPresent()) {
|
||||||
|
executor.submit(() -> serverReceive(data.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clientReceive(String data) {
|
||||||
|
Optional<BasicMessage> message = json.parse(data);
|
||||||
|
|
||||||
|
if(message.isPresent()) {
|
||||||
|
Optional<List<Request>> resultA = clientA.handle(((EventMessage)message.get()).messages);
|
||||||
|
Optional<List<Request>> 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<String> data = json.stringify(message);
|
||||||
|
|
||||||
|
if(data.isPresent()) {
|
||||||
|
executor.submit(() -> clientReceive(data.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serverReceive(String data) {
|
||||||
|
Optional<BasicMessage> message = json.parse(data);
|
||||||
|
|
||||||
|
if(message.isPresent()) {
|
||||||
|
Optional<List<Event>> result = server.checkRequestsAndApply(((RequestMessage)message.get()).messages);
|
||||||
|
|
||||||
|
if(result.isPresent()) {
|
||||||
|
executor.submit(() -> serverSend(result.get().toArray(new Event[0])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user