Skip to content

Commit

Permalink
buggy multi player OneStepLookAhead controller
Browse files Browse the repository at this point in the history
  • Loading branch information
rdgain committed Apr 20, 2016
1 parent a122310 commit 700af4c
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 18 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
classes/
.idea/
examples/.DS_Store
*.class
*.MF
*.jar
src/Test.java
src/Test.java
src/Test.java
src/Test.java
src/Test.java
8 changes: 5 additions & 3 deletions src/TestMultiPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public static void main(String[] args)
//Available controllers:
String doNothingController = "controllers.multiPlayer.doNothing.Agent";
String randomController = "controllers.multiPlayer.sampleRandom.Agent";
String oneStepController = "controllers.multiPlayer.sampleOneStepLookAhead.Agent";

//Available games:
String gamesPath = "examples/2player/";
Expand All @@ -39,9 +40,10 @@ public static void main(String[] args)
// 1. This starts a game, in a level, played by a human.
//ArcadeMachine.playOneGame(game, level1, recordActionsFile, seed);

// 2. This plays a game in a level by the controllers. Separate controllers with a space character. Provide enough as required by the game.
String contrs = doNothingController + " " + doNothingController;
ArcadeMachine.runOneGame(game, level1, visuals, contrs, recordActionsFile, seed, false);
// 2. This plays a game in a level by the controllers. Separate controllers with a space character.
// Provide enough players as required by the game.
String controllers = oneStepController + " " + randomController;
ArcadeMachine.runOneGame(game, level1, visuals, controllers, recordActionsFile, seed, false);

// 3. This replays a game from an action file previously recorded
//String readActionsFile = recordActionsFile;
Expand Down
100 changes: 100 additions & 0 deletions src/controllers/multiPlayer/heuristics/SimpleStateHeuristic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package controllers.multiPlayer.heuristics;

import controllers.Heuristics.StateHeuristic;
import core.game.Observation;
import core.game.StateObservation;
import core.game.StateObservationMulti;
import ontology.Types;
import tools.Vector2d;

import java.util.ArrayList;
import java.util.HashMap;

/**
* Created with IntelliJ IDEA.
* User: ssamot
* Date: 11/02/14
* Time: 15:44
* This is a Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl
*/
public class SimpleStateHeuristic extends StateHeuristicMulti {

double initialNpcCounter = 0;

public SimpleStateHeuristic(StateObservationMulti stateObs) {

}

public double evaluateState(StateObservationMulti stateObs, int playerID) {
Vector2d avatarPosition = stateObs.getAvatarPosition(playerID);
ArrayList<Observation>[] npcPositions = stateObs.getNPCPositions(avatarPosition);
ArrayList<Observation>[] portalPositions = stateObs.getPortalsPositions(avatarPosition);
HashMap<Integer, Integer> resources = stateObs.getAvatarResources(playerID);

ArrayList<Observation>[] npcPositionsNotSorted = stateObs.getNPCPositions();

double won = 0;
Types.WINNER[] winners = stateObs.getMultiGameWinner();
if (winners[playerID] == Types.WINNER.PLAYER_WINS) {
won = 1000000000;
} else if (winners[playerID] == Types.WINNER.PLAYER_LOSES) {
return -999999999;
}


double minDistance = Double.POSITIVE_INFINITY;
Vector2d minObject = null;
int minNPC_ID = -1;
int minNPCType = -1;

int npcCounter = 0;
if (npcPositions != null) {
for (ArrayList<Observation> npcs : npcPositions) {
if(npcs.size() > 0)
{
minObject = npcs.get(0).position; //This is the closest guy
minDistance = npcs.get(0).sqDist; //This is the (square) distance to the closest NPC.
minNPC_ID = npcs.get(0).obsID; //This is the id of the closest NPC.
minNPCType = npcs.get(0).itype; //This is the type of the closest NPC.
npcCounter += npcs.size();
}
}
}

if (portalPositions == null) {

double score = 0;
if (npcCounter == 0) {
score = stateObs.getGameScore(playerID) + won*100000000;
} else {
score = -minDistance / 100.0 + (-npcCounter) * 100.0 + stateObs.getGameScore(playerID) + won*100000000;
}

return score;
}

double minDistancePortal = Double.POSITIVE_INFINITY;
Vector2d minObjectPortal = null;
for (ArrayList<Observation> portals : portalPositions) {
if(portals.size() > 0)
{
minObjectPortal = portals.get(0).position; //This is the closest portal
minDistancePortal = portals.get(0).sqDist; //This is the (square) distance to the closest portal
}
}

double score = 0;
if (minObjectPortal == null) {
score = stateObs.getGameScore() + won*100000000;
}
else {
score = stateObs.getGameScore() + won*1000000 - minDistancePortal * 10.0;
}

return score;
}


}


