Unverified Commit 342fea6f authored by Juon Kawakami's avatar Juon Kawakami 🥗
Browse files

init

parent 54f6cedf
/*
* Last change: $Date: 2004/05/20 23:42:00 $
* $Revision: 1.7 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.objects;
import rescuecore.*;
public abstract class Vertex extends MotionlessObject {
protected IntProperty x,y;
protected ArrayProperty edges;
protected Vertex() {
x = new IntProperty(RescueConstants.PROPERTY_X);
y = new IntProperty(RescueConstants.PROPERTY_Y);
edges = new ArrayProperty(RescueConstants.PROPERTY_EDGES);
}
protected Vertex(int x, int y, int[] edges) {
this.x = new IntProperty(RescueConstants.PROPERTY_X,x);
this.y = new IntProperty(RescueConstants.PROPERTY_Y,y);
this.edges = new ArrayProperty(RescueConstants.PROPERTY_EDGES,edges);
}
public Property getProperty(int property) /*throws UnknownPropertyException*/ {
switch (property) {
case RescueConstants.PROPERTY_X:
return x;
case RescueConstants.PROPERTY_Y:
return y;
case RescueConstants.PROPERTY_EDGES:
return edges;
}
return super.getProperty(property);
}
/*
public boolean propertyExists(int property) {
switch (property) {
case RescueConstants.PROPERTY_X:
case RescueConstants.PROPERTY_Y:
case RescueConstants.PROPERTY_EDGES:
return true;
}
return super.propertyExists(property);
}
*/
public int getX() {
return x.getValue();
}
public boolean setX(int newX, int timestamp, Object source) {
if (x.updateValue(newX,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_X,timestamp,source);
return true;
}
return false;
}
public int getY() {
return y.getValue();
}
public boolean setY(int newY, int timestamp, Object source) {
if (y.updateValue(newY,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_Y,timestamp,source);
return true;
}
return false;
}
public int[] getEdges() {
return edges.getValues();
}
public boolean setEdges(int[] newEdges, int timestamp, Object source) {
if (edges.updateValues(newEdges,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_EDGES,timestamp,source);
return true;
}
return false;
}
public void appendEdge(int next, int timestamp, Object source) {
edges.append(next);
firePropertyChanged(RescueConstants.PROPERTY_EDGES,timestamp,source);
}
public void clearEdges(int timestamp, Object source) {
edges.clear();
firePropertyChanged(RescueConstants.PROPERTY_EDGES,timestamp,source);
}
}
/*
* Last change: $Date: 2004/05/20 23:42:00 $
* $Revision: 1.7 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.objects;
import rescuecore.*;
public abstract class VirtualObject extends RescueObject {
protected VirtualObject() {
super();
}
// public boolean propertyExists(int property) {
// return super.propertyExists(property);
// }
public Property getProperty(int property) /*throws UnknownPropertyException*/ {
return super.getProperty(property);
}
}
/*
* Last change: $Date: 2004/05/20 23:42:00 $
* $Revision: 1.7 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.objects;
import rescuecore.*;
/**
Encapsulation of a TYPE_WORLD object
@see RescueConstants#TYPE_WORLD
*/
public class World extends VirtualObject {
private IntProperty startTime, longitude, latitude, windForce, windDirection;
public World() {
startTime = new IntProperty(RescueConstants.PROPERTY_START_TIME);
longitude = new IntProperty(RescueConstants.PROPERTY_LONGITUDE);
latitude = new IntProperty(RescueConstants.PROPERTY_LATITUDE);
windForce = new IntProperty(RescueConstants.PROPERTY_WIND_FORCE);
windDirection = new IntProperty(RescueConstants.PROPERTY_WIND_DIRECTION);
}
public World(int start, int lon, int lat, int force, int direction) {
startTime = new IntProperty(RescueConstants.PROPERTY_START_TIME,start);
longitude = new IntProperty(RescueConstants.PROPERTY_LONGITUDE,lon);
latitude = new IntProperty(RescueConstants.PROPERTY_LATITUDE,lat);
windForce = new IntProperty(RescueConstants.PROPERTY_WIND_FORCE,force);
windDirection = new IntProperty(RescueConstants.PROPERTY_WIND_DIRECTION,direction);
}
public int getType() {
return RescueConstants.TYPE_WORLD;
}
/*
public boolean propertyExists(int property) {
switch (property) {
case RescueConstants.PROPERTY_START_TIME:
case RescueConstants.PROPERTY_LONGITUDE:
case RescueConstants.PROPERTY_LATITUDE:
case RescueConstants.PROPERTY_WIND_FORCE:
case RescueConstants.PROPERTY_WIND_DIRECTION:
return true;
}
return super.propertyExists(property);
}
*/
public Property getProperty(int property) /*throws UnknownPropertyException*/ {
switch (property) {
case RescueConstants.PROPERTY_START_TIME:
return startTime;
case RescueConstants.PROPERTY_LONGITUDE:
return longitude;
case RescueConstants.PROPERTY_LATITUDE:
return latitude;
case RescueConstants.PROPERTY_WIND_FORCE:
return windForce;
case RescueConstants.PROPERTY_WIND_DIRECTION:
return windDirection;
}
return super.getProperty(property);
}
public int getStartTime() {
return startTime.getValue();
}
public boolean setStartTime(int s, int timestamp, Object source) {
if (startTime.updateValue(s,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_START_TIME,timestamp,source);
return true;
}
return false;
}
public int getLongitude() {
return longitude.getValue();
}
public boolean setLongitude(int l, int timestamp, Object source) {
if (longitude.updateValue(l,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_LONGITUDE,timestamp,source);
return true;
}
return false;
}
public int getLatitude() {
return latitude.getValue();
}
public boolean setLatitude(int l, int timestamp, Object source) {
if (latitude.updateValue(l,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_LATITUDE,timestamp,source);
return true;
}
return false;
}
public int getWindForce() {
return windForce.getValue();
}
public boolean setWindForce(int w, int timestamp, Object source) {
if (windForce.updateValue(w,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_WIND_FORCE,timestamp,source);
return true;
}
return false;
}
public int getWindDirection() {
return windDirection.getValue();
}
public boolean setWindDirection(int w, int timestamp, Object source) {
if (windDirection.updateValue(w,timestamp,source)) {
firePropertyChanged(RescueConstants.PROPERTY_WIND_DIRECTION,timestamp,source);
return true;
}
return false;
}
}
/*
* Last change: $Date: 2004/05/04 03:09:38 $
* $Revision: 1.6 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.sample;
import rescuecore.*;
import rescuecore.objects.*;
import rescuecore.event.*;
import rescuecore.commands.AKChannel;
import java.util.*;
/**
This is a sample implementation of an ambulance team. This agent will attempt to rescue the closest humanoid it knows about. If it doesn't know anything then it moves randomly.
*/
public class SampleAmbulanceTeam extends PlatoonAgent {
private final static byte CHANNEL = 3;
/**
A list of known targets
*/
private List<Humanoid> targets;
/**
Construct a new SampleAmbulanceTeam
*/
public SampleAmbulanceTeam() {
super(RescueConstants.TYPE_AMBULANCE_TEAM); // We need to specify that we can only be an ambulance team
targets = new ArrayList<Humanoid>();
}
/**
Get a reference the the AmbulanceTeam controlled by this agent
@return the AmbulanceTeam controlled by this agent
*/
private AmbulanceTeam me() {
return (AmbulanceTeam)memory.lookup(id);
}
public void initialise(RescueObject[] knowledge) {
// Add a memory listener so that we get informed about changes to humanoids
super.initialise(knowledge);
memory.addMemoryListener(new MemoryListener() {
public void objectAdded(ObjectAddedEvent event) {
RescueObject o = event.getObject();
if (o.isHumanoid()) {
Humanoid h = (Humanoid)o;
// If the object is a buried humanoid, and we know the position of the humanoid, then add it to our target list
if ((h.isBuried() || h.isDamaged()) && memory.lookup(h.getPosition())!=null) {
if (!targets.contains(h)) {
targets.add(h);
// System.out.println(SampleAmbulanceTeam.this+" adding new target "+h);
}
}
}
}
public void objectChanged(ObjectChangedEvent event) {
RescueObject o = event.getObject();
if (o.isHumanoid()) {
Humanoid h = (Humanoid)o;
// If the object is a buried humanoid, and we know the position of the humanoid, then add it to our target list
if ((h.isBuried() || h.isDamaged()) && memory.lookup(h.getPosition())!=null) {
if (!targets.contains(h)) {
targets.add(h);
// System.out.println(SampleAmbulanceTeam.this+" adding changed target "+h);
}
}
else targets.remove(h); // Otherwise remove it
}
}
});
}
public void sense() {
// Is this the first timestep?
if (timeStep==1) {
// Listen on the right channel
appendCommand(new AKChannel(id,timeStep,CHANNEL));
}
SampleSearch.sortByDistance(targets,me(),memory);
for (Humanoid next : targets) {
if (next==me()) continue; // Ignore me
// Am I transporting someone to a refuge?
if (next.getPosition()==id) {
// Am I at a refuge?
if (getLocation() instanceof Refuge) {
unload();
tell("Unloading".getBytes(),CHANNEL);
// System.out.println(this+" unloading");
return;
}
else {
// Plan a path to a refuge
List<RescueObject> refuges = new ArrayList<RescueObject>();
memory.getObjectsOfType(refuges,RescueConstants.TYPE_REFUGE);
SampleSearch.sortByDistance(refuges,me(),memory);
int[] path = SampleSearch.breadthFirstSearch(getLocation(),refuges.iterator().next(),memory);
move(path);
// System.out.println(this+" heading for refuge");
return;
}
}
// Am I at the same location as this target (and not at a refuge)?
if (!(getLocation() instanceof Refuge) && next.getPosition()==getPosition()) {
// System.out.println(this+" at same position as "+next);
// System.out.println(this+" buriedness = "+next.getBuriedness()+", damage="+next.getDamage());
if (next.isBuried()) {
// Yes! Dig him out
// System.out.println(this+" rescueing "+next);
rescue(next);
tell(("Rescueing "+next.getID()).getBytes(),CHANNEL);
return;
}
else if (next.isDamaged()) {
// Load him
System.out.println(this+" loading "+next);
load(next);
tell(("Loading "+next.getID()).getBytes(),CHANNEL);
return;
}
}
}
// Try to plan a path to the next best target
for (Iterator<Humanoid> it = targets.iterator();it.hasNext();) {
Humanoid next = it.next();
RescueObject targetLocation = memory.lookup(next.getPosition());
if (!next.isBuried() || targetLocation==null) {
// If the target is not buried or we don't know its location then remove it from our target list
it.remove();
continue;
}
int[] path = SampleSearch.breadthFirstSearch(getLocation(),targetLocation,memory); // Find a path from my current location to the target's location
if (path!=null) {
// We've found a path. Hooray!
// Send a move command and we're finished
// System.out.println(this+" moving to "+next);
move(path);
return;
}
}
// We couldn't find a good target. Pick a random road and try moving there instead
Collection<RescueObject> allRoads = memory.getObjectsOfType(RescueConstants.TYPE_ROAD); // Find all roads
Road[] roads = new Road[allRoads.size()];
allRoads.toArray(roads);
Road target = (Road)roads[(int)(Math.random()*roads.length)]; // Pick one at random
// Plan a path
int[] path = SampleSearch.breadthFirstSearch(getLocation(),target,memory);
if (path!=null) {
// System.out.println(this+" moving randomly");
move(path); // Move if the path is valid
}
else {
// If we couldn't move randomly then just give up
// System.out.println(this+" giving up");
}
}
protected void hear(int from, byte[] msg, byte channel) {
// System.out.println("Received message from "+from+": "+String.valueOf(msg));
}
}
/*
* Last change: $Date: 2004/07/11 22:26:28 $
* $Revision: 1.6 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.sample;
import rescuecore.*;
import rescuecore.objects.*;
import rescuecore.commands.AKChannel;
/**
This is a sample implementation of a center agent. All this agent does is pass on messages.
*/
public class SampleCenter extends CenterAgent {
private byte agentChannel;
/**
Construct a new SampleCenter
*/
public SampleCenter() {
super(RescueConstants.TYPE_FIRE_STATION, RescueConstants.TYPE_AMBULANCE_CENTER, RescueConstants.TYPE_POLICE_OFFICE);
agentChannel = 0;
}
/**
Get a reference the the Building controlled by this agent
@return the Building controlled by this agent
*/
private Building me() {
return (Building)memory.lookup(id);
}
public void initialise(RescueObject[] knowledge) {
super.initialise(knowledge);
switch (type) {
case RescueConstants.TYPE_FIRE_STATION:
agentChannel = 1;
break;
case RescueConstants.TYPE_POLICE_OFFICE:
agentChannel = 2;
break;
case RescueConstants.TYPE_AMBULANCE_CENTER:
agentChannel = 3;
break;
}
// log("Initialised"); // Log a debugging message
}
public void sense() {
// Is this the first timestep?
if (timeStep==1) {
// Listen on the right channels
byte[] channels = new byte[2];
// All centers listen on channel 4
channels[0] = 4;
channels[1] = agentChannel;
appendCommand(new AKChannel(id,timeStep,channels));
}
}
protected void hear(int from, byte[] msg, byte channel) {
// System.out.println("Received message from "+from+" on channel "+channel+" : "+String.valueOf(msg));
// Pass the message through to the other channel
if (channel==4) tell(msg,agentChannel);
if (channel==agentChannel) tell(msg,(byte)4);
}
/**
Find out if an id represents one of my platoon agents
@param id The id to test
@return true if the RescueObject specified by the id is one of my platoon agents, false otherwise
*/
private boolean isPlatoon(int id) {
int agentType = memory.lookup(id).getType(); // What is the type of the agent we heard the message from?
switch (type) { // What is my type?
case RescueConstants.TYPE_FIRE_STATION:
// I'm a fire station, so my platoon agents are fire brigades
return agentType==RescueConstants.TYPE_FIRE_BRIGADE;
case RescueConstants.TYPE_POLICE_OFFICE:
// I'm a police office, so my platoon agents are police forces
return agentType==RescueConstants.TYPE_POLICE_FORCE;
case RescueConstants.TYPE_AMBULANCE_CENTER:
// I'm an ambulance center, so my platoon agents are ambulance teams
return agentType==RescueConstants.TYPE_AMBULANCE_TEAM;
}
throw new RuntimeException("Weird type for "+this+": "+Handy.getTypeName(type));
}
/**
Find out if an id represents one of the centers
@param id The id to test
@return true if the RescueObject specified by the id is one of the centers
*/
private boolean isCenter(int id) {
RescueObject target = memory.lookup(id);
if (target.isFireStation() || target.isAmbulanceCenter() || target.isPoliceOffice()) return true; // Centers are fire stations, police offices and ambulance centers
return false;
}
}
/*
* Last change: $Date: 2004/05/04 03:09:38 $
* $Revision: 1.6 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.sample;
import rescuecore.*;
import rescuecore.objects.*;
import rescuecore.event.*;
import rescuecore.commands.AKChannel;
import java.util.*;
/**
This is a sample implementation of a fire brigade. This agent will attempt to extinguish the closest fire it knows about. If it doesn't know anything then it moves randomly.
*/
public class SampleFireBrigade extends PlatoonAgent {
private final static byte CHANNEL = 1;
private boolean enableDebug;
/**
A list of known targets
*/
private List targets;
/**
Construct a new SampleFireBrigade
*/
public SampleFireBrigade() {
super(RescueConstants.TYPE_FIRE_BRIGADE);
targets = new ArrayList();
enableDebug = false;
}
public SampleFireBrigade(String[] args) {
this();
for (String next : args) {
if (next.equalsIgnoreCase("debug")) {
enableDebug = true;
}
}
}
/**
Get a reference to the FireBrigade controlled by this agent
@return the FireBrigade controlled by this agent
*/
private FireBrigade me() {
return (FireBrigade)memory.lookup(id);
}
public void initialise(RescueObject[] knowledge) {
if (enableDebug) {
try {
enableDebug("debug.log");
}
catch (Exception e) {
e.printStackTrace();
}
}
super.initialise(knowledge);
// Add a memory listener so that we get informed about changes to the buildings
memory.addMemoryListener(new MemoryListener() {
public void objectAdded(ObjectAddedEvent event) {
RescueObject o = event.getObject();
if (o.isBuilding()) {
if (((Building)o).isOnFire()) targets.add(o); // Add to target list if it is on fire
}
}
public void objectChanged(ObjectChangedEvent event) {
RescueObject o = event.getObject();
if (o.isBuilding() && event.getProperty()==RescueConstants.PROPERTY_FIERYNESS) { // We only care about the fieryness of the building - we can ignore all other updates
if (((Building)o).isOnFire()) targets.add(o); // Add to target list if it is on fire
else targets.remove(o); // Otherwise remove it from the target list
}
}
});
// log("Initialised"); // Log a debugging message
}
public void sense() {
// Is this the first timestep?
if (timeStep==1) {
// Listen on the right channel
appendCommand(new AKChannel(id,timeStep,CHANNEL));
}
// System.out.println("Fire brigade "+id+" water quantity: "+me().getWaterQuantity());
// log("Sense"); // Log a debugging message
// Am I at a refuge?
if (getLocation().isRefuge() && me().getWaterQuantity()<RescueConstants.MAX_WATER) {
// log("Filling at "+getLocation());
return;
}
// Am I out of water?
if (me().getWaterQuantity()==0) {
// Find the closest refuge
moveToClosestRefuge();
return;
}
// Sort the targets by distance from me
// log("Sorting targets");
SampleSearch.sortByDistance(targets,me(),memory);
// Find a valid target
for (Iterator it = targets.iterator();it.hasNext();) {
// Try to plan a path to the next best target
Building next = (Building)it.next();
if (!next.isOnFire()) {
// If the next target is not on fire then remove it from our target list
it.remove();
continue;
}
try {
if (memory.getDistance(me(),next) < RescueConstants.MAX_EXTINGUISH_DISTANCE) {
// System.out.println("Extinguishing "+next);
extinguish(next);
tell(("Extinguishing "+next.getID()).getBytes(),CHANNEL);
return;
}
}
catch (CannotFindLocationException e) {
System.err.println("PANIC! I don't know where I am!");
System.err.println(e);
}
Node entrance = (Node)memory.lookup(next.getEntrances()[0]); // Drive to the first entrance of the building
// log("Trying to plan path to "+next+" (entrance "+entrance+")");
int[] path = SampleSearch.breadthFirstSearch(getLocation(),entrance,memory); // Find a path from my current location to the target
if (path!=null) {
// We've found a path. Hooray!
// Send a move command and we're finished
// log("Moving to "+next);
move(path);
return;
}
// log("No path");
}
// We couldn't find a good target. Pick a random road and try moving there instead
// log("No good targets - picking a Road at random");
Collection<RescueObject> allRoads = memory.getObjectsOfType(RescueConstants.TYPE_ROAD); // Find all roads
Road[] roads = new Road[allRoads.size()];
allRoads.toArray(roads);
Road target = (Road)roads[(int)(Math.random()*roads.length)]; // Pick one at random
// log("Random target: "+target+". Planning path");
// Plan a path
int[] path = SampleSearch.breadthFirstSearch(getLocation(),target,memory);
if (path!=null) {
// log("Moving to "+target);
move(path); // Move if the path is valid
}
else {
// If we couldn't move randomly then just give up
// log("I give up");
}
}
protected void hear(int from, byte[] msg, byte channel) {
// System.out.println("Received message from "+from+": "+String.valueOf(msg));
}
private void moveToClosestRefuge() {
// log("Moving to closest refuge");
Collection<RescueObject> allRefuges = memory.getObjectsOfType(RescueConstants.TYPE_REFUGE);
Refuge[] refuges = new Refuge[allRefuges.size()];
allRefuges.toArray(refuges);
SampleSearch.sortByDistance(refuges,me(),memory);
for (int i=0;i<refuges.length;++i) {
Refuge next = refuges[i];
// log("Trying to plan path to "+next);
int[] path = SampleSearch.breadthFirstSearch(getLocation(),next,memory); // Find a path from my current location to the target
if (path!=null) {
// We've found a path. Hooray!
// Send a move command and we're finished
// log("Moving to "+next);
move(path);
return;
}
// log("No path");
}
// log("Couldn't move to refuge");
}
}
/*
* Last change: $Date: 2004/05/04 03:09:38 $
* $Revision: 1.6 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.sample;
import rescuecore.*;
import rescuecore.objects.*;
import rescuecore.event.*;
import rescuecore.commands.AKChannel;
import java.util.*;
/**
This is a sample implementation of a police force. This agent will attempt to clear the closest blocked road it knows about. If it doesn't know anything then it moves randomly.
*/
public class SamplePoliceForce extends PlatoonAgent {
private final static byte CHANNEL = 2;
/**
A list of known targets
*/
private List targets;
/**
Construct a new SamplePoliceForce
*/
public SamplePoliceForce() {
super(RescueConstants.TYPE_POLICE_FORCE); // We need to specify that we can only be a police force
targets = new ArrayList();
}
/**
Get a reference the the PoliceForce controlled by this agent
@return the PoliceForce controlled by this agent
*/
private PoliceForce me() {
return (PoliceForce)memory.lookup(id);
}
public void initialise(RescueObject[] knowledge) {
// Add a memory listener so that we get informed about changes to the roads
super.initialise(knowledge);
memory.addMemoryListener(new MemoryListener() {
public void objectAdded(ObjectAddedEvent event) {
RescueObject o = event.getObject();
if (o.isRoad()) {
if (((Road)o).isBlocked()) targets.add(o); // Add to target list if it is a blocked road
}
}
public void objectChanged(ObjectChangedEvent event) {
RescueObject o = event.getObject();
if (o.isRoad() && event.getProperty()==RescueConstants.PROPERTY_BLOCK) { // We only care about the blockedness of the road - we can ignore all other updates
if (((Road)o).isBlocked()) targets.add(o); // Add to target list if it is a blocked road
else targets.remove(o); // Otherwise remove it from the target list
}
}
});
// log("Initialised"); // Log a debugging message
}
public void sense() {
// Is this the first timestep?
if (timeStep==1) {
// Listen on the right channel
appendCommand(new AKChannel(id,timeStep,CHANNEL));
}
// log("Sense"); // Log a debugging message
// Am I on a blocked road?
RescueObject location = getLocation();
if (location.isRoad() && ((Road)location).isBlocked()) {
// Yes. Clear it!
// log("Clearing "+location);
clear((Road)location);
tell(("Clearing "+location.getID()).getBytes(),CHANNEL);
return;
}
// Sort the targets by distance from me
// log("Sorting targets");
SampleSearch.sortByDistance(targets,me(),memory);
// Find a valid target
for (Iterator it = targets.iterator();it.hasNext();) {
// Try to plan a path to the next best target
Road next = (Road)it.next();
if (!next.isBlocked()) {
// If the next target is not blocked then remove it from our target list
it.remove();
continue;
}
// log("Trying to plan path to "+next);
int[] path = SampleSearch.breadthFirstSearch(getLocation(),next,memory); // Find a path from my current location to the target
if (path!=null) {
// We've found a path. Hooray!
// Send a move command and we're finished
// log("Moving to "+next);
move(path);
return;
}
// log("No path");
}
// We couldn't find a good target. Pick a random road and try moving there instead
// log("No good targets - picking a Road at random");
Collection<RescueObject> allRoads = memory.getObjectsOfType(RescueConstants.TYPE_ROAD); // Find all roads
Road[] roads = new Road[allRoads.size()];
allRoads.toArray(roads);
Road target = (Road)roads[(int)(Math.random()*roads.length)]; // Pick one at random
// log("Random target: "+target+". Planning path");
// Plan a path
int[] path = SampleSearch.breadthFirstSearch(getLocation(),target,memory);
if (path!=null) {
// log("Moving to "+target);
move(path); // Move if the path is valid
}
else {
// If we couldn't move randomly then just give up
// log("I give up");
}
}
protected void hear(int from, byte[] msg, byte channel) {
// System.out.println("Received message from "+from+": "+String.valueOf(msg));
}
}
/*
* Last change: $Date: 2004/08/03 03:25:05 $
* $Revision: 1.4 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.sample;
import rescuecore.*;
import java.util.*;
public class SampleSearch {
/**
Do a breadth first search from one location to another
@param start The location we start at
@param goal The location we want to get to
@param memory The memory of the agent doing the searching
@return The path from start to goal, or null if no path can be found
*/
public static int[] breadthFirstSearch(RescueObject start, RescueObject goal, Memory memory) {
List open = new LinkedList();
Map ancestors = new HashMap();
open.add(start);
RescueObject next = null;
do {
next = (RescueObject)open.remove(0);
RescueObject[] neighbours = memory.findNeighbours(next);
if (neighbours==null) continue;
for (int i=0;i<neighbours.length;++i) {
if (neighbours[i]==null) continue;
if (neighbours[i]==goal) {
ancestors.put(neighbours[i],next);
next = neighbours[i];
break;
}
else {
if (!ancestors.containsKey(neighbours[i]) && !neighbours[i].isBuilding()) {
open.add(neighbours[i]);
ancestors.put(neighbours[i],next);
}
}
}
} while (next != goal && next != null);
if (next==null) {
// No path
return null;
}
// Walk back from goal to start
RescueObject current = goal;
Stack path = new Stack();
do {
path.push(current);
current = (RescueObject)ancestors.get(current);
} while (current!=start && current!=null);
int[] result = new int[path.size()];
for (int i=0;i<result.length;++i) {
result[i] = ((RescueObject)path.pop()).getID();
}
return result;
}
/**
Sort a list of RescueObjects by distance. This list will be sorted in place.
@param objects The objects to be sorted. When the method returns this list will be sorted.
@param reference The RescueObject to measure distances from
@param memory The memory of the agent doing the sorting
*/
public static void sortByDistance(List objects, RescueObject reference, Memory memory) {
synchronized(DISTANCE_SORTER) {
DISTANCE_SORTER.memory = memory;
DISTANCE_SORTER.reference = reference;
Collections.sort(objects,DISTANCE_SORTER);
}
}
/**
Sort an array of RescueObjects by distance. This array will be sorted in place.
@param objects The objects to be sorted. When the method returns this array will be sorted.
@param reference The RescueObject to measure distances from
@param memory The memory of the agent doing the sorting
*/
public static void sortByDistance(RescueObject[] objects, RescueObject reference, Memory memory) {
synchronized(DISTANCE_SORTER) {
DISTANCE_SORTER.memory = memory;
DISTANCE_SORTER.reference = reference;
Arrays.sort(objects,DISTANCE_SORTER);
}
}
/**
A Comparator for use when sorting RescueObjects by distance
*/
private static class DistanceSorter implements Comparator {
Memory memory;
RescueObject reference;
public int compare(Object o1, Object o2) {
try {
double d1 = memory.getDistance(reference,(RescueObject)o1);
double d2 = memory.getDistance(reference,(RescueObject)o2);
if (d1 < d2) // Object o1 is closer
return -1;
if (d1 > d2) // Object o2 is closer
return 1;
}
catch (CannotFindLocationException e) {
System.err.println(e);
}
// They are the same distance (or we couldn't find one of them). Return the lower id first
return ((RescueObject)o1).getID()-((RescueObject)o2).getID();
}
}
private final static DistanceSorter DISTANCE_SORTER = new DistanceSorter();
}
/*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import rescuecore.*;
import rescuecore.objects.*;
import java.util.*;
public class FixIDs {
private final static String source = "FixIDs";
public static void main(String[] args) {
try {
Road[] roads = MapFiles.loadRoads("road.bin");
Node[] nodes = MapFiles.loadNodes("node.bin");
Building[] buildings = MapFiles.loadBuildings("building.bin");
fixIDs(roads,nodes,buildings);
// Write out the new files
MapFiles.writeBuildings("building.bin",buildings);
MapFiles.writeRoads("road.bin",roads);
MapFiles.writeNodes("node.bin",nodes);
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void fixIDs(Road[] roads, Node[] nodes, Building[] buildings) {
/*
int maxID = 0;
for (int i=0;i<roads.length;++i) maxID = Math.max(maxID,roads[i].getID());
for (int i=0;i<nodes.length;++i) maxID = Math.max(maxID,nodes[i].getID());
for (int i=0;i<buildings.length;++i) maxID = Math.max(maxID,buildings[i].getID());
int nextID = ++maxID;
*/
int nextID = 1;
HashMap<Integer,Integer> idMap = new HashMap<Integer,Integer>();
HashMap<Integer,Node> nodeMap = new HashMap<Integer,Node>();
for (int i=0;i<roads.length;++i) {
// idMap.put(roads[i].getID(),nextID);
// System.out.println("Road: "+roads[i].getID()+" -> "+nextID);
roads[i].setID(nextID++);
}
for (int i=0;i<buildings.length;++i) {
// idMap.put(buildings[i].getID(),nextID);
// System.out.println("Building: "+buildings[i].getID()+" -> "+nextID);
buildings[i].setID(nextID++);
}
for (int i=0;i<nodes.length;++i) {
idMap.put(nodes[i].getID(),nextID);
// System.out.println("Node: "+nodes[i].getID()+" -> "+nextID);
nodes[i].setID(nextID++);
// System.out.println("Node "+nodes[i].getID()+" used to have "+nodes[i].getEdges().length+" edges");
nodes[i].clearEdges(0,null);
nodeMap.put(nodes[i].getID(),nodes[i]);
}
// Fix the road head/tail entries
for (int i=0;i<roads.length;++i) {
int headID = idMap.get(roads[i].getHead());
int tailID = idMap.get(roads[i].getTail());
// if (headID==0) System.out.println("Couldn't find the new head node for road "+roads[i].getID());
// if (tailID==0) System.out.println("Couldn't find the new tail node for road "+roads[i].getID());
roads[i].setHead(idMap.get(roads[i].getHead()),0,null);
roads[i].setTail(idMap.get(roads[i].getTail()),0,null);
Node head = nodeMap.get(roads[i].getHead());
Node tail = nodeMap.get(roads[i].getTail());
head.appendEdge(roads[i].getID(),0,null);
tail.appendEdge(roads[i].getID(),0,null);
}
// Fix the building entrances
for (int i=0;i<buildings.length;++i) {
int[] entrances = buildings[i].getEntrances();
for (int j=0;j<entrances.length;++j) {
// System.out.println("Entrance "+entrances[j]+" -> "+idMap.get(entrances[j]));
entrances[j] = idMap.get(entrances[j]);
Node node = nodeMap.get(entrances[j]);
node.appendEdge(buildings[i].getID(),0,null);
}
buildings[i].setEntrances(entrances,0,null);
}
// Check that the nodes shortcut/pocket/signal timing are the right size
for (int i=0;i<nodes.length;++i) {
Node next = nodes[i];
int numEdges = next.getEdges().length;
int shortcutSize = next.getShortcutToTurn().length;
int pocketSize = next.getPocketToTurnAcross().length;
int timingSize = next.getSignalTiming().length;
while (shortcutSize < numEdges) {
next.appendShortcutToTurn(0,0,null);
++shortcutSize;
}
while (pocketSize < numEdges*2) {
next.appendPocketToTurnAcross(0,0,null);
++pocketSize;
}
while (timingSize < numEdges*3) {
next.appendSignalTiming(0,0,null);
++timingSize;
}
if (shortcutSize > numEdges) {
// System.out.println("Node "+next.getID()+" has too many shortcuts");
next.clearShortcutToTurn(0,null);
for (int j=0;j<numEdges;++j) next.appendShortcutToTurn(0,0,null);
}
if (pocketSize > numEdges*2) {
// System.out.println("Node "+next.getID()+" has too many pockets");
next.clearPocketToTurnAcross(0,null);
for (int j=0;j<numEdges*2;++j) next.appendPocketToTurnAcross(0,0,null);
}
if (timingSize > numEdges*3) {
// System.out.println("Node "+next.getID()+" has too many timings");
next.clearSignalTiming(0,null);
for (int j=0;j<numEdges*3;++j) next.appendSignalTiming(0,0,null);
}
}
}
}
/*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import rescuecore.*;
import rescuecore.view.*;
import rescuecore.log.*;
import rescuecore.objects.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.util.Collection;
public class LogViewer extends JPanel {
private ObjectInspector inspector;
private Map map;
private Log log;
private int time;
public static void main(String[] args) {
if (args.length==0) {
System.err.println("Usage: LogViewer <filename>");
return;
}
try {
Log log = Log.generateLog(args[0]);
JFrame frame = new JFrame("Log viewer");
frame.setContentPane(new LogViewer(log));
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
});
frame.pack();
Toolkit t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
// frame.setSize(200,200);
frame.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
public LogViewer(Log log) {
super(new BorderLayout());
this.log = log;
time = 0;
map = Map.defaultMap(log.getMemory(0));
final JSlider slider = new JSlider(0,log.getMaxTimestep());
add(map,BorderLayout.CENTER);
JPanel timePanel = new JPanel(new BorderLayout());
Border b = BorderFactory.createLineBorder(Color.BLACK);
b = BorderFactory.createTitledBorder(b,"Time Step");
timePanel.setBorder(b);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setSnapToTicks(true);
slider.setMinorTickSpacing(1);
slider.setMajorTickSpacing(10);
JButton left = new JButton(" < ");
JButton right = new JButton(" > ");
left.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){slider.setValue(slider.getValue()-1);}
});
right.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){slider.setValue(slider.getValue()+1);}
});
slider.addChangeListener(new ChangeListener(){
public void stateChanged(ChangeEvent e){if (!slider.getValueIsAdjusting()) setTimeStep(slider.getValue());}
});
timePanel.add(slider,BorderLayout.CENTER);
timePanel.add(left,BorderLayout.WEST);
timePanel.add(right,BorderLayout.EAST);
add(timePanel,BorderLayout.SOUTH);
inspector = new ObjectInspector();
add(inspector,BorderLayout.EAST);
ObjectSelector selector = new ObjectSelector(map);
selector.addObjectSelectionListener(inspector);
slider.setValue(0);
}
private void setTimeStep(int t) {
if (t < 0 || t > log.getMaxTimestep()) return;
time = t;
Memory m = log.getMemory(time);
map.setMemory(m);
map.repaint();
Collection<RescueObject> all = m.getAllObjects();
for (RescueObject next : all) {
if (next instanceof Road) {
Road r = (Road)next;
if (r.getBlock() > r.getWidth()) System.out.println("Overblocked");
if (r.getLinesToHead() != r.getLinesToTail()) System.out.println("Asymmetric road");
}
}
}
private void moveTime(int delta) {
setTimeStep(time+delta);
}
}
/*
* Last change: $Date: 2004/05/04 03:09:39 $
* $Revision: 1.5 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import rescuecore.*;
import rescuecore.objects.*;
import java.io.*;
public class MapFiles {
private final static int GIS_TYPE_AMBULANCE_CENTER = 2;
private final static int GIS_TYPE_FIRE_STATION = 3;
private final static int GIS_TYPE_POLICE_OFFICE = 4;
private final static int GIS_TYPE_REFUGE = 5;
private final static int GIS_TYPE_CIVILIAN = 6;
private final static int GIS_TYPE_AMBULANCE_TEAM = 7;
private final static int GIS_TYPE_FIRE_BRIGADE = 8;
private final static int GIS_TYPE_POLICE_FORCE = 9;
private final static int GIS_TYPE_FIRE = 10;
private final static String[] GIS_TYPES = {"","","AmbulanceCenter","FireStation","PoliceOffice","Refuge","Civilian","AmbulanceTeam","FireBrigade","PoliceForce","FirePoint"};
private static int readInt(InputStream in) throws IOException {
int result = (in.read()&0xFF) | ((in.read() << 8) & 0xFF00) | ((in.read() << 16) & 0xFF0000) | ((in.read() << 24) & 0xFF000000);
return result;
}
private static void writeInt(OutputStream out, int value) throws IOException {
out.write(value&0xFF);
out.write((value>>8)&0xFF);
out.write((value>>16)&0xFF);
out.write((value>>24)&0xFF);
}
public static Node[] loadNodes() throws IOException {
return loadNodes("node.bin");
}
public static Node[] loadNodes(File parentDir) throws IOException {
return loadNodes(parentDir.getAbsolutePath() + File.separator + "node.bin");
}
public static Node[] loadNodes(String file) throws IOException {
System.out.print("Loading nodes from "+file);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
// Skip something, not sure what
readInt(in);
readInt(in);
readInt(in);
int num = readInt(in);
// System.out.println("Loading "+num+" nodes");
Node[] result = new Node[num];
for (int i=0;i<num;++i) {
int size = readInt(in);
int id = readInt(in);
int x = readInt(in);
int y = readInt(in);
int numEdges = readInt(in);
int[] edges = new int[numEdges];
int[] shortcut = new int[numEdges];
int[] pocket = new int[numEdges*2];
int[] signalTiming = new int[numEdges*3];
for (int j=0;j<numEdges;++j) edges[j] = readInt(in);
int signal = readInt(in);
for (int j=0;j<numEdges;++j) shortcut[j] = readInt(in); // shortcutToTurn
for (int j=0;j<numEdges;++j) {
pocket[j*2] = readInt(in); // pocketToTurnAcross
pocket[j*2 + 1] = readInt(in);
}
for (int j=0;j<numEdges;++j) {
signalTiming[j*3] = readInt(in); // signalTiming
signalTiming[j*3 + 1] = readInt(in);
signalTiming[j*3 + 2] = readInt(in);
}
result[i] = new Node(x,y,edges,signal!=0,shortcut,pocket,signalTiming);
result[i].setID(id);
System.out.print(".");
}
System.out.println();
return result;
}
finally {
if (in!=null) in.close();
}
}
public static Road[] loadRoads() throws IOException {
return loadRoads("road.bin");
}
public static Road[] loadRoads(File parentDir) throws IOException {
return loadRoads(parentDir.getAbsolutePath() + File.separator + "road.bin");
}
public static Road[] loadRoads(String file) throws IOException {
System.out.print("Loading roads from "+file);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
readInt(in);
readInt(in);
readInt(in);
int num = readInt(in);
Road[] result = new Road[num];
for (int i=0;i<num;++i) {
int size = readInt(in);
int id = readInt(in);
int head = readInt(in);
int tail = readInt(in);
int length = readInt(in);
int roadKind = readInt(in);
int carsToHead = readInt(in);
int carsToTail = readInt(in);
int humansToHead = readInt(in);
int humansToTail = readInt(in);
int width = readInt(in);
int block = readInt(in);
int repairCost = readInt(in);
int median = readInt(in);
int linesToHead = readInt(in);
int linesToTail = readInt(in);
int widthForWalkers = readInt(in);
result[i] = new Road(head,tail,length,roadKind,carsToHead,carsToTail,humansToHead,humansToTail,width,block,repairCost,median!=0,linesToHead,linesToTail,widthForWalkers);
result[i].setID(id);
System.out.print(".");
}
System.out.println();
return result;
}
finally {
if (in!=null) in.close();
}
}
public static Building[] loadBuildings() throws IOException {
return loadBuildings("building.bin");
}
public static Building[] loadBuildings(File parentDir) throws IOException {
return loadBuildings(parentDir.getAbsolutePath() + File.separator + "building.bin");
}
public static Building[] loadBuildings(String file) throws IOException {
System.out.print("Loading buildings from "+file);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
readInt(in);
readInt(in);
readInt(in);
int num = readInt(in);
Building[] result = new Building[num];
for (int i=0;i<num;++i) {
int size = readInt(in);
int id = readInt(in);
int x = readInt(in);
int y = readInt(in);
int floors = readInt(in);
int attributes = readInt(in);
int ignition = readInt(in);
int fieryness = readInt(in);
int brokenness = readInt(in);
int numEntrances = readInt(in);
int[] entrances = new int[numEntrances];
for (int j=0;j<numEntrances;++j) entrances[j] = readInt(in);
int shapeID = readInt(in);
int area = readInt(in);
int totalArea = readInt(in);
int code = readInt(in);
int numApexes = readInt(in);
int[] apexes = new int[numApexes*2];
for (int j=0;j<numApexes;++j) {
// Apexes
apexes[j*2] = readInt(in);
apexes[j*2 + 1] = readInt(in);
}
result[i] = new Building(x,y,floors,attributes,ignition!=0,fieryness,brokenness,entrances,code,area,totalArea,apexes,0,1);
result[i].setID(id);
System.out.print(".");
}
System.out.println();
return result;
}
finally {
if (in!=null) in.close();
}
}
public static void writeBuildings(String file, Building[] bs) throws IOException{
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
writeInt(out,0);
writeInt(out,0);
writeInt(out,0);
writeInt(out,bs.length);
for(int i = 0; i < bs.length; i++){
writeInt(out,getSize(bs[i]));
writeInt(out,bs[i].getID());
writeInt(out,bs[i].getX());
writeInt(out,bs[i].getY());
writeInt(out,bs[i].getFloors());
writeInt(out,bs[i].getBuildingAttributes());
writeInt(out,bs[i].isIgnited()?1:0);
writeInt(out,bs[i].getFieryness());
writeInt(out,bs[i].getBrokenness());
int[] ent = bs[i].getEntrances();
writeInt(out,ent.length);
for(int j = 0; j < ent.length; j++)
writeInt(out,ent[j]);
writeInt(out,0/*bs[i].getBuildingShapeID()*/);
writeInt(out,bs[i].getGroundArea());
writeInt(out,bs[i].getTotalArea());
writeInt(out,bs[i].getBuildingCode());
int[] ap = bs[i].getApexes();
writeInt(out,ap.length/2);
for(int j = 0; j < ap.length; j++)
writeInt(out,ap[j]);
}
}
finally {
if (out!=null) out.close();
}
}
public static void writeNodes(String file, Node[] ns) throws IOException{
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
writeInt(out,5);
writeInt(out,-152950000);
writeInt(out,52050000);
writeInt(out,ns.length);
// System.out.println("Writing "+ns.length+" nodes");
for(int i = 0; i < ns.length; i++){
writeInt(out,getSize(ns[i]));
writeInt(out,ns[i].getID());
writeInt(out,ns[i].getX());
writeInt(out,ns[i].getY());
int[] ed = ns[i].getEdges();
writeInt(out,ed.length);
// System.out.println("Node "+ns[i].getID()+" has "+ed.length+" edges");
for(int j = 0; j < ed.length; j++)
writeInt(out,ed[j]);
writeInt(out,ns[i].hasSignal()?1:0);
int[] sh = ns[i].getShortcutToTurn();
for(int j = 0; j < sh.length; j++)
writeInt(out,sh[j]);
int[] p = ns[i].getPocketToTurnAcross();
for(int j = 0; j < p.length; j++)
writeInt(out,p[j]);
int[] st = ns[i].getSignalTiming();
for(int j = 0; j < st.length; j++)
writeInt(out,st[j]);
}
}
finally {
if (out!=null) out.close();
}
}
public static void writeRoads(String file, Road[] roads) throws IOException {
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
writeInt(out,5);
writeInt(out,-152950000);
writeInt(out,52050000);
writeInt(out,roads.length);
for(int i = 0; i < roads.length; i++){
writeInt(out,getSize(roads[i]));
writeInt(out,roads[i].getID());
writeInt(out,roads[i].getHead());
writeInt(out,roads[i].getTail());
writeInt(out,roads[i].getLength());
writeInt(out,roads[i].getRoadKind());
writeInt(out,roads[i].getCarsPassToHead());
writeInt(out,roads[i].getCarsPassToTail());
writeInt(out,roads[i].getHumansPassToHead());
writeInt(out,roads[i].getHumansPassToTail());
writeInt(out,roads[i].getWidth());
writeInt(out,roads[i].getBlock());
writeInt(out,roads[i].getRepairCost());
writeInt(out,roads[i].hasMedian()?1:0);
writeInt(out,roads[i].getLinesToHead());
writeInt(out,roads[i].getLinesToTail());
writeInt(out,roads[i].getWidthForWalkers());
}
}
finally {
if (out!=null) out.close();
}
}
public static void writeGISMotionlessObjects(PrintWriter out, FireStation[] fire, PoliceOffice[] police, AmbulanceCenter[] ambulance, Refuge[] refuge) {
out.println("# Motionless Objects");
for (int i=0;i<fire.length;++i) writeFixedObjectData(out,GIS_TYPE_FIRE_STATION,fire[i]);
for (int i=0;i<police.length;++i) writeFixedObjectData(out,GIS_TYPE_POLICE_OFFICE,police[i]);
for (int i=0;i<ambulance.length;++i) writeFixedObjectData(out,GIS_TYPE_AMBULANCE_CENTER,ambulance[i]);
for (int i=0;i<refuge.length;++i) writeFixedObjectData(out,GIS_TYPE_REFUGE,refuge[i]);
}
public static void writeGISMovingObjects(PrintWriter out, FireBrigade[] fire, PoliceForce[] police, AmbulanceTeam[] ambulance, Civilian[] civ, Memory m) {
out.println("# Moving Objects");
for (int i=0;i<civ.length;++i) writeMovingObjectData(out,GIS_TYPE_CIVILIAN,m.lookup(civ[i].getPosition()),m);
for (int i=0;i<ambulance.length;++i) writeMovingObjectData(out,GIS_TYPE_AMBULANCE_TEAM,m.lookup(ambulance[i].getPosition()),m);
for (int i=0;i<fire.length;++i) writeMovingObjectData(out,GIS_TYPE_FIRE_BRIGADE,m.lookup(fire[i].getPosition()),m);
for (int i=0;i<police.length;++i) writeMovingObjectData(out,GIS_TYPE_POLICE_FORCE,m.lookup(police[i].getPosition()),m);
}
public static void writeGISFires(PrintWriter out, Building[] fires) {
out.println("# Fires");
for (int i=0;i<fires.length;++i) {
writeFixedObjectData(out,GIS_TYPE_FIRE,fires[i]);
}
}
public static void writeGISImportantBuildings(PrintWriter out, Building[] buildings) {
out.println("# Important buildings");
for (int i=0;i<buildings.length;++i) {
if (buildings[i].getImportance()>1) {
out.print("ImportantBuilding ");
out.print(buildings[i].getID());
out.print("=");
out.println(buildings[i].getImportance());
}
}
}
private static void writeFixedObjectData(PrintWriter out, int type, Building b) {
// Fixed objects are of them form TYPE = id
out.print(GIS_TYPES[type]);
out.print("=");
out.print(b.getID());
out.println();
}
private static void writeMovingObjectData(PrintWriter out, int type, RescueObject location, Memory m) {
// Moving objects are of the form TYPE = position [,positionExtra]
out.print(GIS_TYPES[type]);
out.print("=");
out.print(location.getID());
if (location.isRoad()) {
Road r = (Road)location;
Node head = m.getHead(r);
Node tail = m.getTail(r);
int extra = (int)((Math.random()*r.getLength())/1000);
out.print(",");
out.print(extra);
}
out.println();
}
private static int getSize(Building b){
return (15 + b.getEntrances().length + b.getApexes().length)*RescueConstants.INT_SIZE;
}
private static int getSize(Node n){
return (6 + n.getEdges().length*7)*RescueConstants.INT_SIZE;
}
private static int getSize(Road r){
return 16*RescueConstants.INT_SIZE;
}
}
/*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import rescuecore.*;
import rescuecore.view.*;
import rescuecore.objects.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
public class PlaceBlockages {
private Road[] allRoads;
private Node[] allNodes;
private Memory memory;
private Map map;
private Point pressPoint;
private Point dragPoint;
private Layer overlay;
private Layer roadLayer;
public PlaceBlockages(Road[] roads, Node[] nodes) {
allRoads = roads;
allNodes = nodes;
memory = new HashMemory();
for (int i=0;i<roads.length;++i) {
memory.add(roads[i],0,this);
}
for (int i=0;i<nodes.length;++i) {
if (memory.lookup(nodes[i].getID())!=null) System.err.println("WARNING: Duplicate node ID: "+nodes[i].getID()+", this is is already used by "+memory.lookup(nodes[i].getID()));
memory.add(nodes[i],0,this);
}
Arrays.sort(allRoads,new RoadSorter(memory));
map = new Map(memory);
roadLayer = Layer.createRoadLayer(memory);
roadLayer.addRenderer(Road.class,new BigRoadRenderer());
map.addLayer(roadLayer);
map.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
handleClick(e);
}
public void mousePressed(MouseEvent e) {
handlePress(e);
}
public void mouseReleased(MouseEvent e) {
handleRelease(e);
}
});
map.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
handleDrag(e);
}
});
JToolBar toolbar = new JToolBar();
Action saveAction = new AbstractAction("Save") {
public void actionPerformed(ActionEvent e) {
save();
}
};
toolbar.add(saveAction);
JFrame frame = new JFrame("Road Blockage Placement");
JPanel top = new JPanel(new BorderLayout());
top.add(toolbar,BorderLayout.NORTH);
top.add(map,BorderLayout.CENTER);
frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {
System.exit(0);
}});
frame.getContentPane().add(top);
frame.pack();
frame.setVisible(true);
}
private void handleClick(MouseEvent e) {
Object[] all = map.getObjectsAtPoint(e.getPoint());
update(all);
map.repaint();
}
private void handlePress(MouseEvent e) {
pressPoint = e.getPoint();
}
private void handleRelease(MouseEvent e) {
if (dragPoint==null) return;
int x1 = Math.min(pressPoint.x,dragPoint.x);
int y1 = Math.min(pressPoint.y,dragPoint.y);
int x2 = Math.max(pressPoint.x,dragPoint.x);
int y2 = Math.max(pressPoint.y,dragPoint.y);
Rectangle2D box = new Rectangle2D.Double(x1,y1,x2-x1,y2-y1);
Object[] objects = map.getObjectsInArea(box);
update(objects);
pressPoint = null;
dragPoint = null;
overlay.removeAllObjects();
map.repaint();
}
private void handleDrag(MouseEvent e) {
if (pressPoint!=null) {
dragPoint = e.getPoint();
int dx = pressPoint.x - dragPoint.x;
int dy = pressPoint.y - dragPoint.y;
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (dx > 5 || dy > 5) {
// Draw a rectangle on the view
Rectangle r = new Rectangle(Math.min(pressPoint.x,dragPoint.x),Math.min(pressPoint.y,dragPoint.y),dx,dy);
overlay.setObject(r);
map.repaint();
}
}
}
private void update(Object[] os) {
for (int i=0;i<os.length;++i) {
if (os[i] instanceof Road) updateRoad((Road)os[i]);
}
map.repaint();
}
private void updateRoad(Road road) {
int lanes = road.getLinesToHead();
int empty = lanes; //road.getFreeLinesToHead(); FIXME
int width = road.getWidth();
--empty;
if (empty==-1) empty = lanes;
int blocked = lanes-empty;
int laneWidth = road.getWidth()/(road.getLinesToHead()+road.getLinesToTail());
int blockNeeded = blocked * laneWidth * 2;
if (blockNeeded > road.getWidth()) {
System.out.println("Trying to set block to "+blockNeeded+" but width is only "+road.getWidth());
blockNeeded = road.getWidth();
}
road.setBlock(blockNeeded,0,this);
// Check that we have blocked the right number of lanes
int free = road.getLinesToHead(); //road.getFreeLinesToHead(); FIXME
if (free != empty) System.out.println("We have "+free+" empty lanes instead of "+empty+"!");
}
private void save() {
try {
// Write out the blocked roads
PrintWriter out = new PrintWriter(new FileWriter(new File("blockades.lst")));
for (int i=0;i<allRoads.length;++i) {
out.println(allRoads[i].getBlock());
}
out.flush();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
private static class BigRoadRenderer implements MapRenderer {
public boolean canRender(Object o) {
return o instanceof Road;
}
public Shape render(Object o, Memory memory, Graphics g, ScreenTransform transform) throws CannotFindLocationException {
Road road = (Road)o;
Node roadHead = (Node)memory.lookup(road.getHead());
Node roadTail = (Node)memory.lookup(road.getTail());
int headX = transform.toScreenX(roadHead.getX());
int headY = transform.toScreenY(roadHead.getY());
int tailX = transform.toScreenX(roadTail.getX());
int tailY = transform.toScreenY(roadTail.getY());
Shape shape = new java.awt.geom.Line2D.Double(headX,headY,tailX,tailY);
shape = new BasicStroke(10).createStrokedShape(shape);
Color c = Color.BLACK;
int lanes = road.getLinesToHead();
int free = lanes; //road.getFreeLinesToHead(); FIXME
c = Color.ORANGE;
if (free==0) c = Color.BLACK;
if (free==lanes) c = Color.WHITE;
RenderTools.setLineMode(g,ViewConstants.LINE_MODE_SOLID,c);
((Graphics2D)g).draw(shape);
return shape;
}
}
public static void main(String[] args) {
try {
Road[] r = MapFiles.loadRoads("road.bin");
Node[] n = MapFiles.loadNodes("node.bin");
new PlaceBlockages(r,n);
}
catch (IOException e) {
e.printStackTrace();
}
}
private class RoadSorter implements Comparator {
private Memory m;
public RoadSorter(Memory m) {
this.m = m;
}
public int compare(Object o1, Object o2) {
Road r1 = (Road)o1;
Road r2 = (Road)o2;
Node h1 = (Node)m.lookup(r1.getHead());
Node t1 = (Node)m.lookup(r1.getTail());
Node h2 = (Node)m.lookup(r2.getHead());
Node t2 = (Node)m.lookup(r2.getTail());
int x1 = (h1.getX()+t1.getX())/2;
int y1 = (h1.getY()+t1.getY())/2;
int x2 = (h2.getX()+t2.getX())/2;
int y2 = (h2.getY()+t2.getY())/2;
if (x1 < x2) return -1;
if (x1 > x2) return 1;
if (y1 < y2) return -1;
if (y2 > y1) return 1;
return 0;
}
}
}
/*
* Last change: $Date: 2004/08/10 20:46:17 $
* $Revision: 1.7 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import java.io.*;
import java.util.*;
import rescuecore.objects.*;
import rescuecore.*;
/**
This class will take a city data file and produce a random gisini.txt file for use on that city.
@author Cameron Skinner
*/
public class RandomConfig {
private Node[] allNodes;
private Road[] allRoads;
private Building[] allBuildings;
public static void main(String[] args) {
new RandomConfig(args);
}
RandomConfig(String[] args) {
Limits fireBrigades = new Limits(10,15,"fireBrigades","fire brigades");
Limits policeForces = new Limits(10,15,"policeForces","police forces");
Limits ambulanceTeams = new Limits(5,8,"ambulanceTeams","ambulance teams");
Limits fireStations = new Limits(1,1,"fireStations","fire stations");
Limits policeStations = new Limits(1,1,"policeStations","police stations");
Limits ambulanceCenters = new Limits(1,1,"ambulanceCenters","ambulance centers");
Limits civilians = new Limits(70,90,"civilians","civilians");
Limits refuges = new Limits(1,5,"refuges","refuges");
Limits fires = new Limits(2,8,"fires","fires");
Limits fireRadius = new Limits(0,20000,"fireradius","fire radius");
Limits[] allLimits = new Limits[] {fireBrigades,policeForces,ambulanceTeams,fireStations,policeStations,ambulanceCenters,civilians,refuges,fires,fireRadius};
boolean allowTrappedAgents = false;
boolean bigFires = false;
boolean trappedCivilians = true;
String dir = "";
for (int i=0;i<args.length;++i) {
if (args[i].startsWith("-min-")) {
for (int j=0;j<allLimits.length;++j) {
if (args[i].equalsIgnoreCase("-min-"+allLimits[j].prefix)) allLimits[j].min = Integer.parseInt(args[++i]);
}
}
else if (args[i].startsWith("-max-")) {
for (int j=0;j<allLimits.length;++j) {
if (args[i].equalsIgnoreCase("-max-"+allLimits[j].prefix)) allLimits[j].max = Integer.parseInt(args[++i]);
}
}
else if (args[i].startsWith("-no-")) {
for (int j=0;j<allLimits.length;++j) {
if (args[i].equalsIgnoreCase("-no-"+allLimits[j].prefix)) {
allLimits[j].min = 0;
allLimits[j].max = 0;
}
}
}
else if (args[i].startsWith("-set-")) {
int num = Integer.parseInt(args[i+1]);
for (int j=0;j<allLimits.length;++j) {
if (args[i].equalsIgnoreCase("-set-"+allLimits[j].prefix)) {
allLimits[j].min = num;
allLimits[j].max = num;
}
}
++i;
}
else if (args[i].equalsIgnoreCase("-t") || args[i].equalsIgnoreCase("--allow-trapped-agents")) {
allowTrappedAgents = true;
}
else if (args[i].equalsIgnoreCase("-c") || args[i].equalsIgnoreCase("--allow-untrapped-civilians")) {
trappedCivilians = false;
}
else if (args[i].equalsIgnoreCase("-b") || args[i].equalsIgnoreCase("--big-fires")) {
bigFires = true;
}
else if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--dir")) {
dir = args[i+1];
}
else if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--help")) {
System.out.println("Usage: RandomConfig [options]");
System.out.println("This program will read from \"road.bin\", \"node.bin\" and \"building.bin\" and produce a randomised \"gisini.txt\"");
System.out.println("Options");
System.out.println("=======");
for (int j=0;j<allLimits.length;++j) {
System.out.println("-min-"+allLimits[j].prefix+"\tSet the minimum number of "+allLimits[j].name+" (currently "+allLimits[j].min+")");
System.out.println("-max-"+allLimits[j].prefix+"\tSet the maximum number of "+allLimits[j].name+" (currently "+allLimits[j].max+")");
System.out.println("-no-"+allLimits[j].prefix+"\tSet the minimum and maximum of "+allLimits[j].name+" to zero");
}
System.out.println("-t\t--allow-trapped-agents\tAllow rescue agents (fire brigades, police forces and ambulance teams) to be placed inside buildings (default OFF)");
System.out.println("-c\t--allow-untrapped-civilians\tAllow civilians to be placed outside buildings (default OFF)");
System.out.println("-b\t--big-fires\tAllow big fires");
System.out.println("-d\t--dir\tSet output directory (use full path)");
System.out.println("-h\t--help\tPrint this message");
return;
}
}
try {
File parentDir = new File(dir);
File gisini = new File(parentDir, "gisini.txt");
// Open the output
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(gisini)));
// Build the city data
allNodes = MapFiles.loadNodes(parentDir);
allRoads = MapFiles.loadRoads(parentDir);
allBuildings = MapFiles.loadBuildings(parentDir);
Memory memory = new HashMemory();
for (int i=0;i<allNodes.length;++i) memory.add(allNodes[i],0);
for (int i=0;i<allRoads.length;++i) memory.add(allRoads[i],0);
for (int i=0;i<allBuildings.length;++i) memory.add(allBuildings[i],0);
// Place items
int numFireBrigades = fireBrigades.getNumber();
int numPoliceForces = policeForces.getNumber();
int numAmbulanceTeams = ambulanceTeams.getNumber();
int numFireStations = fireStations.getNumber();
int numPoliceStations = policeStations.getNumber();
int numAmbulanceCenters = ambulanceCenters.getNumber();
int numRefuges = refuges.getNumber();
int numCivilians = civilians.getNumber();
int numFires = fires.getNumber();
FireStation[] fireStationBuildings = new FireStation[numFireStations];
PoliceOffice[] policeOfficeBuildings = new PoliceOffice[numPoliceStations];
AmbulanceCenter[] ambulanceCenterBuildings = new AmbulanceCenter[numAmbulanceCenters];
Refuge[] refugeBuildings = new Refuge[numRefuges];
Building[] normalBuildings = placeMotionlessObjects(fireStationBuildings,policeOfficeBuildings,ambulanceCenterBuildings,refugeBuildings,allBuildings);
MapFiles.writeGISMotionlessObjects(out,fireStationBuildings,policeOfficeBuildings,ambulanceCenterBuildings,refugeBuildings);
FireBrigade[] fireBrigadeObjects = new FireBrigade[numFireBrigades];
PoliceForce[] policeForceObjects = new PoliceForce[numPoliceForces];
AmbulanceTeam[] ambulanceTeamObjects = new AmbulanceTeam[numAmbulanceTeams];
Civilian[] civilianObjects = new Civilian[numCivilians];
// placeMovingObjects(fireBrigadeObjects,policeForceObjects,ambulanceTeamObjects,civilianObjects,allBuildings,allRoads,allNodes,allowTrappedAgents,trappedCivilians);
placeMovingObjects(fireBrigadeObjects,policeForceObjects,ambulanceTeamObjects,civilianObjects,allBuildings,new Road[0],allNodes,allowTrappedAgents,trappedCivilians);
MapFiles.writeGISMovingObjects(out,fireBrigadeObjects,policeForceObjects,ambulanceTeamObjects,civilianObjects,memory);
Building[] fireBuildings;
if (bigFires) fireBuildings = placeBigFires(numFires,normalBuildings,fireRadius);
else fireBuildings = placeNormalFires(numFires,normalBuildings);
MapFiles.writeGISFires(out,fireBuildings);
out.flush();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
/*
Place all motionless objects (fire stations, police offices, ambulance teams and refuges)
@param fire An array to be filled with fire stations
@param police An array to be filled with police offices
@param ambulance An array to be filled with ambulance centres
@param refuge An array to be filled with refuges
@param allBuildings All buildings in the map
@return All ordinary buildings
*/
public static Building[] placeMotionlessObjects(FireStation[] fire, PoliceOffice[] police, AmbulanceCenter[] ambulance, Refuge[] refuge, Building[] allBuildings) {
List remaining = new ArrayList();
for (int i=0;i<allBuildings.length;++i) remaining.add(allBuildings[i]);
Collections.shuffle(remaining);
System.out.println("Placing "+ambulance.length+" ambulance centers");
Iterator it = remaining.iterator();
for (int i=0;i<ambulance.length;++i) {
Building location = (Building)it.next();
it.remove();
AmbulanceCenter a = new AmbulanceCenter(location);
a.setID(location.getID());
ambulance[i] = a;
// writeFixedObjectData(out,TYPE_AMBULANCE_CENTER,i,location);
}
System.out.println("Placing "+fire.length+" fire stations");
for (int i=0;i<fire.length;++i) {
Building location = (Building)it.next();
it.remove();
FireStation a = new FireStation(location);
a.setID(location.getID());
fire[i] = a;
// writeFixedObjectData(out,TYPE_FIRE_STATION,i,location);
// System.out.print(".");
}
System.out.println("Placing "+police.length+" police stations");
for (int i=0;i<police.length;++i) {
Building location = (Building)it.next();
it.remove();
PoliceOffice a = new PoliceOffice(location);
a.setID(location.getID());
police[i] = a;
// writeFixedObjectData(out,TYPE_POLICE_OFFICE,i,location);
// System.out.print(".");
}
System.out.println("Placing "+refuge.length+" refuges");
for (int i=0;i<refuge.length;++i) {
Building location = (Building)it.next();
it.remove();
Refuge a = new Refuge(location);
a.setID(location.getID());
refuge[i] = a;
// writeFixedObjectData(out,TYPE_REFUGE,i,location);
// System.out.print(".");
}
// System.out.println();
return (Building[])remaining.toArray(new Building[0]);
}
public static void placeMovingObjects(FireBrigade[] fire, PoliceForce[] police, AmbulanceTeam[] ambulance, Civilian[] civ, Building[] b, Road[] r, Node[] n, boolean allowTrappedAgents, boolean trappedCivilians) {
RescueObject[] allLocations = new RescueObject[b.length+r.length+n.length];
System.arraycopy(b,0,allLocations,0,b.length);
System.arraycopy(r,0,allLocations,b.length,r.length);
System.arraycopy(n,0,allLocations,b.length+r.length,n.length);
RescueObject[] outsideLocations = new RescueObject[r.length+n.length];
System.arraycopy(r,0,outsideLocations,0,r.length);
System.arraycopy(n,0,outsideLocations,r.length,n.length);
System.out.println("Placing "+civ.length+" civilians");
for (int i=0;i<civ.length;++i) {
civ[i] = new Civilian();
civ[i].setPosition(randomLocation(trappedCivilians?b:allLocations).getID(),0,null);
// writeMovingObjectData(out,TYPE_CIVILIAN,i,randomLocation(trappedCivilians?b:allLocations));
// System.out.print(".");
}
// System.outln.println();
System.out.println("Placing "+ambulance.length+" ambulance teams");
for (int i=0;i<ambulance.length;++i) {
ambulance[i] = new AmbulanceTeam();
ambulance[i].setPosition(randomLocation(allowTrappedAgents?allLocations:outsideLocations).getID(),0,null);
// writeMovingObjectData(out,TYPE_AMBULANCE_TEAM,i,randomLocation(allowTrappedAgents?allLocations:outsideLocations));
// System.out.print(".");
}
// System.out.println();
System.out.println("Placing "+fire.length+" fire brigades");
for (int i=0;i<fire.length;++i) {
fire[i] = new FireBrigade();
fire[i].setPosition(randomLocation(allowTrappedAgents?allLocations:outsideLocations).getID(),0,null);
// writeMovingObjectData(out,TYPE_FIRE_BRIGADE,i,randomLocation(allowTrappedAgents?allLocations:outsideLocations));
// System.out.print(".");
}
// System.out.println();
System.out.println("Placing "+police.length+" police forces");
for (int i=0;i<police.length;++i) {
police[i] = new PoliceForce();
police[i].setPosition(randomLocation(allowTrappedAgents?allLocations:outsideLocations).getID(),0,null);
// writeMovingObjectData(out,TYPE_POLICE_FORCE,i,randomLocation(allowTrappedAgents?allLocations:outsideLocations));
// System.out.print(".");
}
// System.out.println();
}
public static Building[] placeNormalFires(int num, Building[] b) {
List remaining = new ArrayList();
for (int i=0;i<b.length;++i) remaining.add(b[i]);
Collections.shuffle(remaining);
Building[] result = new Building[num];
System.out.println("Placing "+num+" fires");
Iterator it = remaining.iterator();
for (int i=0;i<num;++i) result[i] = (Building)it.next();
return result;
}
public static Building[] placeBigFires(int num, Building[] b, Limits radius) {
List remaining = new ArrayList();
for (int i=0;i<b.length;++i) remaining.add(b[i]);
Collections.shuffle(remaining);
Collection fires = new HashSet();
System.out.print("Placing "+num+" big fires");
Iterator it = remaining.iterator();
for (int i=0;i<num;++i) {
Building center = (Building)it.next();
fires.add(center);
long r = radius.getNumber();
long distanceSquared = r*r;
// Check for close buildings
for (int j=0;j<b.length;++j) {
long dx = center.getX()-b[j].getX();
long dy = center.getY()-b[j].getY();
long distance = (dx*dx) + (dy*dy);
if (distance <= distanceSquared) fires.add(b[j]);
}
}
return (Building[])fires.toArray(new Building[0]);
}
public static RescueObject randomLocation(RescueObject[] possible) {
return possible[(int)(Math.random()*possible.length)];
}
// private static Node findNode(int id) {
// for (int i=0;i<allNodes.length;++i) if (allNodes[i].getID()==id) return allNodes[i];
// return null;
// }
private class Limits {
int min;
int max;
String prefix;
String name;
Limits(int min, int max, String prefix, String name) {
this.min = min;
this.max = max;
this.prefix = prefix;
this.name = name;
}
int getNumber() {
if (min==max) return min;
int range = max-min;
return (int)(Math.random()*range)+min;
}
}
}
/*
* Last change: $Date: 2004/08/10 20:47:10 $
* $Revision: 1.3 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import java.util.*;
import java.io.*;
import rescuecore.objects.Node;
import rescuecore.objects.Building;
public class RandomPolydata {
private final static int DEFAULT_CENTERS = 4;
private final static int DEFAULT_MAX_LEVEL = 4;
private final static int DEFAULT_MIN_LEVEL = 1;
private final static int DEFAULT_REPEAT = 1;
private final static int DEFAULT_MAX_SIZE = 50;
private final static int DEFAULT_MIN_SIZE = 10;
private static void printUsage() {
System.out.println("Usage: RandomPolydata [options]");
System.out.println("Options");
System.out.println("=======");
System.out.println("-n\t--num-centers\tThe number of epicenters");
System.out.println("-l\t--max-level\tThe maximum magnitude level");
System.out.println("-e\t--min-level\tThe minimum magnitude level");
System.out.println("-r\t--repeat-levels\tThe number of times to repeat levels");
System.out.println("-x\t--max-size\tThe maximum size of the polygons produced by each center as a proportion of the map size (100 means 100% of the map can be covered)");
System.out.println("-m\t--min-size\tThe minimum size of the polygons produced by each center as a proportion of the map size");
System.out.println("--box=left,right,top,bottom,magnitude");
}
public static void main(String[] args) {
int numCenters = DEFAULT_CENTERS;
int maxLevel = DEFAULT_MAX_LEVEL;
int minLevel = DEFAULT_MIN_LEVEL;
int repeat = DEFAULT_REPEAT;
int maxSize = DEFAULT_MAX_SIZE;
int minSize = DEFAULT_MIN_SIZE;
Collection boxes = new ArrayList();
for (int i=0;i<args.length;++i) {
if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--help")) {
printUsage();
return;
}
else if (args[i].equalsIgnoreCase("-n") || args[i].equalsIgnoreCase("--num-centers")) {
numCenters = Integer.parseInt(args[++i]);
}
else if (args[i].equalsIgnoreCase("-l") || args[i].equalsIgnoreCase("--max-level")) {
maxLevel = Integer.parseInt(args[++i]);
}
else if (args[i].equalsIgnoreCase("-e") || args[i].equalsIgnoreCase("--min-level")) {
minLevel = Integer.parseInt(args[++i]);
}
else if (args[i].equalsIgnoreCase("-r") || args[i].equalsIgnoreCase("--repeat-levels")) {
repeat = Integer.parseInt(args[++i]);
}
else if (args[i].equalsIgnoreCase("-x") || args[i].equalsIgnoreCase("--max-size")) {
maxSize = Integer.parseInt(args[++i]);
}
else if (args[i].equalsIgnoreCase("-m") || args[i].equalsIgnoreCase("--min-size")) {
minSize = Integer.parseInt(args[++i]);
}
else if (args[i].startsWith("--box")) {
StringTokenizer tokens = new StringTokenizer(args[i].substring(6),",");
double left = Double.parseDouble(tokens.nextToken());
double right = Double.parseDouble(tokens.nextToken());
double top = Double.parseDouble(tokens.nextToken());
double bottom = Double.parseDouble(tokens.nextToken());
int magnitude = Integer.parseInt(tokens.nextToken());
boxes.add(new Box(left,right,top,bottom,magnitude));
}
}
// Find the size of the city
Node[] allNodes;
Building[] allBuildings;
try {
allNodes = MapFiles.loadNodes();
allBuildings = MapFiles.loadBuildings();
}
catch (IOException e) {
e.printStackTrace();
return;
}
int minX = allNodes[0].getX();
int minY = allNodes[0].getY();
int maxX = minX;
int maxY = minY;
for (int i=0;i<allNodes.length;++i) {
minX = Math.min(minX,allNodes[i].getX());
maxX = Math.max(maxX,allNodes[i].getX());
minY = Math.min(minY,allNodes[i].getY());
maxY = Math.max(maxY,allNodes[i].getY());
}
for (int i=0;i<allBuildings.length;++i) {
minX = Math.min(minX,allBuildings[i].getX());
maxX = Math.max(maxX,allBuildings[i].getX());
minY = Math.min(minY,allBuildings[i].getY());
maxY = Math.max(maxY,allBuildings[i].getY());
}
int xRange = maxX-minX;
int yRange = maxY-minY;
Polygon[] shindo;
Polygon[] gal;
if (boxes.size()==0) {
List shindoPolygons = new ArrayList();
List galPolygons = new ArrayList();
int levelRange = maxLevel-minLevel;
// Place the epicenters
for (int i=0;i<numCenters;++i) {
int centerX = ((int)(Math.random()*xRange)) + minX;
int centerY = ((int)(Math.random()*yRange)) + minY;
int level = ((int)(Math.random()*levelRange)) + minLevel;
int repeats = ((int)(Math.random()*repeat)) + repeat;
// Generate the polygon
double xSize = Math.random()*(maxSize-minSize) + minSize;
int xExtent = (int)(xRange*xSize/100.0);
double ySize = Math.random()*(maxSize-minSize) + minSize;
int yExtent = (int)(yRange*ySize/100.0);
System.out.println("Placing level "+level+" epicenter at "+centerX+","+centerY+" with "+repeats+" repeats. Size is "+xExtent+" x "+yExtent);
// Let's make it an octagon numbered clockwise from zero at the top
int[] xs = new int[8];
int[] ys = new int[8];
xs[0] = xs[4] = centerX;
xs[1] = xs[3] = centerX + xExtent/2;
xs[2] = centerX + xExtent;
xs[5] = xs[7] = centerX - xExtent/2;
xs[6] = centerX - xExtent;
ys[0] = centerY + yExtent;
ys[1] = ys[7] = centerY + yExtent/2;
ys[2] = ys[6] = centerY;
ys[3] = ys[5] = centerY - yExtent/2;
ys[4] = centerY - yExtent;
for (int j=0;j<repeat;++j) {
shindoPolygons.add(new Polygon(level,xs,ys,8));
galPolygons.add(new Polygon(level,xs,ys,8));
}
}
shindo = new Polygon[shindoPolygons.size()];
gal = new Polygon[galPolygons.size()];
shindoPolygons.toArray(shindo);
galPolygons.toArray(gal);
}
else {
shindo = new Polygon[boxes.size()];
gal = new Polygon[boxes.size()];
int i=0;
System.out.println("World extends from "+minX+","+minY+" to "+maxX+","+maxY);
for (Iterator it = boxes.iterator();it.hasNext();i++) {
Box next = (Box)it.next();
int[] xs = new int[4];
int[] ys = new int[4];
int left = (int)((xRange * next.left)+minX);
int right = (int)((xRange * next.right)+minX);
int top = (int)((yRange * next.top)+minY);
int bottom = (int)((yRange * next.bottom)+minY);
xs[0] = xs[3] = left;
xs[1] = xs[2] = right;
ys[0] = ys[1] = top;
ys[2] = ys[3] = bottom;
shindo[i] = new Polygon(next.size,xs,ys,4);
gal[i] = new Polygon(next.size,xs,ys,4);
System.out.println("Putting box from "+left+","+top+" to "+right+","+bottom);
}
}
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("shindopolydata.dat")));
writePolydata(shindo,out);
out.flush();
out.close();
out = new PrintWriter(new BufferedWriter(new FileWriter("galpolydata.dat")));
writePolydata(gal,out);
out.flush();
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
private static void writePolydata(Polygon[] polygons, PrintWriter out) throws IOException {
// olydata format is:
// Line 1: <number of values to read, including the <level>,<number of vertices> pairs>,<number of polygons>
// Each polygon then has:
// <level>,<number of vertices>
// Followed by <number of vertices> pairs of coordinates
int sum = 0;
for (int i=0;i<polygons.length;++i) {
sum += polygons[i].numPoints*2;
sum += 2;
}
out.print(sum);
out.print(",");
out.println(polygons.length);
for (int i=0;i<polygons.length;++i) {
out.print(polygons[i].level);
out.print(",");
out.println(polygons[i].numPoints);
for (int j=0;j<polygons[i].numPoints;++j) {
out.print(polygons[i].xs[j]);
out.print(",");
out.println(polygons[i].ys[j]);
}
}
}
private static class Polygon {
int level;
int[] xs;
int[] ys;
int numPoints;
Polygon(int l, int[] x, int[] y, int num) {
level = l;
xs = x;
ys = y;
numPoints = num;
}
}
private static class Box {
double left,right,top,bottom;
int size;
public Box(double l, double r, double t, double b, int s) {
left = l;
right = r;
top = t;
bottom = b;
size = s;
}
}
}
/*
* Last change: $Date: 2005/02/18 03:34:34 $
* $Revision: 1.5 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools;
import java.io.*;
import java.util.*;
import rescuecore.*;
import rescuecore.objects.*;
import rescuecore.log.*;
/**
This class will calculate the score of a particular log file
*/
public class Score {
private final static String HEADER = "RoboCup-Rescue Prototype Log 00\0";
private final static String SILENT_FLAG = "--silent";
private final static String JUST_SCORE_FLAG = "--just-score";
private final static String KILL_FLAG = "--no-kill-civilians";
private static boolean silent;
private static boolean justScore;
private static boolean killCiviliansAtEnd;
private final static int VERBOSITY_NONE = 0;
private final static int VERBOSITY_SOME = 1;
private final static int VERBOSITY_LOTS = 2;
private final static int MODE_MAXIMUM = 0;
private final static int MODE_MINIMUM = 1;
private final static int MODE_AVERAGE = 2;
private final static int MODE_VARIANCE = 3;
private final static int MODE_STANDARD_DEVIATION = 4;
public static void main(String[] args) {
silent = false;
justScore = false;
killCiviliansAtEnd = true;
if (args.length==0) {
printUsage();
return;
}
List<String> fileNames = new ArrayList<String>();
for (int i=0;i<args.length;++i) {
if (args[i].equalsIgnoreCase(SILENT_FLAG)) {
silent = true;
}
else if (args[i].equalsIgnoreCase(JUST_SCORE_FLAG)) {
justScore = true;
}
else if (args[i].equalsIgnoreCase(KILL_FLAG)) {
killCiviliansAtEnd = false;
}
else {
fileNames.add(args[i]);
}
}
if (fileNames.size()==0) {
printUsage();
return;
}
List<LogScore> allScores = new ArrayList<LogScore>();
for (String next : fileNames) {
try {
if (!silent) System.err.println("Reading log "+next);
LogScore score = calculateScore(next);
if (score!=null) allScores.add(score);
}
catch (Exception e) {
e.printStackTrace();
}
}
LogScore[] scores = new LogScore[allScores.size()];
allScores.toArray(scores);
if (justScore || scores.length==1) {
for (int i=0;i<scores.length;++i) System.out.println(scores[i].score);
}
else {
LogScore max = new LogScore("Highest",scores,MODE_MAXIMUM);
LogScore min = new LogScore("Lowest",scores,MODE_MINIMUM);
LogScore average = new LogScore("Average",scores,MODE_AVERAGE);
LogScore variance = new LogScore("Variance",scores,MODE_VARIANCE);
LogScore sd = new LogScore("Standard deviation",scores,MODE_STANDARD_DEVIATION);
System.out.println("Run\tBuilding area left\tBuilding area total\tHP left\tHP total\tCivilians alive\tTotal civilians\tAgents alive\tTotal agents\tScore from HP\tScore from buildings\tOverall score");
for (int i=0;i<scores.length;++i) {
scores[i].write();
}
System.out.println();
if (scores.length>1) {
System.out.println("\tBuilding area left\tBuilding area total\tHP left\tHP total\tCivilians alive\tTotal civilians\tAgents alive\tTotal agents\tScore from HP\tScore from buildings\tOverall score");
max.write();
min.write();
average.write();
variance.write();
sd.write();
}
}
}
private static LogScore calculateScore(String filename) throws IOException, InvalidLogException {
Log log = Log.generateLog(filename);
return new LogScore(filename,log.getMemory(log.getMaxTimestep()),killCiviliansAtEnd);
}
private static void printUsage() {
System.out.println("Usage: Score [options] <log files>");
System.out.println("Options");
System.out.println("=======");
System.out.println(SILENT_FLAG+"\tSilent mode. No progress indicators will be emitted.");
System.out.println(JUST_SCORE_FLAG+"\tDon't calculate any statistics about the scores.");
System.out.println(KILL_FLAG+"\tDon't consider buried or damaged civilians to be dead.");
}
private static double calculate(double[] values, int mode) {
double result, average;
switch (mode) {
case MODE_MAXIMUM:
result = values[0];
for (int i=0;i<values.length;++i) result = Math.max(result,values[i]);
return result;
case MODE_MINIMUM:
result = values[0];
for (int i=0;i<values.length;++i) result = Math.min(result,values[i]);
return result;
case MODE_AVERAGE:
result = 0;
for (int i=0;i<values.length;++i) result += values[i];
return result/values.length;
case MODE_VARIANCE:
average = 0;
for (int i=0;i<values.length;++i) average += values[i];
average/=values.length;
result = 0;
for (int i=0;i<values.length;++i) result += (values[i]-average)*(values[i]-average);
return result/(values.length-1);
case MODE_STANDARD_DEVIATION:
average = 0;
for (int i=0;i<values.length;++i) average += values[i];
average/=values.length;
result = 0;
for (int i=0;i<values.length;++i) result += (values[i]-average)*(values[i]-average);
return Math.sqrt(result/(values.length-1));
}
throw new RuntimeException("Unknown mode: "+mode);
}
private static class LogScore {
String name;
double score, HPscore, buildingScore, areaMax, areaLeft, hpMax, hpLeft, civilians, civiliansAlive, agents, agentsAlive;
public LogScore(String name, LogScore[] scores, int mode) {
this.name = name;
double[][] values = new double[11][scores.length];
for (int i=0;i<scores.length;++i) {
values[0][i] = scores[i].score;
values[1][i] = scores[i].HPscore;
values[2][i] = scores[i].buildingScore;
values[3][i] = scores[i].areaMax;
values[4][i] = scores[i].areaLeft;
values[5][i] = scores[i].hpMax;
values[6][i] = scores[i].hpLeft;
values[7][i] = scores[i].civilians;
values[8][i] = scores[i].civiliansAlive;
values[9][i] = scores[i].agents;
values[10][i] = scores[i].agentsAlive;
}
score = calculate(values[0],mode);
HPscore = calculate(values[1],mode);
buildingScore = calculate(values[2],mode);
areaMax = calculate(values[3],mode);
areaLeft = calculate(values[4],mode);
hpMax = calculate(values[5],mode);
hpLeft = calculate(values[6],mode);
civilians = calculate(values[7],mode);
civiliansAlive = calculate(values[8],mode);
agents = calculate(values[9],mode);
agentsAlive = calculate(values[10],mode);
}
public LogScore(String name, Memory state, boolean killCivilians) {
this.name = name;
Collection<RescueObject> allBuildings = state.getObjectsOfType(RescueConstants.TYPE_BUILDING,RescueConstants.TYPE_REFUGE,RescueConstants.TYPE_FIRE_STATION,RescueConstants.TYPE_POLICE_OFFICE,RescueConstants.TYPE_AMBULANCE_CENTER);
Collection<RescueObject> allAgents = state.getObjectsOfType(RescueConstants.TYPE_CIVILIAN,RescueConstants.TYPE_FIRE_BRIGADE,RescueConstants.TYPE_POLICE_FORCE,RescueConstants.TYPE_AMBULANCE_TEAM);
areaMax = 0;
areaLeft = 0;
hpMax = 0;
hpLeft = 0;
civilians = 0;
civiliansAlive = 0;
agents = allAgents.size();
agentsAlive = 0;
// System.out.println(allBuildings.length+" buildings");
for (RescueObject b : allBuildings) {
Building next = (Building)b;
double area = next.getTotalArea();
areaMax += area;
// System.out.println(next.toLongString());
// System.out.println("Next building area, fieryness: "+area+", "+next.getFieryness());
switch (next.getFieryness()) {
case RescueConstants.FIERYNESS_NOT_BURNT:
areaLeft += area;
break;
case RescueConstants.FIERYNESS_HEATING:
case RescueConstants.FIERYNESS_SLIGHTLY_BURNT:
case RescueConstants.FIERYNESS_WATER_DAMAGE:
areaLeft += area*2.0/3.0;
break;
case RescueConstants.FIERYNESS_BURNING:
case RescueConstants.FIERYNESS_MODERATELY_BURNT:
areaLeft += area/3.0;
case RescueConstants.FIERYNESS_VERY_BURNT:
case RescueConstants.FIERYNESS_INFERNO:
case RescueConstants.FIERYNESS_BURNT_OUT:
break;
}
// System.out.println("New total area, area left: "+areaMax+", "+areaLeft);
}
for (RescueObject a : allAgents) {
Humanoid next = (Humanoid)a;
if (killCivilians) {
if (next.isCivilian() && (next.isDamaged() || next.isBuried())) next.setHP(0,3000,null);
}
if (next.isAlive()) ++agentsAlive;
if (next.isCivilian()) {
++civilians;
if (next.isAlive()) ++civiliansAlive;
}
hpMax += RescueConstants.MAX_HP;
hpLeft += next.getHP();
}
HPscore = agentsAlive + (hpLeft/hpMax);
buildingScore = Math.sqrt(areaLeft/areaMax);
score = HPscore * buildingScore;
}
public void write() {
System.out.print(name);
System.out.print("\t");
System.out.print(areaLeft);
System.out.print("\t");
System.out.print(areaMax);
System.out.print("\t");
System.out.print(hpLeft);
System.out.print("\t");
System.out.print(hpMax);
System.out.print("\t");
System.out.print(civiliansAlive);
System.out.print("\t");
System.out.print(civilians);
System.out.print("\t");
System.out.print(agentsAlive);
System.out.print("\t");
System.out.print(agents);
System.out.print("\t");
System.out.print(HPscore);
System.out.print("\t");
System.out.print(buildingScore);
System.out.print("\t");
System.out.println(score);
}
}
}
/*
* Last change: $Date: 2004/05/04 03:09:39 $
* $Revision: 1.2 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools.mapgenerator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
/**
* A road weighter that decides on road importance by making 10,000 trips
* through the RescueMap between random pairs of nodes.
*
* @author Jonathan Teutenberg
* @version 1.0 Aug 2003
**/
public class AntsRoadWeighter implements RoadWeighter {
/** Number of runs to use to determine main roads. **/
private static final int RUNS = 15000;
/** Base percentage of 3 lane roads. **/
private static final int THREELANE = 10;
/** Base percentage of 2 lane roads. **/
private static final int TWOLANE = 20;
/** A count of how many times each road (adjacent node pair) has been used. **/
private int[][] usedCount;
/** The Euclidean distances between all pairs of nodes. **/
private int[][] distances;
public void connect(RescueMap rm, int uniformity, boolean nooneway, Random rand) {
int nodes = rm.getNodeCount();
// store all the distances
distances = new int[nodes][nodes];
for (int i = 0; i < nodes; i++)
for (int j = 0; j < i; j++) {
int x = rm.getX(i) - rm.getX(j);
int y = rm.getY(i) - rm.getY(j);
distances[i][j] = (int) Math.sqrt(x * x + y * y);
distances[j][i] = distances[i][j];
}
// record how often each road is used
usedCount = new int[nodes][nodes];
System.out.print("Simulating road use.");
System.out.flush();
int steps = RUNS / 20;
// two arrays to be used in the searches
int[] prevs = new int[nodes];
int[] dists = new int[nodes];
for (int i = 0; i < RUNS; i++) {
int[] picked = pickNodes(rm, rand);
runPath(prevs, dists, rm, picked[0], picked[1]);
if (i % steps == 0) {
System.out.print(".");
System.out.flush();
}
}
System.out.println("done.");
// find the two cutoffs
ArrayList l = new ArrayList(nodes * 5);
for (int i = 0; i < nodes; i++)
for (int j = 0; j < nodes; j++)
if (rm.getRoad(i, j) > 0) {
l.add(Integer.valueOf(usedCount[i][j]));
}
Collections.sort(l);
int index1 = (int) (l.size() * (1 - THREELANE / 100.0));
int v1 = ((Integer) (l.get(index1))).intValue();
int v2 = ((Integer) (l.get(index1 - (int) (l.size() * TWOLANE / 100.0)))).intValue();
// now upgrade the roads
for (int i = 0; i < nodes; i++)
for (int j = 0; j < nodes; j++) {
if (usedCount[i][j] >= v1 || (nooneway && usedCount[j][i] >= v1)) {
rm.setRoad(i, j, 3);
if (nooneway)
rm.setRoad(j, i, 3);
} else if (usedCount[i][j] >= v2 || (nooneway && usedCount[j][i] >= v2)) {
rm.setRoad(i, j, 2);
if (nooneway)
rm.setRoad(j, i, 2);
}
}
}
public int[] pickNodes(RescueMap rm, Random rand) {
return new int[] { (int) (rand.nextDouble() * rm.getNodeCount()), (int) (rand.nextDouble() * rm.getNodeCount()) };
}
private void runPath(int[] prevs, int[] dists, RescueMap rm, int start, int end) {
int nodes = rm.getNodeCount();
// find shortest path with A*
for (int i = 0; i < dists.length; i++)
dists[i] = Integer.MAX_VALUE;
PairHeap q = new PairHeap();
prevs[start] = -1;
dists[start] = distances[start][end];
int next = start;
while (next != end) {
// update every neighbour of next - add if necessary
for (int j = 0; j < nodes; j++) {
if (j != next && rm.getRoad(next, j) > 0) { // connected
int guess = dists[next] + distances[next][j] + distances[j][end];
if (dists[j] > guess) {
// update!
dists[j] = guess;
prevs[j] = next;
q.insert(j, guess);
}
}
}
next = q.deleteMin();
}
// now extract the path
int prev = end;
while (prevs[prev] != -1) {
usedCount[prevs[prev]][prev]++;
prev = prevs[prev];
}
}
}
\ No newline at end of file
/*
* Last change: $Date: 2004/08/10 21:20:24 $
* $Revision: 1.5 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools.mapgenerator;
import java.util.*;
/**
* A BuildingGenerator that recursively chops a block into rectangular buildings.
* @author Jonathan Teutenberg
* @version 1.0 Aug 2003
**/
public class BasicBuildingGenerator extends BlocksBuildingGenerator{
/**
* Divides a block into a number of rectangular buildings.
* @param rm The RescueMap containing the block.
* @param block A list of nodes in anti-clockwise order around the block.
* @param density The density of buildings to add.
* @param rand The random number generator.
* @return Buildings to add as an array of form [building][apex][coordinate]
**/
protected int[][][] fillBlock(RescueMap rm, int[] block,int density, Random rand){
//make a building filling the whole block
int[][] build = new int[block.length+1][2];
for(int i = 0; i < block.length; i++){
build[i][0] = rm.getX(block[i]);
build[i][1] = rm.getY(block[i]);
if(i > 0 && i < block.length-1)
shift(rm,block[i-1],block[i],block[i+1],build[i]);
}
shift(rm,block[block.length-1],block[0],block[1],build[0]);
shift(rm,block[block.length-2],block[block.length-1],block[0],build[build.length-2]);
build[build.length-1][0] = build[0][0];
build[build.length-1][1] = build[0][1];
//now break it up
int minArea = 500000/(density+1);
ArrayList builds = processBuilding(build,minArea,rand);
int[][][] bs = new int[builds.size()][][];
for(int i = 0; i < bs.length; i++) {
bs[i] = (int[][])builds.get(i);
shrink(bs[i],rand.nextDouble()*0.4);
}
return bs;
}
private void shrink(int[][] building, double amount) {
int xMin = building[0][0];
int xMax = building[0][0];
int yMin = building[0][1];
int yMax = building[0][1];
for (int i=1;i<building.length;++i) {
xMin = Math.min(xMin,building[i][0]);
xMax = Math.max(xMax,building[i][0]);
yMin = Math.min(yMin,building[i][1]);
yMax = Math.max(yMax,building[i][1]);
}
int xCenter = (xMin+xMax)/2;
int yCenter = (yMin+yMax)/2;
for (int i=0;i<building.length;++i) {
double dx = building[i][0]-xCenter;
double dy = building[i][1]-yCenter;
building[i][0] -= (int)(dx*amount);
building[i][1] -= (int)(dy*amount);
}
}
/**
* No buildings returned - just have an empty outer rim.
* @param rm The RescueMap containing the block.
* @param block A list of nodes in anti-clockwise order around the block.
* @param density The density of buildings to add.
* @param rand The random number generator.
* @return Buildings to add as an array of form [building][apex][coordinate]
**/
protected int[][][] fillOuterBlock(RescueMap rm, int[] block, int density,Random rand){
return new int[0][][];
}
/**
* Shifts a set of coordinates in the direction normal to the two adjacent road.
* Assumes n1 --> n2 --> n3 is an anticlockwise motion.
* @param n1 First node of the roads.
* @param n2 Middle node of the two roads
* @param n3 The last node of the two roads
* @param c1 The set of coordinates to shift
**/
private static void shift(RescueMap rm, int n1, int n2, int n3, int[] c){
//get the normal to the first road
long n1y = rm.getX(n2) - rm.getX(n1);
long n1x = rm.getY(n1) - rm.getY(n2);
//get normal to the second road
long n2y = rm.getX(n3) - rm.getX(n2);
long n2x = rm.getY(n2) - rm.getY(n3);
//get length of each normal
double len1 = Math.sqrt(n1y*n1y+n1x*n1x);
double len2 = Math.sqrt(n2y*n2y+n2x*n2x);
int d = 3000;//Math.max(rm.getRoad(n1,n2),rm.getRoad(n2,n3))*2000 +500;
int x1 = rm.getX(n1) - (int)(n1x*d*1.0/len1);
int x2 = rm.getX(n2) - (int)(n1x*d*1.0/len1);
int y1 = rm.getY(n1) - (int)(n1y*d*1.0/len1);
int y2 = rm.getY(n2) - (int)(n1y*d*1.0/len1);
int x3 = rm.getX(n2) - (int)(n2x*d*1.0/len2);
int x4 = rm.getX(n3) - (int)(n2x*d*1.0/len2);
int y3 = rm.getY(n2) - (int)(n2y*d*1.0/len2);
int y4 = rm.getY(n3) - (int)(n2y*d*1.0/len2);
int[] intersect = intersection(x1,y1,x2,y2,x3,y3,x4,y4);
if(intersect == null){
c[0] -= (n1x/len1)*d;
c[1] -= (n1y/len1)*d;
}
else{
c[0] = intersect[0];
c[1] = intersect[1];
}
}
/**
* Where two line segments intersect.
**/
private static int[] intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
double b1 = (y2 - y1)/(x2 - x1);
double a1 = y1 - (b1*x1);
double b2 = (y4 - y3)/(x4 - x3);
double a2 = y3 - (b2*x3);
if(x2-x1 == 0) //vertical
return new int[]{(int)x1,(int)(a2+(b2*x1))};
if(x3-x4 == 0) //vertical
return new int[]{(int)x3,(int)(a1+(b1*x3))};
/* if(Math.abs(b1-b2) < 0.001)
return null;
double intX = -(a1-a2)/(b1-b2);
double intY = a1+(b1*intX);*/
double d = ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
if(d == 0)
return null; //parallel roads
double a = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))*1.0/d;
int intX = (int)x1+(int)(a*(x2-x1));
int intY = (int)y1+(int)(a*(y2-y1));
return new int[]{(int)intX,(int)intY};
}
/**
* Recursively splits a building in half, until it is lower than the given threshold
* or gets lucky when within a reasonable size.
* @param building The initial building to split.
* @param minArea The lower threshold that forms the base case.
* @param rand The random number generator.
* @return A list containing all buildings split through recursive calls.
**/
private ArrayList processBuilding(int[][] building, int minArea, Random rand){
int a = RescueMapToolkit.area(building);
//System.out.println(minArea+", "+a);
if(a < 1000) //kill these ones...
return new ArrayList(0);
if(a < minArea){ //primary base case
ArrayList l = new ArrayList(1);
l.add(building);
return l;
}
int lower = (int)(rand.nextDouble()*minArea);
lower = lower*4;
if(a < lower){ //probabilistic base case
ArrayList l = new ArrayList(1);
l.add(building);
return l;
}
//find the max and min points
int minX = building[0][0];
int minY = building[0][1];
int maxX = building[0][0];
int maxY = building[0][1];
for(int i = 1; i < building.length; i++){
if(minX > building[i][0]) minX = building[i][0];
if(maxX < building[i][0]) maxX = building[i][0];
if(minY > building[i][1]) minY = building[i][1];
if(maxY < building[i][1]) maxY = building[i][1];
}
int midX = (minX+maxX)/2;
int midY = (minY+maxY)/2;
//split the building in half
int[][][] split;
if(maxX-minX > maxY-minY)
split = RescueMapToolkit.split(building,midX,minY,midX,maxY);
else
split = RescueMapToolkit.split(building,minX,midY,maxX,midY);
if(split == null || RescueMapToolkit.area(split[0]) == 0 || RescueMapToolkit.area(split[1]) == 0)
return new ArrayList(0);
//and recurse
ArrayList a1 = processBuilding(split[0],minArea,rand);
ArrayList a2 = processBuilding(split[1],minArea,rand);
ArrayList toRet = new ArrayList(a1.size()+a2.size());
for(int i = 0; i < a1.size(); i++)
toRet.add(a1.get(i));
for(int i = 0; i < a2.size(); i++)
toRet.add(a2.get(i));
return toRet;
}
}
/*
* Last change: $Date: 2004/05/04 03:09:39 $
* $Revision: 1.2 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools.mapgenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
/**
* An abstract class that provides functionality for adding buildings to a
* RescueMap one city block at a time.
*
* @author Jonathan Teutenberg
* @version 1.0 Aug 2003
**/
public abstract class BlocksBuildingGenerator implements BuildingGenerator {
/** The outer ring of roads. **/
private int[] outerBlock;
/**
* Adds the buildings.
*
* @param rm The RescueMap to add to.
* @param uniformity The regularity amongst buildings.
* @param buildDensity The density of the buildings.
* @param rand The random number generator.
**/
public void addBuildings(RescueMap rm, int uniformity, int buildDensity, Random rand) {
int[][] blocks = getBlocks(rm);
System.out.println("Filling blocks");
for (int i = 0; i < blocks.length; i++) {
int[][][] builds = fillBlock(rm, blocks[i], buildDensity, rand);
for (int j = 0; j < builds.length; j++) {
int[] centre = RescueMapToolkit.centre(builds[j]);
rm.addBuilding(builds[j], RescueMapToolkit.makeEntrance(rm, centre), (int) (rand.nextDouble() * 4) + 1, 0);
}
System.out.println(i + " of " + blocks.length);
}
int[][][] builds = fillOuterBlock(rm, outerBlock, buildDensity, rand);
for (int j = 0; j < builds.length; j++) {
int[] centre = RescueMapToolkit.centre(builds[j]);
rm.addBuilding(builds[j], RescueMapToolkit.makeEntrance(rm, centre), (int) (rand.nextDouble() * 4) + 1, 0);
}
}
/**
* Give a list of buildings for a block. This should not do the adding of
* buildings.
*
* @param rm The RescueMap containing the block.
* @param block A list of nodes in anti-clockwise order around the block.
* @param buildDensity The density of buildings to add.
* @param rand The random number generator.
* @return Buildings to add as an array of form [building][apex][coordinate]
**/
protected abstract int[][][] fillBlock(RescueMap rm, int[] block, int buildDensity, Random rand);
/**
* Give a list of buildings for the outside of the city.
*
* @param rm The RescueMap containing the block.
* @param block A list of nodes in anti-clockwise order around the block.
* @param buildDensity The density of buildings to add.
* @param rand The random number generator.
* @return Buildings to add as an array of form [building][apex][coordinate]
**/
protected abstract int[][][] fillOuterBlock(RescueMap rm, int[] block, int buildDensity, Random rand);
/**
* Gets a list of city blocks.
*
* @param m The RescueMap to find the blocks of.
* @return Blocks as an array of arrays of nodes: [blocks][nodes]
**/
private int[][] getBlocks(RescueMap m) {
int[][] rs = m.getRoads();
HashMap visited = new HashMap();
ArrayList blocks = new ArrayList(100);
for (int i = 0; i < rs.length; i++) {
Integer vis = (Integer) visited.get(hash(rs[i]));
int v = 0;
if (vis != null)
v = vis.intValue();
if ((v & 1) == 0) {
v = v | 1;
visited.put(hash(rs[i]), Integer.valueOf(v));
// walk head-tail circuit
int[] c = walkCircuit(m, rs[i], visited, true);
if (c.length > 0)
blocks.add(c);
}
if ((v & 2) == 0) {
v = v | 2;
visited.put(hash(rs[i]), Integer.valueOf(v));
// walk tail-head circuit
int[] c = walkCircuit(m, rs[i], visited, false);
if (c.length > 0)
blocks.add(c);
}
}
int[][] blks = new int[blocks.size()][];
blocks.toArray(blks);
return blks;
}
/**
* Creates a hash key for a road.
**/
private static Integer hash(int[] road) {
int a = Math.min(road[0], road[1]);
int b = Math.max(road[0], road[1]);
return Integer.valueOf(b * 10000 + a);
}
/**
* Walks around a block in an anti-clockwise direction This also marks each road
* visited in the 'visited' map.
*
* @param curr The road to begin with.
* @param visited A mapping from nodes to their visited status (either not
* visited, visited in one direction, or visited in both
* directions.
* @param isTail Whether the next road to visit starts at curr's tail or not.
* @return An inorder list of nodes in the circuit (block).
**/
private int[] walkCircuit(RescueMap m, int[] curr, HashMap visited, boolean isTail) {
ArrayList circ = new ArrayList(20);
double totalAngle = 0;
int t = 0;
int s = 1;
if (isTail) {
t = 1;
s = 0;
}
int[] first = { curr[t], curr[s] };
circ.add(Integer.valueOf(curr[t]));
do {
circ.add(Integer.valueOf(curr[s]));
int[] nbs = m.getUnderlyingNeighbours(curr[s]);
// get the neighbour with largest angle
int ind = 0;
double maxAngle = -Math.PI;
double angle;
for (int k = 0; k < nbs.length; k++) {
if (nbs[k] == curr[t]) // no going back!
continue;
angle = RescueMapToolkit.angle(m, curr[t], curr[s], nbs[k]);
// we want the smallest angle greater than 180, otherwise the smallest less than
// 180.
if (angle > maxAngle) {
maxAngle = angle;
ind = k;
}
}
totalAngle += maxAngle;
// make it current, and set its visited status
curr[t] = curr[s];
curr[s] = nbs[ind];
Integer val = (Integer) visited.get(hash(curr));
int v = 0;
if (val != null)
v = val.intValue();
if (curr[s] > curr[t])
visited.put(hash(curr), Integer.valueOf(v | 1));
else
visited.put(hash(curr), Integer.valueOf(v | 2));
} while (curr[s] != first[0]);
int[] rs = new int[circ.size()];
for (int i = 0; i < rs.length; i++)
rs[i] = ((Integer) circ.get(i)).intValue();
if (totalAngle <= 0) { // wrong direction - happens with boundary roads
outerBlock = rs;
return new int[0];
}
return rs;
}
}
\ No newline at end of file
/*
* Last change: $Date: 2004/05/04 03:09:39 $
* $Revision: 1.2 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore.tools.mapgenerator;
import java.util.Random;
/**
* Interface to classes that add buildings to a RescueMap.
* @author Jonathan Teutenberg
* @version 1.0 Aug 2003
**/
public interface BuildingGenerator{
/**
* Adds the buildings.
* @param rm The RescueMap to add to.
* @param uniformity The regularity amongst buildings.
* @param buildDensity The density of the buildings.
* @param rand The random number generator.
**/
public void addBuildings(RescueMap rm, int uniformity, int buildDensity,Random rand);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment