A new short-cut is added for the box continuing pushing with the worker adjusting its position.

This commit is contained in:
2013-06-05 13:39:52 +04:00
parent 70e287006f
commit 78c58c8ef6

View File

@@ -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) );
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //