Skip to content

Commit

Permalink
haveResources w/testing and checkAIPlayer
Browse files Browse the repository at this point in the history
Adding haveResources and checkAIPlayer to RulesAttachment. Included is RulesAttachmentTest which uses "VICTORY_TEST" to test haveResources. checkAIPlayer is not tested because of internal testing for boolean values.

Cheers...
  • Loading branch information
WCSumpton committed Sep 18, 2023
1 parent f072c15 commit 763b7a8
Show file tree
Hide file tree
Showing 2 changed files with 274 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.annotations.VisibleForTesting;
import games.strategy.engine.data.Attachable;
import games.strategy.engine.data.BattleRecordsList;
import games.strategy.engine.data.GameData;
Expand All @@ -13,6 +14,7 @@
import games.strategy.engine.data.MutableProperty;
import games.strategy.engine.data.RelationshipTracker.Relationship;
import games.strategy.engine.data.RelationshipType;
import games.strategy.engine.data.Resource;
import games.strategy.engine.data.TechnologyFrontier;
import games.strategy.engine.data.Territory;
import games.strategy.engine.data.Unit;
Expand Down Expand Up @@ -55,9 +57,13 @@ public class RulesAttachment extends AbstractPlayerRulesAttachment {
private int techCount = -1;
// condition for having specific relationships
private @Nullable List<String> relationship = null;
// condition for checking ai player
private boolean checkAIPlayer = false;
// condition for being at war
private @Nullable Set<GamePlayer> atWarPlayers = null;
private int atWarCount = -1;
// condition for checking resources
private @Nullable String[] haveResources = null;
// condition for having destroyed at least X enemy non-neutral TUV (total unit value) [according
// to
// the prices the defender pays for the units]
Expand Down Expand Up @@ -145,6 +151,50 @@ public static Set<RulesAttachment> getNationalObjectives(final GamePlayer player
return natObjs;
}

@VisibleForTesting
public void setHaveResources(final String value) throws GameParseException {
final String[] s = splitOnColon(value);
if (s.length <= 1) {
throw new GameParseException(
"haveResources must have at least 2 fields. Format value=resource1 count=number, or "
+ "value=resource1:resource2:resource3 count=number"
+ thisErrorMsg());
}
if ((s.length <= 2) && (s[1].equalsIgnoreCase("sum") || s[1].equalsIgnoreCase("add"))) {
throw new GameParseException(
"haveResources must have at least 3 fields when used with 'Sum' or 'Add'. Format value=Sum:resource1 "
+ "count=number, or value=Sum:resource1:resource2:resource3 count=number"
+ thisErrorMsg());
}
final int n = getInt(s[0]);
if (n < 1) {
throw new GameParseException("haveResources must be a positive integer" + thisErrorMsg());
}
for (int i = 1;i < s.length; i++) {
if (s[i].equalsIgnoreCase("sum") || s[i].equalsIgnoreCase("add")) {
i++;
}
// validate that this resource exists in the xml
final Resource r = getData().getResourceList().getResource(s[i]);
if (r == null) {
throw new GameParseException("No resource called: " + s[i] + thisErrorMsg());
}
}
haveResources = s;
}

private void setHaveResources(final String[] value) {
haveResources = value;
}

public String[] getHaveResources() {
return haveResources;
}

private void resetHaveResources() {
haveResources = null;
}

private void setDestroyedTuv(final String value) throws GameParseException {
final String[] s = splitOnColon(value);
if (s.length != 2) {
Expand Down Expand Up @@ -489,6 +539,22 @@ private void resetUnitPresence() {
unitPresence = null;
}

private void setCheckAIPlayer(final String s) {
checkAIPlayer = getBool(s);
}

private void setCheckAIPlayer(final Boolean s) {
checkAIPlayer = s;
}

public boolean getCheckAIPlayer() {
return checkAIPlayer;
}

private void resetCheckAIPlayer() {
checkAIPlayer = false;
}

private int getAtWarCount() {
return atWarCount;
}
Expand Down Expand Up @@ -735,11 +801,21 @@ public boolean isSatisfied(
}
objectiveMet = checkDirectOwnership(listedTerritories, players);
}
// check for ai controlled player
if (objectiveMet && getCheckAIPlayer()) {
objectiveMet = checkCheckAIPlayer(players);
}
// check for resources
if (objectiveMet && haveResources != null) {
objectiveMet = checkHaveResources(players);
}
// get attached to player
final GamePlayer playerAttachedTo = (GamePlayer) getAttachedTo();
// check for players at war
if (objectiveMet && !getAtWarPlayers().isEmpty()) {
objectiveMet = checkAtWar(playerAttachedTo, getAtWarPlayers(), getAtWarCount());
}
// check for techs
if (objectiveMet && !getTechs().isEmpty()) {
objectiveMet = checkTechs(playerAttachedTo, data.getTechnologyFrontier());
}
Expand Down Expand Up @@ -1001,6 +1077,14 @@ private boolean matchTerritories(
return numberMet >= getTerritoryCount();
}

private boolean checkCheckAIPlayer(final List<GamePlayer> players) {
boolean bcheck = true;
for (GamePlayer player : players) {
bcheck = (bcheck && player.isAi());
}
return bcheck;
}

private boolean checkAtWar(
final GamePlayer player, final Set<GamePlayer> enemies, final int count) {
int found = CollectionUtils.countMatches(enemies, player::isAtWar);
Expand Down Expand Up @@ -1031,6 +1115,21 @@ private boolean checkTechs(final GamePlayer player, final TechnologyFrontier tec
return found >= techCount;
}

@VisibleForTesting
public boolean checkHaveResources(final List<GamePlayer> players) {
final boolean toSum =
haveResources[1].equalsIgnoreCase("sum") || haveResources[1].equalsIgnoreCase("add");
int itotal = 0;
for (GamePlayer player : players) {
for (int i = toSum ? 2 : 1; i < haveResources.length; i++) {
final Resource resource = getData().getResourceList().getResource(haveResources[i]);
int iamount = player.getResources().getQuantity(resource);
itotal = toSum ? itotal + iamount : Math.max(itotal, iamount);
}
}
return itotal >= getInt(haveResources[0]);
}

@Override
public void validate(final GameState data) {
validateNames(alliedOwnershipTerritories);
Expand All @@ -1057,6 +1156,12 @@ public MutableProperty<?> getPropertyOrNull(String propertyName) {
this::setRelationship,
this::getRelationship,
this::resetRelationship);
case "checkAIPlayer":
return MutableProperty.of(
this::setCheckAIPlayer,
this::setCheckAIPlayer,
this::getCheckAIPlayer,
this::resetCheckAIPlayer);
case "atWarPlayers":
return MutableProperty.of(
this::setAtWarPlayers,
Expand All @@ -1065,6 +1170,12 @@ public MutableProperty<?> getPropertyOrNull(String propertyName) {
this::resetAtWarPlayers);
case "atWarCount":
return MutableProperty.ofReadOnly(this::getAtWarCount);
case "haveResources":
return MutableProperty.of(
this::setHaveResources,
this::setHaveResources,
this::getHaveResources,
this::resetHaveResources);
case "destroyedTUV":
return MutableProperty.ofString(
this::setDestroyedTuv, this::getDestroyedTuv, this::resetDestroyedTuv);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package games.strategy.triplea.attachments;

import static games.strategy.triplea.Constants.PUS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import games.strategy.engine.data.GameData;
import games.strategy.engine.data.GamePlayer;
import games.strategy.engine.data.gameparser.GameParseException;
import java.security.SecureRandom;
import java.util.List;

import games.strategy.triplea.delegate.GameDataTestUtil;
import games.strategy.triplea.xml.TestMapGameData;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class RulesAttachmentTest {

/**
* "Victory" map is just a branch/mod of Pact of Steel 2. POS2 is an actual game with good gameplay
* that we don't want to mess with, so "Victory" is more of an xml purely for testing purposes, and
* probably should never be played.
*/
private final GameData gameData = TestMapGameData.VICTORY_TEST.getGameData();
private final RulesAttachment attachment = new RulesAttachment("Test attachment", null, gameData);

@Nested
class HaveResources {

private final GamePlayer italians = GameDataTestUtil.italians(gameData);
private final GamePlayer germans = GameDataTestUtil.germans(gameData);
private final String FUEL = "Fuel";
private final String ORE = "Ore";
private final String addString = "add";
private final String sumString ="SUM";

/* Length test for haveResources */
@Test
void setHaveResourcesInvalidLength() {
assertThrows(GameParseException.class, () -> attachment.setHaveResources(""));
assertThrows(GameParseException.class, () -> attachment.setHaveResources(":add"));

assertThrows(GameParseException.class, () -> attachment.setHaveResources("a"));
assertThrows(GameParseException.class, () -> attachment.setHaveResources("a:add"));
}

/* Invalid arguments for haveResources */
@Test
void setHaveResourcesInvalidArgs() {
/* Not a number (NAN) test */
assertThrows(
IllegalArgumentException.class,
() -> attachment.setHaveResources("NAN:PUs"));
assertThrows(
IllegalArgumentException.class,
() -> attachment.setHaveResources("NAN:add:PUs"));
/* -1 value test */
assertThrows(
GameParseException.class,
() -> attachment.setHaveResources("0:PUs"));
assertThrows(
GameParseException.class,
() -> attachment.setHaveResources("0:add:PUs"));
/* Not a resource test */
assertThrows(
GameParseException.class,
() -> attachment.setHaveResources("1:NOT A RESOURCE"));
assertThrows(
GameParseException.class,
() -> attachment.setHaveResources("1:Sum:NOT A RESOURCE"));
assertThrows(
GameParseException.class, () -> attachment.setHaveResources("0:w"));
assertThrows(
GameParseException.class, () -> attachment.setHaveResources("0:w:e"));
assertThrows(
GameParseException.class, () -> attachment.setHaveResources("0:add:w"));
assertThrows(
GameParseException.class, () -> attachment.setHaveResources("0:add:w:e"));
}

/* Testing stored values with getHaveResources */
@Test
void setHaveResourcesTest() throws Exception {
final SecureRandom rand = new SecureRandom();
final String random1 = Integer.toString(Math.abs(rand.nextInt()));
final String[] expected1 = new String[] {random1, PUS};

attachment.setHaveResources(
concatWithColon(random1, addString, PUS));
assertEquals(
expected1[0],
attachment.getHaveResources()[0]);
assertEquals(
expected1[1],
attachment.getHaveResources()[2]);
}

/* Testing checkHaveResources */
@Test
void testCheckHaveResources() throws Exception {
final int italianFuelAmount = italians.getResources().getQuantity(FUEL);
final int italianPuAmount = italians.getResources().getQuantity(PUS);
final int italianOreAmount = italians.getResources().getQuantity(ORE);
final int germanFuelAmount = germans.getResources().getQuantity(FUEL);
final int germanPuAmount = germans.getResources().getQuantity(PUS);
final int germanOreAmount = germans.getResources().getQuantity(ORE);

final int testItalianPU = italianPuAmount;
final int testItalianResources = italianOreAmount + italianFuelAmount + italianPuAmount;
final int testPUs = testItalianPU + germanPuAmount;
final int testResources = testItalianResources + germanPuAmount + germanFuelAmount + germanOreAmount;

/* testing with 1 player */
final List<GamePlayer> players = List.of(italians);
attachment.setHaveResources(
concatWithColon(String.valueOf(testItalianPU), PUS));
assertTrue(
attachment.checkHaveResources(players));
attachment.setHaveResources(
concatWithColon(String.valueOf(testItalianResources), addString, PUS));
assertFalse(
attachment.checkHaveResources(players));
attachment.setHaveResources(
concatWithColon(String.valueOf(testItalianResources), addString, PUS, FUEL));
assertFalse(
attachment.checkHaveResources(players));
attachment.setHaveResources(
concatWithColon(String.valueOf(testItalianResources), addString, PUS, FUEL, ORE));
assertTrue(
attachment.checkHaveResources(players));

/* testing with 2 players */
final List<GamePlayer> players1 = List.of(italians, germans);
attachment.setHaveResources(
concatWithColon(String.valueOf(testPUs), sumString, PUS));
assertTrue(
attachment.checkHaveResources(players1));
attachment.setHaveResources(
concatWithColon(String.valueOf(testResources), sumString, PUS));
assertFalse(
attachment.checkHaveResources(players1));
attachment.setHaveResources(
concatWithColon(String.valueOf(testResources), sumString, PUS, FUEL));
assertFalse(
attachment.checkHaveResources(players1));
attachment.setHaveResources(
concatWithColon(String.valueOf(testResources), sumString, PUS, FUEL, ORE));
assertTrue(
attachment.checkHaveResources(players1));

}
@Test
private String concatWithColon(final String... args) {
return String.join(":", args);
}
}
}

0 comments on commit 763b7a8

Please sign in to comment.