001 package aima.gui.applications; 002 003 import java.awt.Color; 004 import java.util.ArrayList; 005 import java.util.Hashtable; 006 import java.util.List; 007 008 import aima.basic.Agent; 009 import aima.basic.vaccum.*; 010 import aima.gui.framework.AgentAppController; 011 import aima.gui.framework.AgentAppFrame; 012 import aima.gui.framework.AgentAppModel; 013 import aima.gui.framework.AgentView; 014 import aima.gui.framework.SimpleAgentAppDemo; 015 016 /** 017 * Simple graphical application for experiments with vacuum cleaner agents. 018 * It can be used as a template for creating other graphical agent 019 * applications. 020 * @author R. Lunde 021 */ 022 public class VacuumAppDemo extends SimpleAgentAppDemo { 023 024 /** Returns a <code>VacuumModel</code>. */ 025 public AgentAppModel createModel() { 026 return new VacuumModel(); 027 } 028 /** Returns a <code>VacuumFrame</code>. */ 029 public AgentAppFrame createFrame() { 030 return new VacuumFrame(); 031 } 032 /** Returns a <code>VacuumController</code>. */ 033 public AgentAppController createController() { 034 return new VacuumController(); 035 } 036 037 038 ///////////////////////////////////////////////////////////////// 039 // inner classes 040 041 /** 042 * Provides access to the used environment, the names 043 * of the locations (squares) maintained by the environment, and the 044 * current state of all locations. 045 */ 046 protected static class VacuumModel extends AgentAppModel { 047 private TrivialVaccumEnvironment env; 048 private Agent agent; 049 public static String DIRTY = "Dirty"; 050 051 public void setEnv(TrivialVaccumEnvironment env) { this.env = env; } 052 public TrivialVaccumEnvironment getEnv() { return env; } 053 public void setAgent(Agent agent) { this.agent = agent; } 054 public Agent getAgent() { return agent; } 055 056 /** Returns the names of all locations used. */ 057 public List<String> getLocations() { 058 List<String> result = new ArrayList<String>(); 059 if (env != null) { 060 result.add("A"); 061 result.add("B"); 062 } 063 return result; 064 } 065 /** Checks whether the specified location is dirty. */ 066 public boolean isDirty(String location) { 067 return DIRTY.equals(env.getLocationStatus(location)); 068 } 069 /** Checks whether the agent is currently at the specified location. */ 070 public boolean hasAgent(String location) { 071 return agent != null && location.equals(env.getAgentLocation(agent)); 072 } 073 } 074 075 /** 076 * Adds some selectors to the base class and adjusts its size. 077 */ 078 protected static class VacuumFrame extends AgentAppFrame { 079 public static String ENV_SEL = "EnvSelection"; 080 public static String AGENT_SEL = "AgentSelection"; 081 public VacuumFrame() { 082 setAgentView(new VacuumView()); 083 setSelectors( 084 new String[]{ENV_SEL, AGENT_SEL}, 085 new String[]{"Select Environment", "Select Agent"}); 086 setSelectorItems(ENV_SEL, new String[]{"A/B Environment"}, 0); 087 setSelectorItems(AGENT_SEL, new String[]{ 088 "SimpleReflexVaccumAgent", 089 "ReflexVaccumAgent", 090 "ReflexVaccumAgentWithState", 091 "TableDrivenVaccumAgent", 092 "ModelBasedTVEVaccumAgent"}, 0); 093 setTitle("Vacuum Agent Application"); 094 setSize(800, 400); 095 setUpdateDelay(500); 096 } 097 } 098 099 /** 100 * Displays the informations provided by the <code>VacuumModel</code> 101 * on a panel using 2D-graphics. 102 */ 103 protected static class VacuumView extends AgentView { 104 Hashtable<String, int[]> dirtLookup = new Hashtable<String, int[]>(); 105 106 int[] getDirt(String location) { 107 int[] coords = dirtLookup.get(location); 108 if (coords == null) { 109 java.util.Random rand = new java.util.Random(); 110 int size = rand.nextInt(8)+4; 111 coords = new int[2*size]; 112 for (int i = 0; i < size; i++) { 113 coords[2*i] = rand.nextInt(6)+1; 114 coords[2*i+1] = rand.nextInt(8)+1; 115 } 116 } 117 dirtLookup.put(location, coords); 118 return coords; 119 } 120 121 /** 122 * Creates a 2D-graphics showing the agent in its environment. 123 * Locations are represented as rectangles, dirt as grey ovals, 124 * and the agent as red circle. 125 */ 126 public void paint(java.awt.Graphics g) { 127 VacuumModel vmodel = (VacuumModel) model; 128 List<String> locations = vmodel.getLocations(); 129 this.adjustTransformation(0, 0, 11*locations.size()-1, 10); 130 java.awt.Graphics2D g2 = (java.awt.Graphics2D) g; 131 g2.setColor(Color.white); 132 g2.fillRect(0, 0, getWidth(), getHeight()); 133 for (int i = 0; i < locations.size(); i++) { 134 String location = locations.get(i); 135 g2.setColor(Color.black); 136 g2.drawRect(x(11*i), y(0), scale(10), scale(10)); 137 if (vmodel.isDirty(location)) { 138 int[] coords = getDirt(location); 139 for (int j = 0; j < coords.length; j+=2) { 140 g2.setColor(Color.lightGray); 141 g2.fillOval(x(11*i+coords[j]), y(coords[j+1]), scale(3), scale(2)); 142 } 143 } 144 g2.setColor(Color.black); 145 g2.drawString(location, x(11*i)+10, y(0)+20); 146 if (vmodel.hasAgent(location)) { 147 g2.setColor(Color.red); 148 g2.fillOval(x(11*i+2), y(2), scale(6), scale(6)); 149 } 150 } 151 } 152 } 153 154 /** 155 * Defines how to react on user button events. 156 */ 157 protected static class VacuumController extends AgentAppController { 158 /** Does nothing. */ 159 public void clearAgent() { 160 } 161 162 /** 163 * Creates a vacuum agent and a corresponding environment based 164 * on the selection state of the selectors and finally updates 165 * the model. 166 */ 167 public void prepareAgent() { 168 AgentAppFrame.SelectionState selState = frame.getSelection(); 169 TrivialVaccumEnvironment env = null; 170 Agent agent = null; 171 switch(selState.getValue(VacuumFrame.ENV_SEL)) { 172 case 0: env = new TrivialVaccumEnvironment(); break; 173 } 174 switch(selState.getValue(VacuumFrame.AGENT_SEL)) { 175 case 0: agent = new SimpleReflexVaccumAgent(); break; 176 case 1: agent = new ReflexVaccumAgent(); break; 177 case 2: agent = new ReflexVaccumAgentWithState(); break; 178 case 3: agent = new TableDrivenVaccumAgent(); break; 179 case 4: agent = new ModelBasedTVEVaccumAgent(); break; 180 } 181 ((VacuumModel) model).setEnv(env); 182 ((VacuumModel) model).setAgent(agent); 183 if (env != null && agent != null) { 184 env.addAgent(agent); 185 env.registerView(model); 186 frame.modelChanged(); 187 } 188 } 189 190 /** Starts the agent and afterwards updates the status of the frame. */ 191 public void runAgent() { 192 VacuumModel vmodel = (VacuumModel) model; 193 frame.logMessage("<simulation-log>"); 194 vmodel.getEnv().stepUntilDone(); 195 frame.logMessage("Performance: " + 196 vmodel.getEnv().getAgentperformance(vmodel.getAgent())); 197 frame.logMessage("</simulation-log>"); 198 frame.setStatus("Task completed."); 199 } 200 } 201 202 203 ///////////////////////////////////////////////////////////////// 204 // main method 205 206 /** 207 * Starts the application. 208 */ 209 public static void main(String args[]) { 210 new VacuumAppDemo().startApplication(); 211 } 212 }