// Copyright 1999 Regents of The University of Michigan
// This makes all public classes defined for the simulator package available to this class
import umich.coabs.simulator.*;
import java.awt.*;
/**
This class is a decision maker that controls the single transport
in its entities list. The transport explores the network by
avoiding locations it has already visited and actively searching
for evacuees, stopping at each location to allow evacuees to embark
or disembark. It has a very simple state machine and can get stuck
if one of its actions fails.
@author Brad Clement, bradc@umich.edu
*/
public class SmartestTransportDM extends DecisionMaker {
int state = 0; // the state of the state machine
Location destination; // global variable for keeping track of where
// it wants to go
LinkedList visitedLocations;
/**
Just passes basics up to the costructor of the parent class,
DecisionMaker
*/
public SmartestTransportDM(String i, LinkedList e, Control c) {
super(i, e, c);
visitedLocations = new LinkedList();
}
/**
This is the method that is called on each decision cycle by the
Control object of the simulator. It controls the behavior of the
transport in its entities list. Sometimes the
transports will not successfully move to a location. The results
of these action failures are defined in the Transport class. The
default is nothing changes, and a message is printed.
Additionally, this decision maker often winds up in the wrong
state and gets stuck when an action fails. For example, this can
happen when two transports try to go opposite ways on a one-lane
road or when a transport tries to traverse a route that has been
destroyed.
*/
public void TakeStep() {
ListElement elem, elem1; // for stepping through lists
LinkedList candidates = new LinkedList(); // candidate routes to take
int i, n;
Route r; // the chosen route to traverse
Route tr; // temporary route var
Location tl; // temporary route var
double time = 0.0; // used to wait for a specified time
Transport me = (Transport)entities.head.data; // get the transport at
// the front of the
// entities list
boolean seeEvacs = false; // true when an adjacent location has evacuees
boolean seeSafety = false; // true when an adjacent location is safe
// Take step for state 0
if (state == 0) {
visitedLocations.Add(me.getCurLocation());
// Find candidate routes preferring those to locations with evacuees,
// then safety points when carrying evacuees, then locations never
// visited
for (elem=me.getCurLocation().getRoutes().head; elem!=null;
elem=elem.next) {
tr = (Route)elem.data;
// Get location at end of route
if (tr.getEndpt1() == me.getCurLocation())
tl = tr.getEndpt2();
else
tl = tr.getEndpt1();
// If this is a safety location, and we haven't spotted evacuees
if (!seeEvacs && (tl.getColor() == Color.green)) {
// If this is the first safety location we've spotted, dump current
// candidates and set flag
if (!seeSafety && (me.getEvacuees().size > 0)) {
candidates.Empty();
seeSafety = true;
}
// Add route to safety location to candidates
candidates.Add(tr);
} else
// Not a safety location or we're only looking for evacuees
// If we haven't visited this location before
if (visitedLocations.Find(tl) == null) {
// If there are evacuees there
if (tl.getEvacuees().size > 0) {
// If this is the first time we've spotted evacuees, dump
// current candidates and set flag
if (!seeEvacs) {
candidates.Empty();
seeEvacs = true;
}
// Add route to location with evacuees to candidates
candidates.Add(tr);
}
// Add route if we're only after places we haven't been before
if (!seeEvacs && !seeSafety) candidates.Add(tr);
}
}
if (candidates.size == 0) {
candidates = me.getCurLocation().getRoutes();
}
// Pick a random route to traverse; assign it to r
n = (int) (candidates.size * java.lang.Math.random());
if (n == candidates.size)
--n;
elem = candidates.head;
for (i = 0; i < n; i++)
elem = elem.next;
r = (Route) elem.data;
// Get the location at the other end of the route
if (r.getEndpt1() == me.getCurLocation())
destination = r.getEndpt2();
else
destination = r.getEndpt1();
// Move the transport along the chosen route; additionally destroy
// the route with 0.0 probability
if (java.lang.Math.random() < 1.0)
me.Move(destination, r);
else
me.MoveAndDestroy(destination, r);
// Go to next state
state = 1;
} else
// Take step for state 1
if (state == 1) {
// If transport has arrived at its destination, set a timer to
// wait at the current location to let evacuees embark or disembark
if (me.getCurLocation() == destination) {
time = ctrl.getTime();
state = 2;
}
} else
// Take step for state 2
if (state == 2) {
// If time is up go back to state 0 to move to another location
if (ctrl.getTime() - time >= 4.0)
state = 0;
}
}
}