15 changes: 15 additions & 0 deletions src/controllers/multiPlayer/heuristics/StateHeuristicMulti.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package controllers.multiPlayer.heuristics;

import core.game.StateObservationMulti;

/**
* Created with IntelliJ IDEA.
* User: ssamot
* Date: 11/02/14
* Time: 15:43
* This is a Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl
*/
public abstract class StateHeuristicMulti {

abstract public double evaluateState(StateObservationMulti stateObs, int playerID);
}
41 changes: 41 additions & 0 deletions src/controllers/multiPlayer/heuristics/WinScoreHeuristic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package controllers.multiPlayer.heuristics;

import core.game.StateObservationMulti;
import ontology.Types;

/**
* Created with IntelliJ IDEA.
* User: ssamot
* Date: 11/02/14
* Time: 15:44
* This is a Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl
*/
public class WinScoreHeuristic extends StateHeuristicMulti {

private static final double HUGE_NEGATIVE = -1000.0;
private static final double HUGE_POSITIVE = 1000.0;

double initialNpcCounter = 0;

public WinScoreHeuristic(StateObservationMulti stateObs) {

}

public double evaluateState(StateObservationMulti stateObs, int playerID) {
boolean gameOver = stateObs.isGameOver();
Types.WINNER win = stateObs.getMultiGameWinner()[playerID];
double rawScore = stateObs.getGameScore(playerID);

if(gameOver && win == Types.WINNER.PLAYER_LOSES)
return HUGE_NEGATIVE;

if(gameOver && win == Types.WINNER.PLAYER_WINS)
return HUGE_POSITIVE;

return rawScore;
}


}


70 changes: 70 additions & 0 deletions src/controllers/multiPlayer/sampleOneStepLookAhead/Agent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package controllers.multiPlayer.sampleOneStepLookAhead;


import controllers.multiPlayer.heuristics.SimpleStateHeuristic;
import core.game.StateObservationMulti;
import core.player.AbstractMultiPlayer;
import ontology.Types;
import tools.ElapsedCpuTimer;

import java.util.ArrayList;
import java.util.Random;

/**
* This is a Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl
*/
public class Agent extends AbstractMultiPlayer {
int oppID; //player ID of the opponent

public Agent(StateObservationMulti stateObs, ElapsedCpuTimer elapsedTimer) {}

/**
*
* Very simple one step lookahead agent.
* Pass player ID to all state observation methods to query the right player.
* Omitting the player ID will result in it being set to the default 0 (first player, whichever that is).
*
* @param stateObs Observation of the current state.
* @param elapsedTimer Timer when the action returned is due.
* @return An action for the current state
*/
public Types.ACTIONS act(StateObservationMulti stateObs, ElapsedCpuTimer elapsedTimer) {

Types.ACTIONS bestAction = null;
double maxQ = Double.NEGATIVE_INFINITY;

int no_players = stateObs.getNoPlayers();
int id = getPlayerID(); //player ID of this agent
oppID = (getPlayerID() + 1) % stateObs.getNoPlayers();

SimpleStateHeuristic heuristic = new SimpleStateHeuristic(stateObs);

for (Types.ACTIONS action : stateObs.getAvailableActions(id)) {

StateObservationMulti stCopy = stateObs.copy();

//need to provide actions for all players to advance the forward model
Types.ACTIONS[] acts = new Types.ACTIONS[no_players];

//set this agent's action
acts[id] = action;

//get actions available to the opponent and assume they will do a random action
ArrayList<Types.ACTIONS> oppActions = stateObs.getAvailableActions(oppID);
acts[oppID] = oppActions.get(new Random().nextInt(oppActions.size()));

stCopy.advance(acts);
double Q = heuristic.evaluateState(stCopy, id);

//System.out.println("Action:" + action + " score:" + Q);
if (Q > maxQ) {
maxQ = Q;
bestAction = action;
}
}

//System.out.println("====================");
//System.out.println("Action:" + bestAction);
return bestAction;
}
}
3 changes: 0 additions & 3 deletions src/core/ArcadeMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import ontology.avatar.MovingAvatar;
import tools.ElapsedCpuTimer;
import tools.IO;
import tools.KeyHandler;
import tools.StatSummary;

