change ActionSpace interface temporarily to quickly fit antWorld test and improve gui of walking ant

This commit is contained in:
Jan Löwenstrom 2019-12-09 13:41:00 +01:00
parent 2fb218a129
commit 8a533dda94
11 changed files with 94 additions and 29 deletions

View File

@ -1,9 +1,9 @@
package core; package core;
import java.util.Set; import java.util.List;
public interface ActionSpace<A extends Enum> { public interface ActionSpace<A extends Enum> {
Set<Action> getAllActions();
int getNumberOfAction(); int getNumberOfAction();
void addAction(DiscreteAction<A> a); void addAction(DiscreteAction<A> a);
void addActions(A[] as);
} }

View File

@ -1,13 +1,13 @@
package core; package core;
import java.util.HashSet; import java.util.ArrayList;
import java.util.Set; import java.util.List;
public class DiscreteActionSpace<A extends Enum> implements ActionSpace<A>{ public class DiscreteActionSpace<A extends Enum> implements ActionSpace<A>{
private Set<Action> actions; private List<DiscreteAction<A>> actions;
public DiscreteActionSpace(){ public DiscreteActionSpace(){
actions = new HashSet<>(); actions = new ArrayList<>();
} }
@Override @Override
@ -15,14 +15,19 @@ public class DiscreteActionSpace<A extends Enum> implements ActionSpace<A>{
actions.add(action); actions.add(action);
} }
@Override
public void addActions(A[] as) {
for(A a : as){
actions.add(new DiscreteAction<>(a));
}
}
@Override @Override
public int getNumberOfAction(){ public int getNumberOfAction(){
return actions.size(); return actions.size();
} }
public List<DiscreteAction<A>> getAllDiscreteActions(){
@Override
public Set<Action> getAllActions(){
return actions; return actions;
} }
} }

View File

@ -58,9 +58,9 @@ public class StateActionHashTable<A extends Enum> implements StateActionTable {
private Map<Action, Double> createDefaultActionValues(){ private Map<Action, Double> createDefaultActionValues(){
final Map<Action, Double> defaultActionValues = new HashMap<>(); final Map<Action, Double> defaultActionValues = new HashMap<>();
for(Action action: actionSpace.getAllActions()){ // for(Action action: actionSpace.getAllActions()){
defaultActionValues.put(action, DEFAULT_VALUE); // defaultActionValues.put(action, DEFAULT_VALUE);
} //}
return defaultActionValues; return defaultActionValues;
} }
} }

View File

