change ActionSpace interface temporarily to quickly fit antWorld test and improve gui of walking ant
This commit is contained in:
parent
2fb218a129
commit
8a533dda94
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ public enum CellType {
|
||||||
START,
|
START,
|
||||||
FREE,
|
FREE,
|
||||||
OBSTACLE,
|
OBSTACLE,
|
||||||
FOOD,
|
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
POSSIBLE_FOOD,
|
POSSIBLE_FOOD,
|
||||||
|
KNOWN_FOOD,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue