package rabbitescape.engine.behaviours; import static rabbitescape.engine.ChangeDescription.State.*; import static rabbitescape.engine.Direction.*; import static rabbitescape.engine.Token.Type.*; import java.util.Map; import rabbitescape.engine.*; import rabbitescape.engine.ChangeDescription.State; public class Climbing extends Behaviour { boolean hasAbility = false; public boolean abilityActive = false; @Override public void cancel() { abilityActive = false; } @Override public boolean checkTriggered( Rabbit rabbit, World world ) { BehaviourTools t = new BehaviourTools( rabbit, world ); return !hasAbility && t.pickUpToken( climb, true ); } @Override public State newState( BehaviourTools t, boolean triggered ) { if ( triggered ) { hasAbility = true; } if ( !hasAbility ) { return null; } switch ( t.rabbit.state ) { case RABBIT_CLIMBING_RIGHT_START: case RABBIT_CLIMBING_LEFT_START: return newStateStart( t ); case RABBIT_CLIMBING_RIGHT_CONTINUE_1: case RABBIT_CLIMBING_LEFT_CONTINUE_1: return newStateCont1( t ); case RABBIT_CLIMBING_RIGHT_CONTINUE_2: case RABBIT_CLIMBING_LEFT_CONTINUE_2: return newStateCont2( t ); default: return newStateNotClimbing( t ); } } private State newStateStart( BehaviourTools t ) { Block endBlock = t.blockAboveNext(); if ( t.isWall( endBlock ) ) { return t.rl( RABBIT_CLIMBING_RIGHT_CONTINUE_2, RABBIT_CLIMBING_LEFT_CONTINUE_2 ); } else { return t.rl( RABBIT_CLIMBING_RIGHT_END, RABBIT_CLIMBING_LEFT_END ); } } private State newStateCont1( BehaviourTools t ) { return t.rl( RABBIT_CLIMBING_RIGHT_CONTINUE_2, RABBIT_CLIMBING_LEFT_CONTINUE_2 ); } private State newStateCont2( BehaviourTools t ) { Block aboveBlock = t.blockAbove(); if ( t.isRoof( aboveBlock ) ) { abilityActive = false; return t.rl( RABBIT_CLIMBING_RIGHT_BANG_HEAD, RABBIT_CLIMBING_LEFT_BANG_HEAD ); } Block endBlock = t.blockAboveNext(); if ( t.isWall( endBlock ) ) { return t.rl( RABBIT_CLIMBING_RIGHT_CONTINUE_1, RABBIT_CLIMBING_LEFT_CONTINUE_1 ); } else { return t.rl( RABBIT_CLIMBING_RIGHT_END, RABBIT_CLIMBING_LEFT_END ); } } private State newStateNotClimbing( BehaviourTools t ) { int nextX = t.nextX(); int nextY = t.nextY(); Block nextBlock = t.world.getBlockAt( nextX, nextY ); Block aboveBlock = t.world.getBlockAt( t.rabbit.x, t.rabbit.y - 1 ); if ( !t.isRoof( aboveBlock ) && t.isWall( nextBlock ) ) { return t.rl( RABBIT_CLIMBING_RIGHT_START, RABBIT_CLIMBING_LEFT_START ); } return null; } @Override public boolean behave( World world, Rabbit rabbit, State state ) { BehaviourTools t = new BehaviourTools( rabbit, world ); if( t.rabbitIsClimbing() ) { // Can't be both on a wall and on a slope. rabbit.onSlope = false; } switch ( state ) { case RABBIT_CLIMBING_RIGHT_START: case RABBIT_CLIMBING_LEFT_START: { abilityActive = true; return true; } case RABBIT_CLIMBING_RIGHT_END: case RABBIT_CLIMBING_LEFT_END: { rabbit.x = t.nextX(); --rabbit.y; if ( t.hereIsUpSlope() ) { rabbit.onSlope = true; } abilityActive = false; return true; } case RABBIT_CLIMBING_RIGHT_CONTINUE_1: case RABBIT_CLIMBING_LEFT_CONTINUE_1: { abilityActive = true; return true; } case RABBIT_CLIMBING_RIGHT_CONTINUE_2: case RABBIT_CLIMBING_LEFT_CONTINUE_2: { abilityActive = true; --rabbit.y; return true; } case RABBIT_CLIMBING_RIGHT_BANG_HEAD: case RABBIT_CLIMBING_LEFT_BANG_HEAD: { rabbit.dir = opposite( rabbit.dir ); return true; } default: { return false; } } } @Override public void saveState( Map<String, String> saveState ) { BehaviourState.addToStateIfTrue( saveState, "Climbing.hasAbility", hasAbility ); BehaviourState.addToStateIfTrue( saveState, "Climbing.abilityActive", abilityActive ); } @Override public void restoreFromState( Map<String, String> saveState ) { hasAbility = BehaviourState.restoreFromState( saveState, "Climbing.hasAbility", hasAbility ); abilityActive = BehaviourState.restoreFromState( saveState, "Climbing.abilityActive", abilityActive ); } }