@ -11,7 +11,10 @@ import java.awt.*;
@Getter @Getter
@Setter @Setter
public class Ant { public class Ant {
// only set this via .setLocation of Point-class!
@Setter(AccessLevel.NONE)
private Point pos; private Point pos;
private int points;
private boolean spawned; private boolean spawned;
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private boolean hasFood; private boolean hasFood;

View File

@ -3,6 +3,7 @@ package evironment.antGame;
import core.*; import core.*;
import evironment.antGame.gui.MainFrame; import evironment.antGame.gui.MainFrame;
import javax.swing.*;
import java.awt.*; import java.awt.*;
public class AntWorld { public class AntWorld {
@ -37,6 +38,7 @@ public class AntWorld {
public AntWorld(int width, int height, double foodDensity){ public AntWorld(int width, int height, double foodDensity){
grid = new Grid(width, height, foodDensity); grid = new Grid(width, height, foodDensity);
antAgent = new AntAgent(width, height); antAgent = new AntAgent(width, height);
myAnt = new Ant(new Point(-1,-1), 0, false, false);
gui = new MainFrame(this, antAgent); gui = new MainFrame(this, antAgent);
tick = 0; tick = 0;
maxEpisodeTicks = 1000; maxEpisodeTicks = 1000;
@ -60,10 +62,11 @@ public class AntWorld {
if(!myAnt.isSpawned()){ if(!myAnt.isSpawned()){
myAnt.setSpawned(true); myAnt.setSpawned(true);
myAnt.setPos(grid.getStartPoint()); myAnt.getPos().setLocation(grid.getStartPoint());
observation = new AntObservation(grid.getCell(myAnt.getPos()), myAnt.getPos(), myAnt.hasFood()); observation = new AntObservation(grid.getCell(myAnt.getPos()), myAnt.getPos(), myAnt.hasFood());
newState = antAgent.feedObservation(observation); newState = antAgent.feedObservation(observation);
reward = 0.0; reward = 0.0;
++tick;
return new StepResult(newState, reward, false, "Just spawned on the map"); return new StepResult(newState, reward, false, "Just spawned on the map");
} }
@ -120,6 +123,7 @@ public class AntWorld {
reward = Reward.FOOD_DROP_DOWN_FAIL_NOT_START; reward = Reward.FOOD_DROP_DOWN_FAIL_NOT_START;
}else{ }else{
reward = Reward.FOOD_DROP_DOWN_SUCCESS; reward = Reward.FOOD_DROP_DOWN_SUCCESS;
myAnt.setPoints(myAnt.getPoints() + 1);
checkCompletion = true; checkCompletion = true;
} }
} }
@ -141,7 +145,7 @@ public class AntWorld {
// valid movement // valid movement
if(!stayOnCell){ if(!stayOnCell){
myAnt.setPos(potentialNextPos); myAnt.getPos().setLocation(potentialNextPos);
if(antAgent.getCell(myAnt.getPos()).getType() == CellType.UNKNOWN){ if(antAgent.getCell(myAnt.getPos()).getType() == CellType.UNKNOWN){
// the ant will move to a cell that was previously unknown // the ant will move to a cell that was previously unknown
reward = Reward.UNKNOWN_FIELD_EXPLORED; reward = Reward.UNKNOWN_FIELD_EXPLORED;
@ -177,7 +181,10 @@ public class AntWorld {
public void reset() { public void reset() {
RNG.reseed(); RNG.reseed();
grid.initRandomWorld(); grid.initRandomWorld();
myAnt = new Ant(new Point(-1,-1), false, false); myAnt.getPos().setLocation(-1,-1);
myAnt.setPoints(0);
myAnt.setHasFood(false);
myAnt.setSpawned(false);
} }
public void setMaxEpisodeLength(int maxTicks){ public void setMaxEpisodeLength(int maxTicks){
@ -191,19 +198,25 @@ public class AntWorld {
return grid.getGrid(); return grid.getGrid();
} }
public int getTick(){
return tick;
}
public Ant getAnt(){ public Ant getAnt(){
return myAnt; return myAnt;
} }
public static void main(String[] args) { public static void main(String[] args) {
RNG.setSeed(1993); RNG.setSeed(1993);
AntWorld a = new AntWorld(10, 10, 0.1); AntWorld a = new AntWorld(10, 10, 0.1);
System.out.println("ayay"); DiscreteActionSpace<AntAction> actionSpace = new DiscreteActionSpace<>();
a.getGui().repaint(); actionSpace.addActions(AntAction.values());
for(int i = 0; i< 10; ++i){
a.step(new DiscreteAction<>(AntAction.MOVE_RIGHT)); for(int i = 0; i< 1000; ++i){
a.getGui().repaint(); DiscreteAction<AntAction> selectedAction = actionSpace.getAllDiscreteActions().get(RNG.getRandom().nextInt(actionSpace.getNumberOfAction()));
StepResult step = a.step(selectedAction);
SwingUtilities.invokeLater(()-> a.getGui().update(selectedAction.getValue(), step));
try { try {
Thread.sleep(1000); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -4,7 +4,7 @@ public enum CellType {
START, START,
FREE, FREE,
OBSTACLE, OBSTACLE,
FOOD,
UNKNOWN, UNKNOWN,
POSSIBLE_FOOD, POSSIBLE_FOOD,
KNOWN_FOOD,
} }

View File

@ -27,7 +27,7 @@ public class Grid {
for(int x = 0; x < width; ++x){ for(int x = 0; x < width; ++x){
for(int y = 0; y < height; ++y){ for(int y = 0; y < height; ++y){
if( RNG.getRandom().nextDouble() < foodDensity){ if( RNG.getRandom().nextDouble() < foodDensity){
grid[x][y] = new Cell(new Point(x,y), CellType.FOOD, 1); grid[x][y] = new Cell(new Point(x,y), CellType.FREE, 1);
}else{ }else{
grid[x][y] = new Cell(new Point(x,y), CellType.FREE); grid[x][y] = new Cell(new Point(x,y), CellType.FREE);
} }

View File

@ -13,7 +13,6 @@ public class CellColor {
map.put(CellType.FREE, Color.GREEN); map.put(CellType.FREE, Color.GREEN);
map.put(CellType.START, Color.BLUE); map.put(CellType.START, Color.BLUE);
map.put(CellType.UNKNOWN, Color.GRAY); map.put(CellType.UNKNOWN, Color.GRAY);
map.put(CellType.FOOD, Color.YELLOW);
map.put(CellType.OBSTACLE, Color.RED); map.put(CellType.OBSTACLE, Color.RED);
} }
} }

View File

@ -1,5 +1,6 @@
package evironment.antGame.gui; package evironment.antGame.gui;
import evironment.antGame.Ant;
import evironment.antGame.Cell; import evironment.antGame.Cell;
import javax.swing.*; import javax.swing.*;
@ -9,12 +10,12 @@ public class CellsScrollPane extends JScrollPane {
private int cellSize; private int cellSize;
private final int paneWidth = 500; private final int paneWidth = 500;
private final int paneHeight = 500; private final int paneHeight = 500;
private Font font;
public CellsScrollPane(Cell[][] cells, int size){ public CellsScrollPane(Cell[][] cells, Ant ant, int size){
super(); super();
cellSize = size;
setPreferredSize(new Dimension(paneWidth, paneHeight)); setPreferredSize(new Dimension(paneWidth, paneHeight));
cellSize = (paneWidth- cells.length) /cells.length; cellSize = (paneWidth- cells.length) /cells.length;
font = new Font("plain", Font.BOLD, cellSize);
JPanel worldPanel = new JPanel(){ JPanel worldPanel = new JPanel(){
{ {
setPreferredSize(new Dimension(cells.length * cellSize, cells[0].length * cellSize)); setPreferredSize(new Dimension(cells.length * cellSize, cells[0].length * cellSize));
@ -26,6 +27,7 @@ public class CellsScrollPane extends JScrollPane {
}else { }else {
cellSize += 1; cellSize += 1;
} }
font = new Font("plain", Font.BOLD, cellSize);
setPreferredSize(new Dimension(cells.length * cellSize, cells[0].length * cellSize)); setPreferredSize(new Dimension(cells.length * cellSize, cells[0].length * cellSize));
revalidate(); revalidate();
repaint(); repaint();
@ -40,9 +42,19 @@ public class CellsScrollPane extends JScrollPane {
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawRect(i*cellSize, j*cellSize, cellSize, cellSize); g.drawRect(i*cellSize, j*cellSize, cellSize, cellSize);
g.setColor(CellColor.map.get(cells[i][j].getType())); g.setColor(CellColor.map.get(cells[i][j].getType()));
if(cells[i][j].getFood() > 0){
g.setColor(Color.YELLOW);
}
g.fillRect(i*cellSize+1, j*cellSize+1, cellSize -1, cellSize-1); g.fillRect(i*cellSize+1, j*cellSize+1, cellSize -1, cellSize-1);
} }
} }
if(ant.hasFood()){
g.setColor(Color.RED);
}else {
g.setColor(Color.BLACK);
}
g.setFont(font);
g.drawString("A", ant.getPos().x * cellSize, (ant.getPos().y + 1) * cellSize);
} }
}; };
getViewport().add(worldPanel); getViewport().add(worldPanel);

View File

@ -1,9 +1,28 @@
package evironment.antGame.gui; package evironment.antGame.gui;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
public class HistoryPanel extends JPanel { public class HistoryPanel extends JPanel {
private final int panelWidth = 1000;
private final int panelHeight = 300;
private JTextArea textArea;
public HistoryPanel(){ public HistoryPanel(){
setPreferredSize(new Dimension(panelWidth, panelHeight));
textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
JScrollPane scrollBar = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollBar.setPreferredSize(new Dimension(panelWidth, panelHeight));
add(scrollBar);
setVisible(true);
}
public void addText(String toAppend){
textArea.append(toAppend);
textArea.append("\n\n");
revalidate();
} }
} }

View File

@ -1,5 +1,7 @@
package evironment.antGame.gui; package evironment.antGame.gui;
import core.StepResult;
import evironment.antGame.AntAction;
import evironment.antGame.AntAgent; import evironment.antGame.AntAgent;
import evironment.antGame.AntWorld; import evironment.antGame.AntWorld;
@ -7,12 +9,16 @@ import javax.swing.*;
import java.awt.*; import java.awt.*;
public class MainFrame extends JFrame { public class MainFrame extends JFrame {
private AntWorld antWorld;
private HistoryPanel historyPanel;
public MainFrame(AntWorld antWorld, AntAgent antAgent){ public MainFrame(AntWorld antWorld, AntAgent antAgent){
this.antWorld = antWorld;
setLayout(new BorderLayout()); setLayout(new BorderLayout());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
CellsScrollPane worldPane = new CellsScrollPane(antWorld.getCellArray(), 10); CellsScrollPane worldPane = new CellsScrollPane(antWorld.getCellArray(), antWorld.getAnt(), 10);
CellsScrollPane antBrainPane = new CellsScrollPane(antAgent.getKnownWorld(), 10); CellsScrollPane antBrainPane = new CellsScrollPane(antAgent.getKnownWorld(), antWorld.getAnt(), 10);
historyPanel = new HistoryPanel();
JComponent mapComponent = new JPanel(); JComponent mapComponent = new JPanel();
FlowLayout flowLayout = new FlowLayout(); FlowLayout flowLayout = new FlowLayout();
@ -22,7 +28,15 @@ public class MainFrame extends JFrame {
mapComponent.add(antBrainPane); mapComponent.add(antBrainPane);
add(BorderLayout.CENTER, mapComponent); add(BorderLayout.CENTER, mapComponent);
add(BorderLayout.SOUTH, historyPanel);
pack(); pack();
setVisible(true); setVisible(true);
} }
public void update(AntAction lastAction, StepResult stepResult){
historyPanel.addText(String.format("Tick %d: \t Selected action: %s \t Reward: %f \t Info: %s \n totalPoints: %d \t hasFood: %b \t ",
antWorld.getTick(), lastAction.toString(), stepResult.getReward(), stepResult.getInfo(), antWorld.getAnt().getPoints(), antWorld.getAnt().hasFood()));
repaint();
}
} }