/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.app.virus;
import sim.field.continuous.*;
import sim.engine.*;
import sim.util.*;
public /*strictfp*/ class VirusInfectionDemo extends SimState
{
private static final long serialVersionUID = 1;
public static final double XMIN = 0;
public static final double XMAX = 800;
public static final double YMIN = 0;
public static final double YMAX = 600;
public static final double DIAMETER = 8;
public static final double HEALING_DISTANCE = 20;
public static final double HEALING_DISTANCE_SQUARED = HEALING_DISTANCE * HEALING_DISTANCE;
public static final double INFECTION_DISTANCE = 20;
public static final double INFECTION_DISTANCE_SQUARED = INFECTION_DISTANCE * INFECTION_DISTANCE;
public static final int NUM_HUMANS = 100;
public static final int NUM_GOODS = 4;
public static final int NUM_EVILS = 4;
public Continuous2D environment = null;
/** Creates a VirusInfectionDemo simulation with the given random number seed. */
public VirusInfectionDemo(long seed)
{
super(seed);
}
boolean conflict( final Agent agent1, final Double2D a, final Agent agent2, final Double2D b )
{
if( ( ( a.x > b.x && a.x < b.x+DIAMETER ) ||
( a.x+DIAMETER > b.x && a.x+DIAMETER < b.x+DIAMETER ) ) &&
( ( a.y > b.y && a.y < b.y+DIAMETER ) ||
( a.y+DIAMETER > b.y && a.y+DIAMETER < b.y+DIAMETER ) ) )
{
return true;
}
return false;
}
public boolean withinInfectionDistance( final Agent agent1, final Double2D a, final Agent agent2, final Double2D b )
{
return ( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) <= INFECTION_DISTANCE_SQUARED );
}
public boolean withinHealingDistance( final Agent agent1, final Double2D a, final Agent agent2, final Double2D b )
{
return ( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) <= HEALING_DISTANCE_SQUARED );
}
boolean acceptablePosition( final Agent agent, final Double2D location )
{
if( location.x < DIAMETER/2 || location.x > (XMAX-XMIN)/*environment.getXSize()*/-DIAMETER/2 ||
location.y < DIAMETER/2 || location.y > (YMAX-YMIN)/*environment.getYSize()*/-DIAMETER/2 )
return false;
Bag mysteriousObjects = environment.getNeighborsWithinDistance( location, 2*DIAMETER );
if( mysteriousObjects != null )
{
for( int i = 0 ; i < mysteriousObjects.numObjs ; i++ )
{
if( mysteriousObjects.objs[i] != null && mysteriousObjects.objs[i] != agent )
{
Agent ta = (Agent)(mysteriousObjects.objs[i]);
if( conflict( agent, location, ta, environment.getObjectLocation(ta) ) )
return false;
}
}
}
return true;
}
public void start()
{
super.start(); // clear out the schedule
environment = new Continuous2D(25.0, (XMAX-XMIN), (YMAX-YMIN) );
// Schedule the agents -- we could instead use a RandomSequence, which would be faster,
// but this is a good test of the scheduler
for(int x=0;x<NUM_HUMANS+NUM_GOODS+NUM_EVILS;x++)
{
Double2D loc = null;
Agent agent = null;
int times = 0;
do
{
loc = new Double2D( random.nextDouble()*(XMAX-XMIN-DIAMETER)+XMIN+DIAMETER/2,
random.nextDouble()*(YMAX-YMIN-DIAMETER)+YMIN+DIAMETER/2 );
if( x < NUM_HUMANS )
agent = new Human( "Human"+x, loc );
else if( x < NUM_HUMANS+NUM_GOODS )
agent = new Good( "Good"+(x-NUM_HUMANS), loc );
else
agent = new Evil( "Evil"+(x-NUM_HUMANS-NUM_GOODS), loc );
times++;
if( times == 1000 )
{
// can't place agents, oh well
break;
}
} while( !acceptablePosition( agent, loc ) );
environment.setObjectLocation(agent,loc);
schedule.scheduleRepeating(agent);
}
}
public static void main(String[] args)
{
doLoop(VirusInfectionDemo.class, args);
System.exit(0);
}
}