package rabbitescape.engine; import static rabbitescape.engine.Block.Shape.*; import static rabbitescape.engine.Direction.RIGHT; import static rabbitescape.engine.Direction.opposite; import rabbitescape.engine.util.Position; public class BehaviourTools { public final Rabbit rabbit; public final World world; public BehaviourTools( Rabbit rabbit, World world ) { this.rabbit = rabbit; this.world = world; } public ChangeDescription.State rl( ChangeDescription.State rightState, ChangeDescription.State leftState ) { return rabbit.dir == RIGHT ? rightState : leftState; } public boolean pickUpToken( Token.Type type ) { return pickUpToken( type, false ); } public boolean rabbitIsFalling() { switch (rabbit.state) { case RABBIT_FALLING: case RABBIT_FALLING_1: case RABBIT_FALLING_1_TO_DEATH: case RABBIT_DYING_OF_FALLING_2: case RABBIT_DYING_OF_FALLING: case RABBIT_FALLING_ONTO_LOWER_RIGHT: case RABBIT_FALLING_ONTO_RISE_RIGHT: case RABBIT_FALLING_ONTO_LOWER_LEFT: case RABBIT_FALLING_ONTO_RISE_LEFT: case RABBIT_FALLING_1_ONTO_LOWER_RIGHT: case RABBIT_FALLING_1_ONTO_RISE_RIGHT: case RABBIT_FALLING_1_ONTO_LOWER_LEFT: case RABBIT_FALLING_1_ONTO_RISE_LEFT: case RABBIT_DYING_OF_FALLING_SLOPE_RISE_RIGHT: case RABBIT_DYING_OF_FALLING_SLOPE_RISE_RIGHT_2: case RABBIT_DYING_OF_FALLING_2_SLOPE_RISE_RIGHT: case RABBIT_DYING_OF_FALLING_2_SLOPE_RISE_RIGHT_2: case RABBIT_DYING_OF_FALLING_SLOPE_RISE_LEFT: case RABBIT_DYING_OF_FALLING_SLOPE_RISE_LEFT_2: case RABBIT_DYING_OF_FALLING_2_SLOPE_RISE_LEFT: case RABBIT_DYING_OF_FALLING_2_SLOPE_RISE_LEFT_2: return true; default: return false; } } public boolean rabbitIsClimbing() { switch( rabbit.state) { case RABBIT_ENTERING_EXIT_CLIMBING_RIGHT: case RABBIT_ENTERING_EXIT_CLIMBING_LEFT: case RABBIT_CLIMBING_LEFT_START: case RABBIT_CLIMBING_LEFT_CONTINUE_1: case RABBIT_CLIMBING_LEFT_CONTINUE_2: case RABBIT_CLIMBING_LEFT_END: case RABBIT_CLIMBING_LEFT_BANG_HEAD: case RABBIT_CLIMBING_RIGHT_START: case RABBIT_CLIMBING_RIGHT_CONTINUE_1: case RABBIT_CLIMBING_RIGHT_CONTINUE_2: case RABBIT_CLIMBING_RIGHT_END: case RABBIT_CLIMBING_RIGHT_BANG_HEAD: return true; default: return false; } } /** * Checks for the presence of a token. Removes token from the the world and returns * true if a token is being picked up. */ public boolean pickUpToken( Token.Type type, boolean evenIfNotOnGround ) { if ( rabbitIsFalling() && rabbit.isFallingToDeath() ) { return false; // Dying rabbits not allowed to consume tokens } if ( evenIfNotOnGround || onGround() ) { Token token = world.getTokenAt( rabbit.x, rabbit.y ); if ( token != null && token.type == type ) { world.changes.removeToken( token ); return true; } } return false; } public Block blockHere() { return world.getBlockAt( rabbit.x, rabbit.y ); } public Block blockNext() { return world.getBlockAt( nextX(), rabbit.y ); } public Block blockBelow() { return world.getBlockAt( rabbit.x, rabbit.y + 1 ); } public Block block2Below() { return world.getBlockAt( rabbit.x, rabbit.y + 2 ); } public Block blockBelowNext() { return world.getBlockAt( nextX(), rabbit.y + 1 ); } public Block blockAbove() { return world.getBlockAt( rabbit.x, rabbit.y - 1 ); } public Block blockAboveNext() { return world.getBlockAt( nextX(), rabbit.y - 1 ); } private boolean onGround() { return ( rabbit.onSlope || blockBelow() != null ); } public boolean isWall( Block block ) { return ( block != null && ( block.shape == FLAT || ( block.riseDir() == opposite( rabbit.dir ) && isSolid( block ) ) ) ); } public static boolean shapeEquals( Block b, Block.Shape s ) { if ( null == b ) { return false; } return s == b.shape; } public static boolean isRightRiseSlope( Block b ) { if( b == null ) { return false; } return b.shape == UP_RIGHT || b.shape == BRIDGE_UP_RIGHT; } public static boolean isLeftRiseSlope( Block b ) { if( b == null ) { return false; } return b.shape == UP_LEFT || b.shape == BRIDGE_UP_LEFT; } public static boolean isSlope( Block b ) { return isRightRiseSlope( b ) || isLeftRiseSlope( b ); } public static boolean isBridge( Block b ) { if( b == null ) { return false; } switch ( b.shape ) { case BRIDGE_UP_LEFT: case BRIDGE_UP_RIGHT: return true; default: return false; } } public static boolean isSolid( Block block ) { return ( block.shape == FLAT || block.shape == UP_LEFT || block.shape == UP_RIGHT ); } public boolean isRoof( Block block ) { return ( block != null && ( block.shape == FLAT || block.shape == UP_LEFT || block.shape == UP_RIGHT ) ); } public boolean isOnSlopeStateUnreliable() { Block block = blockHere(); return null != block && ( block.shape == UP_LEFT || block.shape == UP_RIGHT || block.shape == BRIDGE_UP_LEFT || block.shape == BRIDGE_UP_RIGHT ); } public boolean isFlat( Block block ) { return s_isFlat( block ); } public static boolean s_isFlat( Block block ) { return ( block != null && block.shape == FLAT ); } private boolean goingUpSlope() { if ( rabbit.onSlope ) { if( isOnUpSlope() ) { return true; } } return false; } public boolean isOnUpSlope() { return rabbit.onSlope && hereIsUpSlope(); } /** * Check if rabbit is changing from an up slope directly to a down slope. */ public boolean isCresting() { // block where slope would be if it continues Block contBlock = world.getBlockAt( nextX(), nextY() ); Block belowContBlock = world.getBlockAt( nextX(), nextY() + 1 ); return isOnUpSlope() && null == contBlock && isDownSlope( belowContBlock ); } /** * Check if rabbit is changing from a down slope directly to an up slope. */ public boolean isValleying() { // block where slope would be if it continues Block alongBlock = world.getBlockAt( nextX(), rabbit.y ); return isOnDownSlope() && isUpSlope( alongBlock ); } public boolean hereIsUpSlope() { return isUpSlope( blockHere() ); } public boolean isUpSlope( Block block ) { return ( block != null && block.riseDir() == rabbit.dir ); } public boolean isOnDownSlope() { return rabbit.onSlope && hereIsDownSlope(); } private boolean hereIsDownSlope() { return isDownSlope( blockHere() ); } public boolean isDownSlope( Block block ) { return ( block != null && block.riseDir() == opposite( rabbit.dir ) ); } public static boolean isSlopeNotBridge( Block b ) { if ( null == b ) { return false; } switch( b.shape ) { case UP_LEFT: case UP_RIGHT: return true; default: return false; } } public int nextX() { return rabbit.x + ( rabbit.dir == RIGHT ? 1 : -1 ); } public int nextY() { if ( goingUpSlope() ) { return rabbit.y - 1; } else { return rabbit.y; } } /** * @brief A rabbit may be on a slope block as a digger * or basher removes it. This is here to make sure * they fall. */ public boolean blockHereJustRemoved() { for ( Position p : world.changes.blocksJustRemoved ) { if ( rabbit.x == p.x && rabbit.y == p.y ) { return true; } } return false; } }