/**
Expand Down Expand Up @@ -530,7 +529,6 @@ public static void runGames(String game_file, String[] level_files, int level_ti
scores.add(score);
victories.add(toPlay.getWinner()== Types.WINNER.PLAYER_WINS ? 1 : 0);

scores.add(score);
for (MovingAvatar a : toPlay.getAvatars()) {
if (a.getWinState() == Types.WINNER.PLAYER_WINS)
scores.addWin();
Expand Down Expand Up @@ -777,7 +775,6 @@ protected static Player createController(String playerName, int playerID, StateO

player = (AbstractMultiPlayer) controllerArgsConstructor.newInstance(constructorArgs);
player.setPlayerID(playerID);

}
//Check if we returned on time, and act in consequence.
long timeTaken = ect.elapsedMillis();
Expand Down
16 changes: 4 additions & 12 deletions src/core/game/ForwardModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,10 @@ final public void update(Game a_gameState)
shieldedEffects = new ArrayList[numSpriteTypes];

//Copy array of avatars from the game.
this.avatars = new MovingAvatar[no_players];
//for (int i = 0; i < no_players; i++) {
// this.avatars[i] = (MovingAvatar) a_gameState.avatars[i].copy();
//}
System.arraycopy(a_gameState.avatars, 0, this.avatars, 0, no_players);
/*this.avatars = new MovingAvatar[no_players];
for (int i = 0; i < no_players; i++) {
this.avatars[i] = (MovingAvatar) a_gameState.avatars[i].copy();
}*/

//Copy of sprites from the game.
spriteGroups = new SpriteGroup[numSpriteTypes];
Expand Down Expand Up @@ -461,13 +460,6 @@ private void initNonVolatile(Game a_gameState)
this.avatarLastAction = new Types.ACTIONS[no_players];
System.arraycopy(a_gameState.avatarLastAction, 0, avatarLastAction, 0, no_players);

//Copy array of avatars from the game.
this.avatars = new MovingAvatar[no_players];
//for (int i = 0; i < no_players; i++) {
// this.avatars[i] = (MovingAvatar) a_gameState.avatars[i].copy();
//}
System.arraycopy(a_gameState.avatars, 0, avatars, 0, no_players);

//create the boolean maps of sprite types.
npcList = new boolean[a_gameState.spriteGroups.length];
immList = new boolean[a_gameState.spriteGroups.length];
Expand Down
5 changes: 5 additions & 0 deletions src/core/game/StateObservationMulti.java
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ public Types.ACTIONS getAvatarLastAction(int playerID)
*/
public int getAvatarLimitHealthPoints(int playerID) {return model.getAvatarLimitHealthPoints(playerID);}

public StateObservationMulti copy() {
StateObservationMulti copyObs = new StateObservationMulti(model.copy());
return copyObs;
}

/**
* Method overwritten with multi player optimisations.
* @param o Object to compare this to.
Expand Down

0 comments on commit 700af4c

Please sign in to comment.