package rabbitescape.engine;
import static rabbitescape.engine.ChangeDescription.State.*;
import java.util.HashMap;
import java.util.Map;
import rabbitescape.engine.ChangeDescription.State;
import rabbitescape.engine.err.RabbitEscapeException;
public class Token extends Thing
{
public static class UnknownType extends RabbitEscapeException
{
public final Type type;
public UnknownType( Type type )
{
this.type = type;
}
private static final long serialVersionUID = 1L;
}
public static enum Type
{
bash,
dig,
bridge,
block,
climb,
explode,
brolly
}
public final Type type;
public Token( int x, int y, Type type )
{
super( x, y, switchType( type, false, false, true ) );
this.type = type;
}
public Token( int x, int y, Type type, World world )
{
this( x, y, type );
boolean onSlope = BehaviourTools.isSlope( world.getBlockAt( x, y ) );
// Can't use calcNewState here since we have just been created, so
// can't be moving (until a time step passes).
state = switchType( type, false, false, onSlope );
}
private static State switchType( Type type, boolean moving, boolean slopeBelow, boolean onSlope )
{
switch( type )
{
case bash: return chooseState( moving, slopeBelow, onSlope,
TOKEN_BASH_FALLING, TOKEN_BASH_STILL,
TOKEN_BASH_FALL_TO_SLOPE, TOKEN_BASH_ON_SLOPE);
case dig: return chooseState( moving, slopeBelow, onSlope,
TOKEN_DIG_FALLING, TOKEN_DIG_STILL,
TOKEN_DIG_FALL_TO_SLOPE, TOKEN_DIG_ON_SLOPE);
case bridge: return chooseState( moving, slopeBelow, onSlope,
TOKEN_BRIDGE_FALLING, TOKEN_BRIDGE_STILL,
TOKEN_BRIDGE_FALL_TO_SLOPE, TOKEN_BRIDGE_ON_SLOPE);
case block: return chooseState( moving, slopeBelow, onSlope,
TOKEN_BLOCK_FALLING, TOKEN_BLOCK_STILL,
TOKEN_BLOCK_FALL_TO_SLOPE, TOKEN_BLOCK_ON_SLOPE);
case climb: return chooseState( moving, slopeBelow, onSlope,
TOKEN_CLIMB_FALLING, TOKEN_CLIMB_STILL,
TOKEN_CLIMB_FALL_TO_SLOPE, TOKEN_CLIMB_ON_SLOPE);
case explode: return chooseState( moving, slopeBelow, onSlope,
TOKEN_EXPLODE_FALLING, TOKEN_EXPLODE_STILL,
TOKEN_EXPLODE_FALL_TO_SLOPE, TOKEN_EXPLODE_ON_SLOPE);
case brolly: return chooseState( moving, slopeBelow, onSlope,
TOKEN_BROLLY_FALLING, TOKEN_BROLLY_STILL,
TOKEN_BROLLY_FALL_TO_SLOPE, TOKEN_BROLLY_ON_SLOPE);
default: throw new UnknownType( type );
}
}
private static State chooseState( boolean moving, boolean slopeBelow, boolean onSlope,
State falling, State onFlat, State fallingToSlope, State onSlopeState)
{
if ( onSlope )
{
return onSlopeState;
}
if ( !moving )
{
return onFlat;
}
if ( slopeBelow )
{
return fallingToSlope;
}
return falling;
}
@Override
public void calcNewState( World world )
{
Block onBlock = world.getBlockAt( x, y );
Block belowBlock = world.getBlockAt( x, y + 1 );
boolean still = (
BehaviourTools.s_isFlat( belowBlock )
|| ( onBlock != null )
|| BridgeTools.someoneIsBridgingAt( world, x, y )
);
state = switchType( type, !still,
BehaviourTools.isSlope( belowBlock ), BehaviourTools.isSlope( onBlock ) );
}
@Override
public void step( World world )
{
switch ( state )
{
case TOKEN_BASH_FALLING:
case TOKEN_BASH_FALL_TO_SLOPE:
case TOKEN_DIG_FALLING:
case TOKEN_DIG_FALL_TO_SLOPE:
case TOKEN_BRIDGE_FALLING:
case TOKEN_BRIDGE_FALL_TO_SLOPE:
case TOKEN_BLOCK_FALLING:
case TOKEN_BLOCK_FALL_TO_SLOPE:
case TOKEN_CLIMB_FALLING:
case TOKEN_CLIMB_FALL_TO_SLOPE:
case TOKEN_EXPLODE_FALL_TO_SLOPE:
case TOKEN_EXPLODE_FALLING:
case TOKEN_BROLLY_FALLING:
case TOKEN_BROLLY_FALL_TO_SLOPE:
{
++y;
if ( y >= world.size.height )
{
world.changes.removeToken( this );
}
return;
}
default:
// Nothing to do
}
}
@Override
public Map<String, String> saveState()
{
return new HashMap<String, String>();
}
@Override
public void restoreFromState( Map<String, String> state )
{
}
public static String name( Type ability )
{
String n = ability.name();
return n.substring( 0, 1 ).toUpperCase() + n.substring( 1 );
}
@Override
public String overlayText()
{
return type.toString();
}
}