package rabbitescape.engine;
import static rabbitescape.engine.ChangeDescription.State.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import rabbitescape.engine.ChangeDescription.State;
import rabbitescape.engine.behaviours.*;
public class Rabbit extends Thing implements Comparable<Rabbit>
{
public final static int NOT_INDEXED = 0;
private final List<Behaviour> behaviours;
private final List<Behaviour> behavioursTriggerOrder;
public int index;
private Falling falling;
public Direction dir;
public boolean onSlope;
public Rabbit( int x, int y, Direction dir )
{
super( x, y, RABBIT_WALKING_LEFT );
this.dir = dir;
this.onSlope = false;
behaviours = new ArrayList<>();
behavioursTriggerOrder = new ArrayList<>();
createBehaviours();
index = NOT_INDEXED;
}
private void createBehaviours()
{
Climbing climbing = new Climbing();
Digging digging = new Digging();
Exploding exploding = new Exploding();
Burning burning = new Burning();
OutOfBounds outOfBounds = new OutOfBounds();
Drowning drowning = new Drowning();
Exiting exiting = new Exiting();
Brollychuting brollychuting = new Brollychuting( climbing );
falling = new Falling( climbing, brollychuting );
Bashing bashing = new Bashing();
Bridging bridging = new Bridging();
Blocking blocking = new Blocking();
Walking walking = new Walking();
behavioursTriggerOrder.add( exploding );
behavioursTriggerOrder.add( outOfBounds );
behavioursTriggerOrder.add( burning );
behavioursTriggerOrder.add( drowning );
behavioursTriggerOrder.add( falling );
behavioursTriggerOrder.add( exiting );
behavioursTriggerOrder.add( brollychuting );
behavioursTriggerOrder.add( climbing );
behavioursTriggerOrder.add( bashing );
behavioursTriggerOrder.add( digging );
behavioursTriggerOrder.add( bridging );
behavioursTriggerOrder.add( blocking );
behavioursTriggerOrder.add( walking );
behaviours.add( exploding );
behaviours.add( outOfBounds );
behaviours.add( burning );
behaviours.add( drowning );
behaviours.add( falling );
behaviours.add( exiting );
behaviours.add( brollychuting );
behaviours.add( bashing );
behaviours.add( digging );
behaviours.add( bridging );
behaviours.add( blocking );
behaviours.add( climbing );
behaviours.add( walking );
assert behavioursTriggerOrder.size() == behaviours.size();
}
public boolean isFallingToDeath()
{
return falling.isFallingToDeath();
}
@Override
public void calcNewState( World world )
{
for ( Behaviour behaviour : behavioursTriggerOrder )
{
behaviour.triggered = false;
}
for ( Behaviour behaviour : behavioursTriggerOrder )
{
behaviour.triggered = behaviour.checkTriggered( this, world );
if ( behaviour.triggered )
{
cancelAllBehavioursExcept( behaviour );
}
}
boolean done = false;
for ( Behaviour behaviour : behaviours )
{
State thisState = behaviour.newState(
new BehaviourTools( this, world ), behaviour.triggered );
if ( thisState != null && !done )
{
state = thisState;
done = true;
}
}
}
private void cancelAllBehavioursExcept( Behaviour exception )
{
for ( Behaviour behaviour : behaviours )
{
if ( behaviour != exception )
{
behaviour.cancel();
}
}
}
@Override
public void step( World world )
{
for ( Behaviour behaviour : behaviours )
{
boolean handled = behaviour.behave( world, this, state );
if ( handled )
{
break;
}
}
}
@Override
public Map<String, String> saveState()
{
Map<String, String> ret = new HashMap<String, String>();
BehaviourState.addToStateIfGtZero( ret, "index", index );
BehaviourState.addToStateIfTrue( ret, "onSlope", onSlope );
for ( Behaviour behaviour : behaviours )
{
behaviour.saveState( ret );
}
return ret;
}
@Override
public void restoreFromState( Map<String, String> state )
{
index = BehaviourState.restoreFromState( state, "index", -1 );
onSlope = BehaviourState.restoreFromState(
state, "onSlope", false
);
for ( Behaviour behaviour : behaviours )
{
behaviour.restoreFromState( state );
}
}
@Override
public String overlayText()
{
String fmt;
switch ( dir )
{
case LEFT:
fmt = "<[%d] ";
break;
case RIGHT:
fmt = " [%d]>";
break;
default:
throw new RuntimeException( "Rabbit should only be left or right");
}
return String.format( fmt, index ) ;
}
@Override
public int compareTo( Rabbit r )
{
return this.index - r.index;
}
@Override
public boolean equals( Object o )
{
if ( null == o || !( o instanceof Rabbit ) )
{
return false;
}
return ( (Rabbit)o ).index == this.index;
}
@Override
public int hashCode()
{
return index;
}
}