/*******************************************************************************
* Copyright (c) 2015 - 2017
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.logic.map.grid.partition;
import jsettlers.algorithms.partitions.IBlockingProvider;
import jsettlers.common.buildings.EBuildingType;
import jsettlers.common.map.shapes.FreeMapArea;
import jsettlers.common.map.shapes.MapCircle;
import jsettlers.common.material.EMaterialType;
import jsettlers.common.position.ShortPoint2D;
import jsettlers.logic.map.grid.partition.manager.PartitionManager;
import jsettlers.logic.map.grid.partition.manager.materials.offers.EOfferPriority;
import jsettlers.logic.map.grid.partition.manager.materials.offers.MaterialOffer;
import jsettlers.logic.player.PlayerSetting;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class PartitionsGridTest {
private static final short WIDTH = 200;
private static final short HEIGHT = 200;
private final PartitionsGrid grid = new PartitionsGrid(WIDTH, HEIGHT, PlayerSetting.createDefaultSettings((byte) 0, (byte) 10),
IBlockingProvider.DEFAULT_IMPLEMENTATION);
@Test
public void testMergeNoArea() {
short partition1 = grid.createNewPartition((byte) 1);
short partition2 = grid.createNewPartition((byte) 1);
grid.mergePartitions(partition1, partition2);
}
@Test
public void testMergeWithArea() {
short partition1 = grid.createNewPartition((byte) 1);
short partition2 = grid.createNewPartition((byte) 1);
setPartitionInCircle(partition1, 75, 75, 30);
setPartitionInCircle(partition2, 125, 125, 30);
grid.mergePartitions(partition1, partition2);
}
@Test
public void testMergeAndRepresentatives() {
short partitions[] = new short[] { grid.createNewPartition((byte) 1), grid.createNewPartition((byte) 1), grid.createNewPartition((byte) 1),
grid.createNewPartition((byte) 1), grid.createNewPartition((byte) 1) };
grid.mergePartitions(partitions[0], partitions[1]);
grid.mergePartitions(partitions[2], partitions[3]);
grid.mergePartitions(partitions[0], partitions[3]);
grid.mergePartitions(partitions[3], partitions[4]);
for (int i = 0; i < partitions.length - 1; i++) { // all partitions are merged and should have the same representative
assertEquals(grid.partitionObjects[partitions[i]], grid.partitionObjects[partitions[i + 1]]);
}
}
@Test
public void testMergeWithAreaAndGoods() {
short partition1 = grid.createNewPartition((byte) 1);
short partition2 = grid.createNewPartition((byte) 1);
ShortPoint2D materialTestPos = new ShortPoint2D(75, 80);
Partition noPlayerPartition = grid.getPartitionAt(materialTestPos.x, materialTestPos.y);
assertEquals(WIDTH * HEIGHT, noPlayerPartition.getNumberOfElements()); // test if no player partition has all positions
// put material at the test position
noPlayerPartition.addOffer(materialTestPos, EMaterialType.STONE, EOfferPriority.NORMAL);
noPlayerPartition.addOffer(materialTestPos, EMaterialType.STONE, EOfferPriority.NORMAL);
// assert the material is at the test position
assertOfferAt(materialTestPos, EMaterialType.STONE, 2);
// occupy the areas for the both new partitions
int positionsPartition1 = setPartitionInCircle(partition1, 75, 75, 30);
assertEquals(positionsPartition1, grid.getPartitionAt((short) 75, (short) 75).getNumberOfElements());
assertEquals(1, grid.getPartitionAt(materialTestPos.x, materialTestPos.y).getPlayerId());
assertOfferAt(materialTestPos, EMaterialType.STONE, 2); // assert the offer switch to partition1
assertNull(noPlayerPartition.getMaterialOfferAt(materialTestPos, EMaterialType.STONE, EOfferPriority.NORMAL)); // assert the no player
// partition removed the offer
int positionsPartition2 = setPartitionInCircle(partition2, 125, 125, 30);
assertEquals(positionsPartition2, grid.getPartitionAt((short) 125, (short) 125).getNumberOfElements());
// material position must be in partition1
assertEquals(partition1, grid.getPartitionIdAt(materialTestPos.x, materialTestPos.y));
short mergePartition = grid.mergePartitions(partition1, partition2);
assertEquals(mergePartition, grid.getPartitionIdAt(materialTestPos.x, materialTestPos.y));
assertOfferAt(materialTestPos, EMaterialType.STONE, 2);
assertEquals(mergePartition, grid.getPartitionIdAt((short) 75, (short) 75));
assertEquals(mergePartition, grid.getPartitionIdAt((short) 125, (short) 125));
}
@Test
public void testRemoveTower() {
addTower(0, 100, 100, 40);
assertEquals(0, grid.getPlayerIdAt(140, 100));
assertEquals(1, grid.getTowerCountAt(140, 100));
addTower(1, 150, 100, 40);
addTower(1, 155, 110, 40);
assertEquals(0, grid.getPlayerIdAt(140, 100));
assertEquals(1, grid.getTowerCountAt(140, 100));
assertEquals(2, grid.getTowerCountAt(150, 105));
removeTower(100, 100);
assertEquals(1, grid.getPlayerIdAt(140, 100));
assertEquals(2, grid.getTowerCountAt(140, 100));
}
@Test
public void testMergePartition() {
addTower(0, 50, 100, 40);
addTower(0, 150, 100, 40);
// check if the partitions are not connected
assertFalse(grid.getPartitionIdAt(50, 100) == grid.getPartitionIdAt(150, 100));
addTower(0, 100, 100, 40);
// no the partitions should be connected
assertEquals(grid.getPartitionIdAt(50, 100), grid.getPartitionIdAt(150, 100));
assertEquals(grid.getPartitionIdAt(100, 100), grid.getPartitionIdAt(150, 100));
}
@Test
public void testDividePartitionsByNewTower() {
addTower(0, 50, 100, 40);
addTower(0, 150, 100, 40);
// check if the partitions are not connected
assertTrue(grid.getPartitionIdAt(50, 100) != grid.getPartitionIdAt(150, 100));
addTower(0, 100, 100, 40);
// no the partitions should be connected
assertEquals(grid.getPartitionIdAt(50, 100), grid.getPartitionIdAt(150, 100));
assertEquals(grid.getPartitionIdAt(100, 100), grid.getPartitionIdAt(150, 100));
removeTower(100, 100);
// partitions still should be connected
assertEquals(grid.getPartitionIdAt(50, 100), grid.getPartitionIdAt(150, 100));
addTower(1, 100, 100, 40);
// now the partitions should be divided
assertTrue(grid.getPartitionIdAt(50, 100) != grid.getPartitionIdAt(150, 100));
assertCircleIs(getTowerCircle(50, 100, 40), grid.getPartitionIdAt(50, 100));
}
@Test
public void testDividePartitionsByRemovingTower() {
addTower(0, 50, 100, 40);
// add two stones
PartitionManager partition = grid.getPartitionAt(50, 100);
ShortPoint2D materialPos = new ShortPoint2D(75, 100);
partition.addOffer(materialPos, EMaterialType.STONE, EOfferPriority.NORMAL);
partition.addOffer(materialPos, EMaterialType.STONE, EOfferPriority.NORMAL);
addTower(0, 150, 100, 40);
// check if the partitions are not connected
assertTrue(grid.getPartitionIdAt(50, 100) != grid.getPartitionIdAt(150, 100));
addTower(0, 100, 100, 40);
// no the partitions should be connected
assertEquals(grid.getPartitionIdAt(50, 100), grid.getPartitionIdAt(150, 100));
assertEquals(grid.getPartitionIdAt(100, 100), grid.getPartitionIdAt(150, 100));
addTower(1, 75, 55, 42);
addTower(1, 120, 145, 42);
// partitions still should be connected
assertEquals(grid.getPartitionIdAt(50, 100), grid.getPartitionIdAt(150, 100));
removeTower(100, 100);
// now the partitions should be divided
assertTrue(grid.getPartitionIdAt(50, 100) != grid.getPartitionIdAt(150, 100));
assertCircleIs(getTowerCircle(50, 100, 40), grid.getPartitionIdAt(50, 100));
assertCircleIs(getTowerCircle(150, 100, 40), grid.getPartitionIdAt(150, 100));
assertEquals(grid.getPartitionIdAt(75, 55), grid.getPartitionIdAt(120, 145)); // do tower positions equal?
assertEquals(grid.getPartitionIdAt(74, 55), grid.getPartitionIdAt(120, 145)); // do the surroundings equal the tower positions?
assertEquals(grid.getPartitionIdAt(75, 55), grid.getPartitionIdAt(121, 145));
assertOfferAt(materialPos, EMaterialType.STONE, 2);
}
@Test
public void testTakeOverCloseTower() {
addTower(0, 50, 100, 40);
addTower(0, 70, 100, 40);
assertEquals(2, grid.getTowerCountAt(50, 100));
assertEquals(2, grid.getTowerCountAt(70, 100));
short oldPartitionId = grid.getPartitionIdAt(70, 100);
assertEquals(oldPartitionId, grid.getPartitionIdAt(50, 100));
changePlayerOfTower(50, 100, 1);
assertEquals(oldPartitionId, grid.getPartitionIdAt(70, 100));
assertTrue(oldPartitionId != grid.getPartitionIdAt(50, 100));
}
@Test
public void testTowerCount() {
addTower(0, 82, 120, 40);
addTower(0, 75, 85, 40);
addTower(0, 125, 105, 40);
addTower(0, 94, 71, 40);
assertEquals(2, grid.getTowerCountAt(82, 120));
assertEquals(3, grid.getTowerCountAt(75, 85));
assertEquals(2, grid.getTowerCountAt(125, 105));
assertEquals(3, grid.getTowerCountAt(94, 71));
changePlayerOfTower(82, 120, 1);
changePlayerOfTower(75, 85, 1);
changePlayerOfTower(125, 105, 1);
changePlayerOfTower(94, 71, 1);
assertEquals(2, grid.getTowerCountAt(82, 120));
assertEquals(3, grid.getTowerCountAt(75, 85));
assertEquals(2, grid.getTowerCountAt(125, 105));
assertEquals(3, grid.getTowerCountAt(94, 71));
}
private void changePlayerOfTower(int x, int y, int newPlayer) {
ShortPoint2D pos = new ShortPoint2D(x, y);
grid.changePlayerOfTower(pos, (byte) newPlayer);
}
private void assertCircleIs(MapCircle circle, short partition) {
for (ShortPoint2D pos : circle) {
assertEquals(partition, grid.getPartitionIdAt(pos.x, pos.y));
}
}
private void removeTower(int x, int y) {
grid.removeTowerAndFreeOccupiedArea(new ShortPoint2D(x, y));
}
private void addTower(int playerId, int x, int y, int radius) {
grid.addTowerAndOccupyArea((byte) playerId, getTowerCircle(x, y, radius), getGroundArea(new ShortPoint2D(x, y)));
}
private FreeMapArea getGroundArea(ShortPoint2D pos) {
return new FreeMapArea(pos, EBuildingType.TOWER.getProtectedTiles());
}
private MapCircle getTowerCircle(int x, int y, int radius) {
return new MapCircle(new ShortPoint2D(x, y), radius);
}
private void assertOfferAt(ShortPoint2D materialTestPos, EMaterialType material, int amount) {
MaterialOffer offer = grid.getPartitionAt(materialTestPos.x, materialTestPos.y).getMaterialOfferAt(materialTestPos, material,
EOfferPriority.NORMAL);
assertNotNull(offer);
assertEquals(amount, offer.getAmount());
}
private int setPartitionInCircle(short partition, int x, int y, float radius) {
MapCircle circle = new MapCircle(new ShortPoint2D(x, y), radius);
int positions = 0;
for (ShortPoint2D curr : circle) {
grid.changePartitionUncheckedAt(curr.x, curr.y, partition);
positions++;
}
return positions;
}
}