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) )
|
||||
{
|
||||
//
|
||||
// Check if worker selected a box and can push it?
|
||||
// Calculate possible moves map.
|
||||
//
|
||||
if ( puzzle.isSelected() )
|
||||
{
|
||||
//
|
||||
// Get directions to push and act accordingly.
|
||||
//
|
||||
int pushes[] = getPushDirections(x, y);
|
||||
if ( pushes != null )
|
||||
{
|
||||
for ( int i = 0; i < pushes.length; i+=2 )
|
||||
animator.queue( new Animator.Push(pushes[i],pushes[i+1]) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
calcMoves();
|
||||
//
|
||||
// Check if worker selected a box and can push it to the location?
|
||||
// If yes then we are done.
|
||||
//
|
||||
if ( puzzle.isSelected()
|
||||
&& tryMoveBox(animator, x, y) )
|
||||
return true;
|
||||
//
|
||||
// Either nothing was selected or the box cannot be moved to
|
||||
// tapped location. Try move worker alone.
|
||||
//
|
||||
calcMoves();
|
||||
if ( isAccessible(x,y) )
|
||||
{
|
||||
//
|
||||
// First unselect box.
|
||||
//
|
||||
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) );
|
||||
}
|
||||
if ( tryMoveWorker( animator, x, y ) )
|
||||
return true;
|
||||
//
|
||||
// Show that action is not allowed.
|
||||
//
|
||||
undoable( animator, 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) )
|
||||
{
|
||||
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.
|
||||
//
|
||||
else if ( Puzzle.hasBox(tile) )
|
||||
{
|
||||
//
|
||||
// Calculate possible moves map.
|
||||
//
|
||||
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
|
||||
// yes then simplly select the box.
|
||||
// If the box is selected then unselect it.
|
||||
//
|
||||
if ( Puzzle.hasWorker( west )
|
||||
|| Puzzle.hasWorker( east )
|
||||
|| Puzzle.hasWorker( north )
|
||||
|| Puzzle.hasWorker( south ) )
|
||||
if ( puzzle.isSelected(x,y) )
|
||||
{
|
||||
if ( !puzzle.isSelected(x,y) )
|
||||
{
|
||||
if ( puzzle.isSelected() )
|
||||
animator.queue( new Animator.Unselect() );
|
||||
animator.queue( new Animator.Select(x,y) );
|
||||
}
|
||||
unselect( animator );
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// Otherwise, check which is of the cells is in closes walking
|
||||
// distance and move worker to that cell, then select.
|
||||
// Try move the worker next to the box and select it if the
|
||||
// box is not selected yet.
|
||||
//
|
||||
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;
|
||||
}
|
||||
//
|
||||
// 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) );
|
||||
}
|
||||
}
|
||||
if ( trySelectBox( animator, x, y ) )
|
||||
return true;
|
||||
//
|
||||
// Show that action is not allowed if reached till here.
|
||||
//
|
||||
undoable( animator, x, y );
|
||||
}
|
||||
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