Gamelib/src/test/java/uulm/teamname/marvelous/gamelibrary/gamelogic/GameLogicTest.java

304 lines
12 KiB
Java

package uulm.teamname.marvelous.gamelibrary.gamelogic;
import net.jqwik.api.*;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import uulm.teamname.marvelous.gamelibrary.IntVector2;
import uulm.teamname.marvelous.gamelibrary.config.*;
import uulm.teamname.marvelous.gamelibrary.entities.*;
import uulm.teamname.marvelous.gamelibrary.entities.Character;
import uulm.teamname.marvelous.gamelibrary.requests.*;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
class GameLogicTest extends BaseGameLogicTest {
@BeforeAll
static void setUp() {
generate();
}
@Test
void testGeneration() {
GameInstance game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
game.startGame(player1Selection, player2Selection);
int n = 0;
for(int x = 0; x < scenarioConfig.scenario[0].length; x++) {
for(int y = 0; y < scenarioConfig.scenario.length; y++) {
if(scenarioConfig.scenario[y][x] == FieldType.ROCK) {
ArrayList<Entity> found = game.state.getEntities().findByPosition(new IntVector2(x, y));
assertEquals(1, found.size(), "Rock Entity "+n+" should exist");
assertEquals(EntityType.Rocks, found.get(0).id.type, "Rock Entity "+n+" should be of type Rock");
assertEquals(100, ((Rock)found.get(0)).getHp(), "Rock Entity "+n+" should have 100 HP");
n++;
}
}
}
n = 0;
for(Integer i: player1Selection) {
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P1, n));
assertNotEquals(null, found, "Character Entity "+n+" for Player 1 should exist");
Character c = (Character)found;
assertEquals(characterConfig.characters[i].HP, c.hp.getMax(), "Character "+n+" should have the right amount of HP");
assertEquals(characterConfig.characters[i].MP, c.mp.getMax(), "Character "+n+" should have the right amount of MP");
assertEquals(characterConfig.characters[i].AP, c.ap.getMax(), "Character "+n+" should have the right amount of AP");
assertEquals(characterConfig.characters[i].meleeDamage, c.meleeDamage, "Character "+n+" should have the right amount of meleeDamage");
assertEquals(characterConfig.characters[i].rangedDamage, c.rangedDamage, "Character "+n+" should have the right amount of rangedDamage");
assertEquals(characterConfig.characters[i].attackRange, c.attackRange, "Character "+n+" should have the right amount of attackRange");
n++;
}
n = 0;
for(Integer i: player2Selection) {
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P2, n));
assertNotEquals(null, found, "Character Entity "+n+" for Player 2 should exist");
Character c = (Character)found;
assertEquals(characterConfig.characters[i].HP, c.hp.getMax(), "Character "+n+" should have the right amount of HP");
assertEquals(characterConfig.characters[i].MP, c.mp.getMax(), "Character "+n+" should have the right amount of MP");
assertEquals(characterConfig.characters[i].AP, c.ap.getMax(), "Character "+n+" should have the right amount of AP");
assertEquals(characterConfig.characters[i].meleeDamage, c.meleeDamage, "Character "+n+" should have the right amount of meleeDamage");
assertEquals(characterConfig.characters[i].rangedDamage, c.rangedDamage, "Character "+n+" should have the right amount of rangedDamage");
assertEquals(characterConfig.characters[i].attackRange, c.attackRange, "Character "+n+" should have the right amount of attackRange");
n++;
}
}
@Test
void testSnapshot() {
GameState state = new GameState(partyConfig, characterConfig, scenarioConfig);
state.entities.addEntity(new Rock(new EntityID(EntityType.Rocks, 0), new IntVector2(0, 0), 100));
GameState snapshot = state.snapshot();
snapshot.turnNumber = 10;
assertEquals(0, state.turnNumber, "Original's turn number should remain unchanged");
assertTrue(snapshot.entities.iterator().hasNext(), "Snapshot should contain cloned entities");
((Rock)snapshot.entities.iterator().next()).decreaseHp(5);
assertEquals(100, ((Rock)state.entities.iterator().next()).getHp(), "Original's rock entity hp should remain unchanged");
}
@Test
void testGame() {
GameInstance server = new GameInstance(partyConfig, characterConfig, scenarioConfig);
server.startGame(player1Selection, player2Selection);
System.out.println(server);
}
@Test
void testGamestateEvent() {
GameInstance a = new GameInstance(partyConfig, characterConfig, scenarioConfig);
GameInstance b = new GameInstance(partyConfig, characterConfig, scenarioConfig);
b.applyEvents(a.startGame(player1Selection, player2Selection));
assertEquals(a.toString(), b.toString(), "Second GameInstance copies the state successfully");
}
@Test
void testRasterize() {
ArrayList<IntVector2> result = GameLogic.rasterize(new IntVector2(0, 0), new IntVector2(1, 1), false, false);
assertEquals(0, result.size(), "Diagonals are not included");
IntVector2[] result2 = GameLogic.rasterize(new IntVector2(0, 0), new IntVector2(4, 0)).toArray(new IntVector2[0]);
assertEquals(new HashSet<>(Arrays.asList(
new IntVector2(0, 0), new IntVector2(1, 0), new IntVector2(2, 0), new IntVector2(3, 0), new IntVector2(4, 0)
)), new HashSet<>(Arrays.asList(result2)), "Straight lines work correctly");
IntVector2[] result3 = GameLogic.rasterize(new IntVector2(0, 0), new IntVector2(2, 1)).toArray(new IntVector2[0]);
assertEquals(new HashSet<>(Arrays.asList(
new IntVector2(0, 0), new IntVector2(1, 0), new IntVector2(1, 1), new IntVector2(2, 1))
), new HashSet<>(Arrays.asList(result3)), "Tilted lines work correctly");
}
@Test
void testPathfind() {
int size = 20;
IntVector2 a = new IntVector2(Math.abs(randomIntegers.next() % size), Math.abs(randomIntegers.next() % size));
IntVector2 b = new IntVector2(Math.abs(randomIntegers.next() % size), Math.abs(randomIntegers.next() % size));
ArrayList<IntVector2> result = GameLogic.Bresenham8Connected(a, b);
assertEquals(result.get(0), a, "Start point should be point A");
assertEquals(result.get(result.size() - 1), b, "End point should be point B");
IntVector2 old = a;
for(IntVector2 pos: result) {
if(pos.equals(a)) {
continue;
}
assertEquals(1, old.distanceChebyshev(pos), "Distance between every step should be 1");
old = pos;
}
}
// @Provide("gamestate")
// Arbitrary<GameState> gamestate() {
// var states = Arbitraries.integers()
// .tuple2()
// .map(x -> new IntVector2(x.get1(), x.get2()))
// .map(GameState::new);
// }
// @Provide("entityManager")
// Arbitrary<EntityManager> entityManager() {
// var managers = Arbitraries.of(EntityManager.class);
//
// }
// @Provide("entity")
// Arbitrary<Entity> entity() {
// var entities = Arbitraries.of(Entity.class);
// }
// Characters are kind of hard, but most prequisites are here
// @Provide("character")
// Arbitrary<Character> character() {
// var characters = Combinators.combine(
// anyStat(),
// Arbitraries.integers()
// ).as(x -> new Character());
// }
@Provide("stat")
Arbitrary<Stat> anyStat() {
var stats = Combinators.combine(
Arbitraries.of(StatType.class),
Arbitraries.integers())
.as(Stat::new);
return Combinators.combine(stats, Arbitraries.integers().greaterOrEqual(0))
.as((stat, decrease) -> {
stat.decreaseValue(decrease % (stat.getMax() + 1));
return stat;
});
}
@Provide("entityIDs")
Arbitrary<EntityID> entityIDs() {
return Combinators.combine(
Arbitraries.of(EntityType.class),
Arbitraries.integers()
).as((type, id) -> {
EntityID eid;
switch (type) {
case NPC -> eid = new EntityID(type, id % 3);
case P1, P2, InfinityStones -> eid = new EntityID(type, id % 6);
case Rocks -> eid = new EntityID(type, id);
default -> throw new IllegalStateException("Unexpected value: " + type);
}
return eid;
});
}
@Provide("positions")
Arbitrary<IntVector2> positions() {
return Arbitraries.integers()
.greaterOrEqual(0)
.tuple2()
.map(x -> new IntVector2(x.get1(), x.get2()));
}
@Provide("requests")
Arbitrary<Request> requests() {
return Combinators.combine(
Arbitraries.of(true, false),
gameRequests(),
characterRequests())
.as((which, gameRequest, characterRequest) -> which ? gameRequest : characterRequest);
}
@Provide("gameRequests")
Arbitrary<GameRequest> gameRequests() {
final var gameRequestTypes = List.of(
RequestType.PauseStopRequest,
RequestType.PauseStartRequest,
RequestType.EndRoundRequest,
RequestType.DisconnectRequest,
RequestType.Req);
return Arbitraries.of(RequestType.class)
.filter(gameRequestTypes::contains)
.map(x -> new RequestBuilder(x).buildGameRequest());
}
@Provide("characterRequests")
Arbitrary<CharacterRequest> characterRequests() {
final var characterRequestTypes = List.of(
RequestType.MeleeAttackRequest,
RequestType.RangedAttackRequest,
RequestType.MoveRequest,
RequestType.ExchangeInfinityStoneRequest,
RequestType.UseInfinityStoneRequest);
var positions = Arbitraries.integers()
.greaterOrEqual(0)
.tuple2()
.map(x -> new IntVector2(x.get1(), x.get2()));
var characterIDs = Combinators.combine(Arbitraries.of(true, false)
.map(x -> x ? EntityType.P1 : EntityType.P2),
Arbitraries.integers()
.between(0, 5))
.as(EntityID::new);
var rockIDs = Arbitraries.integers()
.greaterOrEqual(0)
.map(x -> new EntityID(EntityType.Rocks, x));
var targetIDs = Combinators.combine(
Arbitraries.of(true, false),
characterIDs,
rockIDs)
.as((which, characterID, rockID) -> which ? characterID : rockID);
var stoneTypes = Arbitraries.of(StoneType.class);
var values = Arbitraries.integers();
return Combinators.combine(
Arbitraries.of(RequestType.class).filter(characterRequestTypes::contains), // types
positions.tuple2(),
characterIDs,
targetIDs,
stoneTypes,
values
).as((type, pos, characterID, targetID, stoneType, val) -> {
return new RequestBuilder(type)
.withOriginField(pos.get1())
.withTargetField(pos.get2())
.withOriginEntity(characterID)
.withTargetEntity(targetID)
.withStoneType(stoneType)
.withValue(val)
.buildCharacterRequest();
});
}
}