* 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.
*/
packagerescuecore;
importjava.io.*;
importrescuecore.debug.*;
importrescuecore.commands.*;
/**
This is the base class for all agents. This class handles messages from the server, provides a memory of the simulation environment and convenience methods for path planning etc. This class also enforces the message limits imposed by the robocup rescue rules.
<p>Agent implementations should provide at least one of the following three constructors:
<ol><li>A no-arg constructor - e.g. MyAgent()
<li>A String[] constructor - e.g. MyAgent(String[] args)
<li>A constructor that takes one or more String arguments - e.g. MyAgent(String arg1, String arg2)
</ol>
The reason for this is that the AgentSystem allows arguments to be passed to the Agent via the command line. When creating an instance of the agent it first looks for any constructor that accepts the right number of String arguments, followed by the String[] constructor. Failing that, the no-arg constructor will be used.
<p>
For example, assuming we have the three constructors mentioned above, if the command line provides two arguments then the AgentSystem will use the MyAgent(String arg1, String arg2) constructor. If only one argument is provided then the MyAgent(String[] args) constructor is used.
System.out.println("Connect succeeded for "+tempID+". Kernel assigned id:"+id);
try{
RescueObject[]knowledge=ok.getKnowledge();
// Initialise
initialise(knowledge);
// Send AK_ACKNOWLEDGE
RescueMessageack=newRescueMessage();
ack.append(newAKAcknowledge(requestID,id));
sendMessage(ack);
}
catch(Exceptione){
System.out.println(e);
e.printStackTrace();
}
timeStep=0;
running=true;
returntrue;
}
else{
System.out.println("Received a KA_CONNECT_OK for agent "+requestID+", but I'm listening for a reply for "+tempID);
}
returnfalse;
}
publicfinalStringhandleConnectError(Commandc){
KAConnectErrorerror=(KAConnectError)c;
intrequestID=error.getRequestID();
Stringreason=error.getReason();
if(requestID==tempID)
returnreason;
else
System.out.println("Received a KA_CONNECT_ERROR ("+reason+") for agent "+requestID+", but I'm listening for a reply for "+tempID);
returnnull;
}
publicbooleanisRunning(){
returnrunning;
}
publicvoidshutdown(){
running=false;
}
publicfinalvoidhandleMessage(Commandc){
// System.out.println("Handling "+c);
switch(c.getType()){
caseRescueConstants.KA_SENSE:
handleSense((KASense)c);
break;
caseRescueConstants.KA_HEAR:
caseRescueConstants.KA_HEAR_SAY:
caseRescueConstants.KA_HEAR_TELL:
handleHear(c);
break;
caseRescueConstants.KA_CONNECT_OK:
if(running){
// Someone obviously didn't get our AK_ACKNOWLEDGE
KAConnectOKok=(KAConnectOK)c;
intrequestID=ok.getRequestID();
System.out.println(this+" just received a KA_CONNECT_OK to "+requestID+" - my tempID is "+tempID);
if(requestID==tempID){
intnewID=ok.getAgentID();
System.out.println("Old ID: "+id+", new ID: "+newID);
id=newID;
RescueMessageack=newRescueMessage();
ack.append(newAKAcknowledge(requestID,id));
sendMessage(ack);
}
}
break;
default:
handleOtherMessage(c);
break;
}
logObject(c);
}
protectedvoidhandleOtherMessage(Commandc){
System.out.println("Timestep "+timeStep+": "+this+" received a weird command: "+Handy.getCommandTypeName(c.getType()));
}
/**
Handle a KA_SENSE message
@param c The KA_SENSE Command object
*/
privatevoidhandleSense(Commandc){
// System.out.println("Last timestep ("+timeStep+") "+this+" sent "+numSent+" messages and received "+numReceived);
KASensesense=(KASense)c;
// numSent = numReceived = 0;
try{
intnewTimeStep=sense.getTime();
if(newTimeStep<timeStep)System.err.println(this+" just moved back in time! It was timestep "+timeStep+" and now it's timestep "+newTimeStep);
if(newTimeStep>timeStep+1)System.err.println(this+" just skipped ahead in time! It was timestep "+timeStep+" and now it's timestep "+newTimeStep);
timeStep=newTimeStep;
memory.update(sense);// Update the memory
}
catch(Exceptione){
e.printStackTrace();
}
// long start = System.currentTimeMillis();
sense();
// long end = System.currentTimeMillis();
// System.out.println("Sense took "+(end-start)+"ms for "+this);
flushCommands();
// Flush the log
DebugWriter.flush(this);
}
/**
Handle a KA_HEAR (or KA_HEAR_SAY, or KA_HEAR_TELL) message
@param hear The KA_HEAR Command object.
@see RescueConstants#KA_HEAR
@see RescueConstants#KA_HEAR_SAY
@see RescueConstants#KA_HEAR_TELL
*/
privatevoidhandleHear(Commandc){
KAHearhear=(KAHear)c;
inttoID=hear.getToID();
intfromID=hear.getFromID();
intlength=hear.getLength();
byte[]msg=hear.getData();
bytechannel=hear.getChannel();
// System.out.println(Handy.getCommandTypeName(type)+" received by "+id+" from "+fromID+" - have already accepted "+numReceived+" messages of "+receiveMax+" this timestep");
// if (willListenHear(fromID) && canListen()) {
// System.out.println("Hear from "+fromID+" to "+toID+" on channel "+channel);
hear(fromID,msg,channel);
// ++numReceived;
// }
}
/*
private boolean canListen() {
if (numReceived < receiveMax) return true;
System.err.println("WARNING: "+this+" tried to receive too many messages in timestep "+timeStep+" (maximum="+receiveMax+")");
Construct a new Memory object for use by this Agent. This method allows Agents to customise their choice of Memory object. The default implementation returns a {@link HashMemory}.
@return A new Memory object
*/
protectedMemorygenerateMemory(){
returnnewHashMemory();
}
/**
Called after a KA_SENSE is received
*/
protectedabstractvoidsense();
/**
Called after a KA_HEAR is received
@param from The agent that sent the message
@param msg The message body
@param channel The channel that this message was received on
* 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.
*/
packagerescuecore;
importjava.util.*;
/**
This is an implementation of Memory that stores the data in an array
*/
publicclassArrayMemoryextendsMemory{
privatefinalstaticintDEFAULT_MEMORY_SIZE=3000;
privatefinalstaticintDEFAULT_RESIZE_FACTOR=1000;
protectedRescueObject[]data;
privateintdataSize;
privateintresizeFactor;
/**
Construct a new empty memory
*/
publicArrayMemory(){
this(DEFAULT_MEMORY_SIZE,DEFAULT_RESIZE_FACTOR);
}
/**
Construct a new empty memory
@param size The initial size of the array
@param factor The amount to increase the array by if we run out of room
* 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.
*/
packagerescuecore;
/**
This class encapsulates information about an array property
ArrayProperty result = ArrayProperty(type,values,null);
result.numValues = numValues;
return result;
}
*/
publicint[]getValues(){
int[]result=newint[numValues];
System.arraycopy(values,0,result,0,numValues);
returnresult;
}
publicStringgetStringValue(){
StringBufferresult=newStringBuffer();
result.append("[");
for(inti=0;i<numValues;++i){
result.append(values[i]);
if(i<numValues-1)result.append(",");
}
result.append("]");
returnresult.toString();
}
/**
Set the values of this property. The timestamp will also be updated. Note that this method does not check that the update is newer than the current value - it is up to the application to test for this.
@param newValues The new values
@param timestamp The timestamp of this update
@param source The source of this update
@return true if and only if the values were actually changed, i.e the new values are different from the old ones
Update the values of this property. The timestamp will also be updated.
@param newValues The new values
@param timestamp The timestamp of this update
@param source The source of this update
@return true if and only if the values were actually changed, i.e the new values are different from the old ones and the new timestamp is greater than the old timestamp