Commit c2b4493d authored by Fabian Jakob Sauer's avatar Fabian Jakob Sauer

Initial commit.

parents
<component name="libraryTable">
<library name="the-game-f2f-engine">
<CLASSES>
<root url="jar://$PROJECT_DIR$/src/the-game-f2f-engine.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="true" project-jdk-name="openjdk-14" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/TheGameAI.iml" filepath="$PROJECT_DIR$/TheGameAI.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="87772642-515a-4b7b-9523-7ca721ec65cc" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Class" />
</list>
</option>
</component>
<component name="ProjectId" id="1bUWqjD056QjDWVghR0Gtul2HCU" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="project.structure.last.edited" value="Modules" />
<property name="project.structure.proportion" value="0.0" />
<property name="project.structure.side.proportion" value="0.0" />
</component>
<component name="RunManager" selected="Application.main">
<configuration name="TestClass" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="TestClass" />
<module name="TheGameAI" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="main" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="main" />
<module name="TheGameAI" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="the-game-f2f-engine.jar" type="JarApplication" temporary="true">
<option name="JAR_PATH" value="$PROJECT_DIR$/src/the-game-f2f-engine.jar" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Application.main" />
<item itemvalue="JAR Application.the-game-f2f-engine.jar" />
<item itemvalue="Application.TestClass" />
</list>
</recent_temporary>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="87772642-515a-4b7b-9523-7ca721ec65cc" name="Default Changelist" comment="" />
<created>1588687345122</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1588687345122</updated>
</task>
<servers />
</component>
<component name="WindowStateProjectService">
<state x="322" y="93" key="#Project_Structure" timestamp="1588687390551">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="322" y="93" key="#Project_Structure/0.0.1920.1040@0.0.1920.1040" timestamp="1588687390551" />
<state width="1877" height="242" key="GridCell.Tab.0.bottom" timestamp="1588688336055">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="242" key="GridCell.Tab.0.bottom/0.0.1920.1040@0.0.1920.1040" timestamp="1588688336055" />
<state width="1877" height="242" key="GridCell.Tab.0.center" timestamp="1588688336055">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="242" key="GridCell.Tab.0.center/0.0.1920.1040@0.0.1920.1040" timestamp="1588688336055" />
<state width="1877" height="242" key="GridCell.Tab.0.left" timestamp="1588688336055">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="242" key="GridCell.Tab.0.left/0.0.1920.1040@0.0.1920.1040" timestamp="1588688336055" />
<state width="1877" height="242" key="GridCell.Tab.0.right" timestamp="1588688336055">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1877" height="242" key="GridCell.Tab.0.right/0.0.1920.1040@0.0.1920.1040" timestamp="1588688336055" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="the-game-f2f-engine" level="project" />
</component>
</module>
\ No newline at end of file
package de.upb.isml.thegamef2f.engine.player;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import de.upb.isml.thegamef2f.engine.CardPosition;
import de.upb.isml.thegamef2f.engine.GameState;
import de.upb.isml.thegamef2f.engine.Move;
import de.upb.isml.thegamef2f.engine.Placement;
import de.upb.isml.thegamef2f.engine.board.Card;
/**
* This class is an example implementation of an AI based on a random strategy.
* At each turn, the AI constructs a move in the following iterative manner: As
* long as the AI still have hand cards, it generates all valid placements using
* its hand cards and uniformly at random chooses one of these placements. It
* continues this process until it either has no more hand cards or cannot
* generate a valid placement anymore. The resulting list of placements is
* finally converted into a move.
*
* @author Alexander Tornede
*
*/
public class RandomPlayer implements Player {
private Random random;
@Override
public void initialize(long randomSeed) {
this.random = new Random(randomSeed);
}
@Override
public Move computeMove(GameState gameState) {
GameState currentGameState = gameState;
boolean placedOnOpponentsPiles = false;
List<Placement> placementsOfMove = new ArrayList<>();
// as long as we still have hand cards
while (!currentGameState.getHandCards().isEmpty()) {
List<Placement> validPlacements = new ArrayList<>();
// compute all valid placements
for (Card card : currentGameState.getHandCards()) {
for (CardPosition position : CardPosition.values()) {
Placement placement = new Placement(card, position);
if (isPlacementValid(placement, currentGameState, !placedOnOpponentsPiles)) {
validPlacements.add(placement);
}
}
}
// if we cannot find a valid placement anymore, we can stop here and return the
// ones we have so far
if (validPlacements.isEmpty()) {
return new Move(placementsOfMove);
}
// pick a random placement out of the valid ones
Placement randomPlacement = validPlacements.get(random.nextInt(validPlacements.size()));
if (randomPlacement.getPosition() == CardPosition.OPPONENTS_ASCENDING_DISCARD_PILE
|| randomPlacement.getPosition() == CardPosition.OPPONENTS_DESCENDING_DISCARD_PILE) {
placedOnOpponentsPiles = true;
}
// add this random placement to the placements for our move
placementsOfMove.add(randomPlacement);
// update the view we have on the game to make sure that the next set of valid
// placements is indeed valid
currentGameState = computeNewGameStateAfterPlacement(currentGameState, randomPlacement);
}
return new Move(placementsOfMove);
}
private GameState computeNewGameStateAfterPlacement(GameState gameStatePriorToPlacement, Placement placement) {
List<Card> handCards = new ArrayList<>(gameStatePriorToPlacement.getHandCards());
handCards.remove(placement.getCard());
List<Card> cardsOnOwnAscendingDiscardPile = new ArrayList<>(
gameStatePriorToPlacement.getCardsOnOwnAscendingDiscardPile());
if (placement.getPosition() == CardPosition.OWN_ASCENDING_DISCARD_PILE) {
cardsOnOwnAscendingDiscardPile.add(placement.getCard());
}
List<Card> cardsOnOwnDescendingDiscardPile = new ArrayList<>(
gameStatePriorToPlacement.getCardsOnOwnDescendingDiscardPile());
if (placement.getPosition() == CardPosition.OWN_DESCENDING_DISCARD_PILE) {
cardsOnOwnDescendingDiscardPile.add(placement.getCard());
}
List<Card> cardsOnOpponentsAscendingDiscardPile = new ArrayList<>(
gameStatePriorToPlacement.getCardsOnOpponentsAscendingDiscardPile());
if (placement.getPosition() == CardPosition.OPPONENTS_ASCENDING_DISCARD_PILE) {
cardsOnOpponentsAscendingDiscardPile.add(placement.getCard());
}
List<Card> cardsOnOpponentsDescendingDiscardPile = new ArrayList<>(
gameStatePriorToPlacement.getCardsOnOpponentsDescendingDiscardPile());
if (placement.getPosition() == CardPosition.OPPONENTS_ASCENDING_DISCARD_PILE) {
cardsOnOpponentsDescendingDiscardPile.add(placement.getCard());
}
return new GameState(handCards, cardsOnOwnAscendingDiscardPile, cardsOnOwnDescendingDiscardPile,
cardsOnOpponentsAscendingDiscardPile, cardsOnOpponentsDescendingDiscardPile);
}
private boolean isPlacementValid(Placement placement, GameState gameState, boolean placingOnOpponentPilesAllowed) {
switch (placement.getPosition()) {
case OPPONENTS_ASCENDING_DISCARD_PILE:
return placingOnOpponentPilesAllowed
? canPlaceCardOnOpponentsAscendingDiscardPile(placement.getCard(), gameState)
: false;
case OPPONENTS_DESCENDING_DISCARD_PILE:
return placingOnOpponentPilesAllowed
? canPlaceCardOnOpponentsDescendingDiscardPile(placement.getCard(), gameState)
: false;
case OWN_ASCENDING_DISCARD_PILE:
return canPlaceCardOnOwnAscendingDiscardPile(placement.getCard(), gameState);
case OWN_DESCENDING_DISCARD_PILE:
return canPlaceCardOnOwnDescendingDiscardPile(placement.getCard(), gameState);
}
return false;
}
private boolean canPlaceCardOnOwnAscendingDiscardPile(Card card, GameState gameState) {
return gameState.getTopCardOnOwnAscendingDiscardPile().isSmallerThan(card)
|| gameState.getTopCardOnOwnAscendingDiscardPile().is10LargerThan(card);
}
private boolean canPlaceCardOnOwnDescendingDiscardPile(Card card, GameState gameState) {
return card.isSmallerThan(gameState.getTopCardOnOwnDescendingDiscardPile())
|| card.is10LargerThan(gameState.getTopCardOnOwnDescendingDiscardPile());
}
private boolean canPlaceCardOnOpponentsAscendingDiscardPile(Card card, GameState gameState) {
return card.isSmallerThan(gameState.getTopCardOnOpponentsAscendingDiscardPile());
}
private boolean canPlaceCardOnOpponentsDescendingDiscardPile(Card card, GameState gameState) {
return gameState.getTopCardOnOpponentsDescendingDiscardPile().isSmallerThan(card);
}
@Override
public String toString() {
return getName();
}
}
\ No newline at end of file
import de.upb.isml.thegamef2f.engine.board.Game;
import de.upb.isml.thegamef2f.engine.player.Player;
import de.upb.isml.thegamef2f.engine.player.RandomPlayer;
public class main {
public static void main(String[] args) {
Game game = new Game(new RandomPlayer(), new RandomPlayer(), 2147953);
Player winner = game.simulate();
game.getHistory().printHistory();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment