A new short-cut is added for the box continuing pushing with the worker adjusting its position.
This commit is contained in:
@@ -44,145 +44,304 @@ public class PuzzleLogic
|
|||||||
if ( Puzzle.isEmpty(tile) )
|
if ( Puzzle.isEmpty(tile) )
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Check if worker selected a box and can push it?
|
// Calculate possible moves map.
|
||||||
//
|
//
|
||||||
if ( puzzle.isSelected() )
|
calcMoves();
|
||||||
{
|
//
|
||||||
//
|
// Check if worker selected a box and can push it to the location?
|
||||||
// Get directions to push and act accordingly.
|
// If yes then we are done.
|
||||||
//
|
//
|
||||||
int pushes[] = getPushDirections(x, y);
|
if ( puzzle.isSelected()
|
||||||
if ( pushes != null )
|
&& tryMoveBox(animator, x, y) )
|
||||||
{
|
return true;
|
||||||
for ( int i = 0; i < pushes.length; i+=2 )
|
|
||||||
animator.queue( new Animator.Push(pushes[i],pushes[i+1]) );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// Either nothing was selected or the box cannot be moved to
|
// Either nothing was selected or the box cannot be moved to
|
||||||
// tapped location. Try move worker alone.
|
// tapped location. Try move worker alone.
|
||||||
//
|
//
|
||||||
calcMoves();
|
if ( tryMoveWorker( animator, x, y ) )
|
||||||
if ( isAccessible(x,y) )
|
return true;
|
||||||
{
|
//
|
||||||
//
|
// Show that action is not allowed.
|
||||||
// First unselect box.
|
//
|
||||||
//
|
undoable( animator, x, y );
|
||||||
if ( puzzle.isSelected() )
|
|
||||||
animator.queue( new Animator.Unselect() );
|
|
||||||
//
|
|
||||||
// Get directions and queue moves accordingly.
|
|
||||||
//
|
|
||||||
int dirs[] = getDirections(x, y);
|
|
||||||
for ( int i = 0; i < dirs.length; i+=2 )
|
|
||||||
animator.queue( new Animator.Move(dirs[i],dirs[i+1]) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Show that action is not allowed.
|
|
||||||
//
|
|
||||||
animator.queue( new Animator.NoMove(x,y) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// The tapped is the worker. Unselect if selected.
|
// The tapped is the worker. Try move the box. If not possible
|
||||||
|
// then unselect if selected.
|
||||||
//
|
//
|
||||||
else if ( Puzzle.hasWorker(tile) )
|
else if ( Puzzle.hasWorker(tile) )
|
||||||
{
|
{
|
||||||
if ( puzzle.isSelected() )
|
if ( !puzzle.isSelected() )
|
||||||
{
|
{
|
||||||
animator.queue( new Animator.Unselect() );
|
buzz( animator );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Calculate possible moves map.
|
||||||
|
//
|
||||||
|
calcMoves();
|
||||||
|
//
|
||||||
|
// Check if worker selected a box and can push it to the location?
|
||||||
|
// If yes then we are done.
|
||||||
|
//
|
||||||
|
if ( tryMoveBox(animator, x, y) )
|
||||||
|
return true;
|
||||||
|
//
|
||||||
|
// If the box is not movable then unselect it.
|
||||||
|
//
|
||||||
|
unselect( animator );
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// The tapped is a box.
|
// The tapped is a box.
|
||||||
//
|
//
|
||||||
else if ( Puzzle.hasBox(tile) )
|
else if ( Puzzle.hasBox(tile) )
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Calculate possible moves map.
|
||||||
|
//
|
||||||
calcMoves();
|
calcMoves();
|
||||||
int north = puzzle.getSym(x,y-1);
|
|
||||||
int south = puzzle.getSym(x,y+1);
|
|
||||||
int west = puzzle.getSym(x-1,y);
|
|
||||||
int east = puzzle.getSym(x+1,y);
|
|
||||||
//
|
//
|
||||||
// First check if there is a worker in a nighbour cell. If
|
// If the box is selected then unselect it.
|
||||||
// yes then simplly select the box.
|
|
||||||
//
|
//
|
||||||
if ( Puzzle.hasWorker( west )
|
if ( puzzle.isSelected(x,y) )
|
||||||
|| Puzzle.hasWorker( east )
|
|
||||||
|| Puzzle.hasWorker( north )
|
|
||||||
|| Puzzle.hasWorker( south ) )
|
|
||||||
{
|
{
|
||||||
if ( !puzzle.isSelected(x,y) )
|
unselect( animator );
|
||||||
{
|
return true;
|
||||||
if ( puzzle.isSelected() )
|
|
||||||
animator.queue( new Animator.Unselect() );
|
|
||||||
animator.queue( new Animator.Select(x,y) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Otherwise, check which is of the cells is in closes walking
|
// Try move the worker next to the box and select it if the
|
||||||
// distance and move worker to that cell, then select.
|
// box is not selected yet.
|
||||||
//
|
//
|
||||||
else
|
if ( trySelectBox( animator, x, y ) )
|
||||||
{
|
return true;
|
||||||
int pref_x = -1;
|
//
|
||||||
int pref_y = -1;
|
// Show that action is not allowed if reached till here.
|
||||||
int shortest = Integer.MAX_VALUE;
|
//
|
||||||
if ( Puzzle.isEmpty( north )
|
undoable( animator, x, y );
|
||||||
&& shortest > stepsAway( x, y-1) )
|
|
||||||
{
|
|
||||||
shortest = stepsAway( x, y-1);
|
|
||||||
pref_x = x;
|
|
||||||
pref_y = y-1;
|
|
||||||
}
|
|
||||||
if ( Puzzle.isEmpty( south )
|
|
||||||
&& shortest > stepsAway( x, y+1) )
|
|
||||||
{
|
|
||||||
shortest = stepsAway( x, y+1);
|
|
||||||
pref_x = x;
|
|
||||||
pref_y = y+1;
|
|
||||||
}
|
|
||||||
if ( Puzzle.isEmpty( west )
|
|
||||||
&& shortest > stepsAway( x-1, y) )
|
|
||||||
{
|
|
||||||
shortest = stepsAway( x-1, y);
|
|
||||||
pref_x = x-1;
|
|
||||||
pref_y = y;
|
|
||||||
}
|
|
||||||
if ( Puzzle.isEmpty( east )
|
|
||||||
&& shortest > stepsAway( x+1, y) )
|
|
||||||
{
|
|
||||||
shortest = stepsAway( x+1, y);
|
|
||||||
pref_x = x+1;
|
|
||||||
pref_y = y;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Looks there is place to approach to box.
|
|
||||||
//
|
|
||||||
if ( shortest < Integer.MAX_VALUE )
|
|
||||||
{
|
|
||||||
if ( puzzle.isSelected() )
|
|
||||||
animator.queue( new Animator.Unselect() );
|
|
||||||
int dirs[] = getDirections(pref_x, pref_y);
|
|
||||||
for ( int i = 0; i < dirs.length; i+=2 )
|
|
||||||
animator.queue( new Animator.Move(dirs[i],dirs[i+1]) );
|
|
||||||
//animator.queue( new Animator.Select(x,y) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Show that action is not allowed.
|
|
||||||
//
|
|
||||||
animator.queue( new Animator.NoMove(x,y) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Routes to accessible cells from where worker stands.
|
||||||
|
//
|
||||||
|
protected boolean tryMoveWorker( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// If the filed is not accessable then move failed.
|
||||||
|
//
|
||||||
|
if ( !isAccessible(x,y) )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// First unselect box.
|
||||||
|
//
|
||||||
|
if ( puzzle.isSelected() )
|
||||||
|
unselect( animator );
|
||||||
|
//
|
||||||
|
// Get directions and queue moves accordingly.
|
||||||
|
//
|
||||||
|
int dirs[] = getDirections(x, y);
|
||||||
|
for ( int i = 0; i < dirs.length; i+=2 )
|
||||||
|
move( animator, dirs[i],dirs[i+1] );
|
||||||
|
//
|
||||||
|
// Done.
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean tryMoveBox( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// If no box is selected then we cannot move no box.
|
||||||
|
//
|
||||||
|
if ( !puzzle.isSelected() )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// Check that asked move is orthogonal to the slected box.
|
||||||
|
//
|
||||||
|
int bx = puzzle.getSelectedX();
|
||||||
|
int by = puzzle.getSelectedY();
|
||||||
|
int dx = x-bx;
|
||||||
|
int dy = y-by;
|
||||||
|
if ( dx != 0 && dy != 0 )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// There is no point to continue also in case if the asked cell
|
||||||
|
// is the box.
|
||||||
|
//
|
||||||
|
if ( dx == 0 && dy == 0 )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// Now find the desired place for the worker to start push this
|
||||||
|
// box.
|
||||||
|
//
|
||||||
|
int wx = bx;
|
||||||
|
int wy = by;
|
||||||
|
if ( x < bx )
|
||||||
|
++wx;
|
||||||
|
else if ( x > bx )
|
||||||
|
--wx;
|
||||||
|
else if ( y < by )
|
||||||
|
++wy;
|
||||||
|
else
|
||||||
|
--wy;
|
||||||
|
//
|
||||||
|
// Check if the desired place for the worker is accessable? If not
|
||||||
|
// then there is no point to continue.
|
||||||
|
//
|
||||||
|
if ( !isAccessible(wx, wy) )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// Now check that all cell till x,y are empty and that we can
|
||||||
|
// push box till there.
|
||||||
|
//
|
||||||
|
int sx = bx-wx;
|
||||||
|
int sy = by-wy;
|
||||||
|
int ix = bx;
|
||||||
|
int iy = by;
|
||||||
|
while ( x != ix || y != iy )
|
||||||
|
{
|
||||||
|
ix+=sx;
|
||||||
|
iy+=sy;
|
||||||
|
int v = puzzle.getSym(ix,iy);
|
||||||
|
if ( !puzzle.isEmpty(v) && !puzzle.hasWorker(v) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Ok, looks we can do the desired action. Now put instructions on
|
||||||
|
// what to do. First move worker to desired position if he is not
|
||||||
|
// there already.
|
||||||
|
//
|
||||||
|
if ( wx != puzzle.getWorkerX() || wy != puzzle.getWorkerY() )
|
||||||
|
{
|
||||||
|
tryMoveWorker( animator, wx, wy );
|
||||||
|
select( animator, bx, by );
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Now create the steps to push the box.
|
||||||
|
//
|
||||||
|
ix = bx;
|
||||||
|
iy = by;
|
||||||
|
while ( x != ix || y != iy )
|
||||||
|
{
|
||||||
|
push( animator, ix, iy );
|
||||||
|
ix+=sx;
|
||||||
|
iy+=sy;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Done
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean trySelectBox( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
int north = puzzle.getSym(x,y-1);
|
||||||
|
int south = puzzle.getSym(x,y+1);
|
||||||
|
int west = puzzle.getSym(x-1,y);
|
||||||
|
int east = puzzle.getSym(x+1,y);
|
||||||
|
//
|
||||||
|
// First check if there is a worker in a nighbour cell. If
|
||||||
|
// yes then simplly select the box. If the box is already selected
|
||||||
|
// then do nothing and if othe box is selected then unselect it first
|
||||||
|
// and then select the box.
|
||||||
|
//
|
||||||
|
if ( Puzzle.hasWorker( west )
|
||||||
|
|| Puzzle.hasWorker( east )
|
||||||
|
|| Puzzle.hasWorker( north )
|
||||||
|
|| Puzzle.hasWorker( south ) )
|
||||||
|
{
|
||||||
|
if ( !puzzle.isSelected(x,y) )
|
||||||
|
{
|
||||||
|
if ( puzzle.isSelected() )
|
||||||
|
unselect( animator );
|
||||||
|
select( animator, x, y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Otherwise, check which is of the cells is in closes walking
|
||||||
|
// distance and move worker to that cell, then select.
|
||||||
|
//
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pref_x = -1;
|
||||||
|
int pref_y = -1;
|
||||||
|
int shortest = Integer.MAX_VALUE;
|
||||||
|
if ( Puzzle.isEmpty( north )
|
||||||
|
&& shortest > stepsAway( x, y-1) )
|
||||||
|
{
|
||||||
|
shortest = stepsAway( x, y-1);
|
||||||
|
pref_x = x;
|
||||||
|
pref_y = y-1;
|
||||||
|
}
|
||||||
|
if ( Puzzle.isEmpty( south )
|
||||||
|
&& shortest > stepsAway( x, y+1) )
|
||||||
|
{
|
||||||
|
shortest = stepsAway( x, y+1);
|
||||||
|
pref_x = x;
|
||||||
|
pref_y = y+1;
|
||||||
|
}
|
||||||
|
if ( Puzzle.isEmpty( west )
|
||||||
|
&& shortest > stepsAway( x-1, y) )
|
||||||
|
{
|
||||||
|
shortest = stepsAway( x-1, y);
|
||||||
|
pref_x = x-1;
|
||||||
|
pref_y = y;
|
||||||
|
}
|
||||||
|
if ( Puzzle.isEmpty( east )
|
||||||
|
&& shortest > stepsAway( x+1, y) )
|
||||||
|
{
|
||||||
|
shortest = stepsAway( x+1, y);
|
||||||
|
pref_x = x+1;
|
||||||
|
pref_y = y;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Move the worker to the direction. If we cannot move worker
|
||||||
|
// next to the box then we cannot select it.
|
||||||
|
//
|
||||||
|
if ( !tryMoveWorker(animator, pref_x, pref_y) )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// Select the box.
|
||||||
|
//
|
||||||
|
select(animator,x,y);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Done
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void move( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
animator.queue( new Animator.Move(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void push( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
animator.queue( new Animator.Push(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void select( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
animator.queue( new Animator.Select(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unselect( Animator animator )
|
||||||
|
{
|
||||||
|
animator.queue( new Animator.Unselect() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buzz( Animator animator )
|
||||||
|
{
|
||||||
|
//animator.queue( new Animator.NoMove(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void undoable( Animator animator, int x, int y )
|
||||||
|
{
|
||||||
|
animator.queue( new Animator.NoMove(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user