/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OSPATHS2.CPP
//Description : Object SeekPathS2
//Owner : Alex
#include
#include
#include
#include
#include
#include
#include
#include
#include
//----------- Define static variables -----------//
static Location* world_loc_matrix;
static int cur_stack_pos_s2 = 0;
static NodeS2* stack_array[MAX_STACK_NUM];
static DWORD group_id_s2;
static short search_mode_s2;
static char mobile_type_s2;
static short target_recno_s2;
static short building_id_s2; // used in search_mode = SEARCH_MODE_TO_FIRM or SEARCH_MODE_TO_TOWN, get from miscNo
static int building_x1_s2, building_y1_s2, building_x2_s2, building_y2_s2;
// the building upper-left to lower-right positions
// if search_mode = SEARCH_MODE_TO_FIRM or SEARCH_MODE_TO_TOWN
static FirmInfo *searchFirmInfo_s2;
static short x_shift_array[8] = { 1, 1, 0, -1, -1, -1, 0, 1};
static short y_shift_array[8] = { 0, -1, -1, -1, 0, 1, 1, 1};
//---- used in determining the return nodes in the starting node -----//
static char source_blocked_exit_direction[8]; // indicate which exit direction of starting node is impossible
static char source_locate_type; // indicate the upper left position of the unit located in the 2x2 node
//---- used to decide which path is return in a node -------//
static short prefer_upper_s2; // if upper and lower paths are available, true if the upper path is preferred
static short prefer_lower_s2; // if upper and lower paths are available, true if the lower path is preferred
static short prefer_left_s2; // if left and right paths are available, true if the left path is preferred
static short prefer_right_s2; // if left and right paths are available, true if the right path is preferred
//--- show whether shift-map method is used the direction shifted ---//
static short use_shift_map_method_s2;// is 0 or 1, 1 for using this method
static short shift_map_x_offset_s2; // useful only as shift-map-method is applied
static short shift_map_y_offset_s2; // useful only as shift-map-method is applied
//static short reverse_direction_result_node;
//-- store the orginal and the finalized starting and destination location --//
static short source_x_s2; // starting x location in 2x2 node format
static short source_y_s2; // starting y location in 2x2 node format
static int vir_start_x_s2; // store the start x loc after applying shift-map-method
static int vir_start_y_s2; // store the start y loc after applying shift-map-method
static int final_dest_x_s2; // store the finalize x loc after applying shift-map-method, path-reuse, and etc
static int final_dest_y_s2; // store the finalize y loc after applying shift-map-method, path-reuse, and etc
//------------------- used in path-reuse -----------------------//
static int max_node_num_s2;
static short *reuse_node_matrix_ptr_s2;
static NodeS2 *reuse_result_node_ptr_s2;
static int final_dx;
static int final_dy;
//------- aliasing class member vars for fast access ------//
static SeekPathS2* cur_seek_path_s2;
static short cur_dest_x_s2, cur_dest_y_s2;
static short* cur_node_matrix_s2;
static NodeS2* cur_node_array_s2;
static short cur_border_x1_s2, cur_border_y1_s2, cur_border_x2_s2, cur_border_y2_s2;
#ifdef DEBUG
static ResultNode *debugPtr1, *debugPtr2;
static short debugVX, debugVY;
static int debugCount;
void debug_checks2(ResultNode *nodeArray, int count)
{
debugPtr1 = nodeArray;
debugPtr2 = nodeArray+1;
for(debugCount=1; debugCountnode_x<0 || debugPtr1->node_x>=MAX_WORLD_X_LOC-1 ||
debugPtr1->node_y<0 || debugPtr1->node_y>=MAX_WORLD_Y_LOC-1);
debugVX = debugPtr1->node_x - debugPtr2->node_x;
debugVY = debugPtr1->node_y - debugPtr2->node_y;
err_when(debugVX!=0 && debugVY!=0 && (abs(debugVX)!=abs(debugVY)));
}
err_when(debugPtr1->node_x<0 || debugPtr1->node_x>=MAX_WORLD_X_LOC-1 ||
debugPtr1->node_y<0 || debugPtr1->node_y>=MAX_WORLD_Y_LOC-1);
}
#endif
#ifdef DEBUG
#define debug_check_paths2(nodeArray, count) debug_checks2((nodeArray), (count))
#else
#define debug_check_paths2(nodeArray, count)
#endif
//----------- Define static functions -----------//
static void stack_push(NodeS2 *nodePtr);
static NodeS2* stack_pop();
//------- Begin of static function sys_yield ----------//
static void sys_yield()
{
//sys.yield();
}
//------- End of static function sys_yield ----------//
//------- Begin of static function can_move_to ----------//
static int can_move_to(int xLoc, int yLoc) // xLoc, yLoc is location after applying shift-map-method
{
//-------------------------------------------------------//
// note : return value should be 0 (false) or 1 (true)
//-------------------------------------------------------//
int x, y;
//-------------------- boundary checking -----------------//
if(shift_map_x_offset_s2==0)
{
if(xLoc<0 || xLoc>=MAX_WORLD_X_LOC)
return 0;
else
x = xLoc;
}
else // shifted
{
if(xLoc<1 || xLoc>MAX_WORLD_X_LOC)
return 0;
else
x = xLoc+shift_map_x_offset_s2;
}
if(shift_map_y_offset_s2==0)
{
if(yLoc<0 || yLoc>=MAX_WORLD_Y_LOC)
return 0;
else
y = yLoc;
}
else // shifted
{
if(yLoc<1 || yLoc>MAX_WORLD_Y_LOC)
return 0;
else
y = yLoc+shift_map_y_offset_s2;
}
Location* locPtr = world_loc_matrix+y*MAX_WORLD_X_LOC+x;
Unit* unitPtr;
//---------- checking whether the location is walkable ----------//
switch(mobile_type_s2)
{
case UNIT_LAND:
if(!locPtr->walkable() && search_mode_s2=SEARCH_MODE_TO_FIRM
return 0;
switch(search_mode_s2)
{
case SEARCH_MODE_IN_A_GROUP: // group move
case SEARCH_MODE_REUSE: // path-reuse
if(!locPtr->cargo_recno)
return 1;
else
{
unitPtr = unit_array[locPtr->cargo_recno];
return (unitPtr->unit_group_id==group_id_s2 && unitPtr->cur_action!=SPRITE_ATTACK) ||
unitPtr->cur_action==SPRITE_MOVE;
}
case SEARCH_MODE_A_UNIT_IN_GROUP: // a unit in a group
return locPtr->cargo_recno==0 || unit_array[locPtr->cargo_recno]->cur_action==SPRITE_MOVE;
case SEARCH_MODE_TO_ATTACK: // to attack target
if(!locPtr->cargo_recno)
return 1;
else
{
unitPtr = unit_array[locPtr->cargo_recno];
return (unitPtr->unit_group_id==group_id_s2 && unitPtr->cur_action!=SPRITE_ATTACK) ||
locPtr->cargo_recno==target_recno_s2 || unitPtr->cur_action==SPRITE_MOVE;
}
case SEARCH_MODE_BLOCKING: // 2x2 unit blocking
if(locPtr->cargo_recno)
unitPtr = unit_array[locPtr->cargo_recno];
return locPtr->cargo_recno==0 ||
(unitPtr->unit_group_id==group_id_s2 && (unitPtr->cur_action==SPRITE_MOVE || unitPtr->cur_action==SPRITE_READY_TO_MOVE));
case SEARCH_MODE_TO_VEHICLE:
err_here(); //** error
return 0;
//-----------------------------------------------------------------------//
// for the following search_mode, location may be treated as walkable
// although it is not.
//-----------------------------------------------------------------------//
case SEARCH_MODE_TO_FIRM: // move to a firm, (location may be not walkable)
case SEARCH_MODE_TO_TOWN: // move to a town zone, (location may be not walkable)
return (locPtr->walkable() && (locPtr->cargo_recno==0 ||
(unit_array[locPtr->cargo_recno]->unit_group_id==group_id_s2 &&
unit_array[locPtr->cargo_recno]->cur_action!=SPRITE_ATTACK) )) ||
(xLoc>=building_x1_s2 && xLoc<=building_x2_s2 && yLoc>=building_y1_s2 && yLoc<=building_y2_s2);
case SEARCH_MODE_TO_WALL_FOR_GROUP: // move to wall for a group, (location may be not walkable)
return (locPtr->walkable() && (locPtr->cargo_recno==0 ||
(unit_array[locPtr->cargo_recno]->unit_group_id==group_id_s2 &&
unit_array[locPtr->cargo_recno]->cur_action!=SPRITE_ATTACK) )) ||
(xLoc==final_dest_x_s2 && yLoc==final_dest_y_s2);
case SEARCH_MODE_TO_WALL_FOR_UNIT: // move to wall for a unit only, (location may be not walkable)
return (locPtr->walkable() && locPtr->cargo_recno==0) ||
(xLoc==final_dest_x_s2 && yLoc==final_dest_y_s2);
}
break;
case UNIT_SEA:
if( !locPtr->sailable() )
return 0;
if( search_mode_s2== SEARCH_MODE_A_UNIT_IN_GROUP)
return locPtr->cargo_recno==0;
else
return locPtr->cargo_recno==0 || unit_array[locPtr->cargo_recno]->unit_group_id==group_id_s2 ||
(search_mode_s2==SEARCH_MODE_TO_ATTACK && locPtr->cargo_recno==target_recno_s2);
break;
case UNIT_AIR:
if( search_mode_s2== SEARCH_MODE_A_UNIT_IN_GROUP)
return locPtr->air_cargo_recno==0;
else
return locPtr->air_cargo_recno==0 || unit_array[locPtr->air_cargo_recno]->unit_group_id==group_id_s2 ||
(search_mode_s2==SEARCH_MODE_TO_ATTACK && locPtr->air_cargo_recno==target_recno_s2);
break;
default:
err_here();
break;
}
return 0;
}
//------- End of static function can_move_to ----------//
//------- Begin of static function can_move_to_s2 ----------//
static int can_move_to_s2(int xLoc, int yLoc) // xLoc, yLoc is location after applying shift-map-method
{
//------------------------------------------------//
// note: return value should be 0 or 1
//------------------------------------------------//
if(can_move_to(xLoc,yLoc) && can_move_to(xLoc+1,yLoc) &&
can_move_to(xLoc,yLoc+1) && can_move_to(xLoc+1,yLoc+1))
return 1; // is walkable
else
return 0; // is not walkable as one point is not walkable
}
//------- End of static function can_move_to_s2 ----------//
//-------- Begin of function SeekPathS2::init ---------//
void SeekPathS2::init(int maxNode)
{
max_node = maxNode;
node_array = (NodeS2*) mem_add( max_node * sizeof(NodeS2) );
node_matrix = (short*) mem_add(sizeof(short)*(MAX_WORLD_X_LOC/2+1)*(MAX_WORLD_Y_LOC/2+1));
path_status = PATH_WAIT;
open_node_list = NULL;
closed_node_list = NULL;
}
//--------- End of function SeekPathS2::init ---------//
//-------- Begin of function SeekPathS2::deinit ---------//
void SeekPathS2::deinit()
{
if( node_array )
{
mem_del(node_array);
node_array = NULL;
}
if( node_matrix )
{
mem_del(node_matrix);
node_matrix = NULL;
}
}
//--------- End of function SeekPathS2::deinit ---------//
//-------- Begin of function SeekPathS2::set_node_matrix ---------//
void SeekPathS2::set_node_matrix(short reuseNodeMatrix[])
{
reuse_node_matrix_ptr_s2 = reuseNodeMatrix;
}
//--------- End of function SeekPathS2::set_node_matrix ---------//
//-------- Begin of function SeekPathS2::reset ---------//
void SeekPathS2::reset()
{
path_status=PATH_WAIT;
open_node_list=NULL;
closed_node_list=NULL;
}
//--------- End of function SeekPathS2::reset ---------//
//-------- Begin of function SeekPathS2::add_result_node ---------//
inline void SeekPathS2::add_result_node(ResultNode** curPtr, ResultNode** prePtr, int& count)
{
err_when(abs((*curPtr)->node_x-(*prePtr)->node_x)>1 || abs((*curPtr)->node_y-(*prePtr)->node_y)>1);
*prePtr = *curPtr;
(*curPtr)++;
count++;
}
//--------- End of function SeekPathS2::add_result_node ---------//
//-------- Begin of function SeekPathS2::seek ---------//
//
// sx, sy - the starting world location.
// dx, dy - the destination world location.
// groupId - unit group id.
// mobileType - mobile type, can be UNIT_AIR, UNIT_LAND or UNIT_SEA
//
// [int] searchMode - 1, SEARCH_MODE_IN_A_GROUP for one group with an unique group id (default)
// 2, SEARCH_MODE_A_UNIT_IN_GROUP for one sprite in a group
// 3, SEARCH_MODE_TO_ATTACK for attacking
// 4, SEARCH_MODE_REUSE for path reuse
// 5, SEARCH_MODE_BLOCKING for 2x2 unit blocked searching
// 6, SEARCH_MODE_TO_FIRM for moving to a firm
// 7, SEARCH_MODE_TO_TOWN for moving to a town zone
// 8, SEARCH_MODE_TO_VEHICLE for moving to a vehicle
// (default : 1)
//
// [int] miscNo - target record no if searchMode=SEARCH_MODE_TO_ATTACK
// - firm ID if searchMode=SEARCH_MODE_TO_FIRM
//
// [int] maxTries - maximum no. of tries in the first seek action.
// this refer to the maximum no. of nodes created.
// (default : max_node)
//
// [int] borderX1, borderY1, - borders of the seek area in the world map
// borderX2, borderY2 (default: the whole map)
//
// Note: if maxTries==max_node, incremental seek (PATH_SEEKING) won't happen.
//
// return : seekStatus - PATH_FOUND, PATH_SEEKING, PATH_NODE_USED_UP, or PATH_IMPOSSIBLE
// if PATH_FOUND, or PATH_NODE_USED_UP, can call get_result() to retrieve the result.
//
int SeekPathS2::seek(int sx,int sy,int dx,int dy,DWORD groupId,char mobileType,short searchMode,short miscNo,
int maxTries,int borderX1,int borderY1,int borderX2,int borderY2)
{
//-------- initialize vars --------------//
path_status = PATH_SEEKING;
world_loc_matrix = world.loc_matrix; // alias for fast access
open_node_list = NULL;
closed_node_list = NULL;
search_mode_s2 = searchMode;
group_id_s2 = groupId;
mobile_type_s2 = mobileType;
//------------------------------------------------------------------------------//
// extract informaton from the parameter "miscNo"
//------------------------------------------------------------------------------//
target_recno_s2 = building_id_s2 = 0;
building_x1_s2 = building_y1_s2 = building_x2_s2 = building_y2_s2 = -1;
err_when(search_mode_s2==SEARCH_MODE_TO_VEHICLE);
if(search_mode_s2==SEARCH_MODE_TO_ATTACK)
target_recno_s2 = miscNo;
else
{
building_id_s2 = miscNo;
building_x1_s2 = dx; // upper left corner location
building_y1_s2 = dy;
//------- calculate the lower right corner location -------//
if(search_mode_s2==SEARCH_MODE_TO_FIRM)
{
searchFirmInfo_s2 = firm_res[building_id_s2];
building_x2_s2 = dx+searchFirmInfo_s2->loc_width-1;
building_y2_s2 = dy+searchFirmInfo_s2->loc_height-1;
}
else if(search_mode_s2==SEARCH_MODE_TO_TOWN)
{
if(miscNo != -1)
{
Location* buildPtr = world.get_loc(dx, dy);
Town* targetTown = town_array[buildPtr->town_recno()];
building_x2_s2 = targetTown->loc_x2;
building_y2_s2 = targetTown->loc_y2;
}
else // searching to settle. Detail explained in function set_move_to_surround()
{
building_x2_s2 = building_x1_s2+STD_TOWN_LOC_WIDTH-1;
building_y2_s2 = building_y1_s2+STD_TOWN_LOC_HEIGHT-1;
}
}
}
//------------------------------------------------------------------------------//
// set start location and destination location
//------------------------------------------------------------------------------//
real_sour_x = sx;
real_sour_y = sy;
//---------- adjust destination for some kind of searching ------------//
if(search_mode_s2==SEARCH_MODE_TO_FIRM || search_mode_s2==SEARCH_MODE_TO_TOWN)
{
final_dx = (building_x1_s2+building_x2_s2)/2; // the destination is set to be the middle of the building
final_dy = (building_y1_s2+building_y2_s2)/2;
}
else
{
//---------- no adjustment --------//
final_dx = real_dest_x = dx;
final_dy = real_dest_y = dy;
}
//------------------------------------------------------------------------------//
// check whether applying shift-map-method
//------------------------------------------------------------------------------//
if(final_dx%2) // perform x-shift
{
use_shift_map_method_s2 = 1;
shift_map_x_offset_s2 = -1;
vir_start_x_s2 = sx+1;
final_dest_x_s2 = final_dx+1;
}
else
{
use_shift_map_method_s2 = 0;
shift_map_x_offset_s2 = 0;
vir_start_x_s2 = sx;
final_dest_x_s2 = final_dx;
}
if(final_dy%2) // perform y-shift
{
use_shift_map_method_s2 = 1;
shift_map_y_offset_s2 = -1;
vir_start_y_s2 = sy+1;
final_dest_y_s2 = final_dy+1;
}
else
{
//use_shift_map_method_s2 = 0; // have been set to zero in the previous check
shift_map_y_offset_s2 = 0;
vir_start_y_s2 = sy;
final_dest_y_s2 = final_dy;
}
//--------------------------------------------------------------//
// change to 2x2 node format
//--------------------------------------------------------------//
border_x1 = short(borderX1/2); // change to 2x2 node format
border_y1 = short(borderY1/2);
border_x2 = short(borderX2/2);
border_y2 = short(borderY2/2);
if(shift_map_x_offset_s2!=0) // adjust if shift-map is used
border_x2++;
if(shift_map_y_offset_s2!=0)
border_y2++;
//-------------- initialize the array -----------------//
memset(source_blocked_exit_direction, 0, sizeof(char)*8);
//----- determine the blocked exit direction in starting point----------//
// there are four cases the real source located in the 2x2 node
//
// -- -- the number in the 2x2 node representing where the
// | 1| 2| upper_left location of the unit is
// -- --
// | 3| 4|
// -- --
if(vir_start_y_s2%2 != 1)
{
if(vir_start_x_s2%2 != 1) // case 1
source_locate_type = 1;
else // case 2
{
source_locate_type = 2;
if(!can_move_to(vir_start_x_s2-1, vir_start_y_s2+1) && !can_move_to(vir_start_x_s2, vir_start_y_s2-1))
source_blocked_exit_direction[7] = 1; // direction 8
if(!can_move_to(vir_start_x_s2-1, vir_start_y_s2) && !can_move_to(vir_start_x_s2, vir_start_y_s2+2))
source_blocked_exit_direction[1] = 1; // direction 2
// other cases will not be checked as these cases do not crack the search
}
}
else
{
if(vir_start_x_s2%2 != 1) // case 3
{
source_locate_type = 3;
if(!can_move_to(vir_start_x_s2, vir_start_y_s2-1) && !can_move_to(vir_start_x_s2+2, vir_start_y_s2))
source_blocked_exit_direction[5] = 1; // direction 6
if(!can_move_to(vir_start_x_s2-1, vir_start_y_s2) && !can_move_to(vir_start_x_s2+1, vir_start_y_s2-1))
source_blocked_exit_direction[7] = 1; // direction 8
// other cases will not be checked as these cases do not crack the search
}
else // case 4
{
source_locate_type = 4;
if(!can_move_to(vir_start_x_s2, vir_start_y_s2-1) || !can_move_to(vir_start_x_s2-1, vir_start_y_s2))
source_blocked_exit_direction[7] = 1; // direction 8
if(!can_move_to(vir_start_x_s2-1, vir_start_y_s2+1) && !can_move_to(vir_start_x_s2, vir_start_y_s2-1))
source_blocked_exit_direction[0] = 1; // direction 1
if(!can_move_to(vir_start_x_s2-1, vir_start_y_s2) && !can_move_to(vir_start_x_s2+1, vir_start_y_s2-1))
source_blocked_exit_direction[6] = 1; // direction 7
// other cases will not be checked as these cases do not crack the search
}
}
source_x_s2 = short(vir_start_x_s2/2); // the upper left corner is used
source_y_s2 = short(vir_start_y_s2/2);
err_when(final_dest_x_s2%2 || final_dest_y_s2%2);
dest_x = short(final_dest_x_s2/2);
dest_y = short(final_dest_y_s2/2);
if(search_mode_s2!=SEARCH_MODE_REUSE)
{
max_node_num_s2 = 0xFFFF;
memset(node_matrix, 0, sizeof(short)*((MAX_WORLD_X_LOC/2+1)*(MAX_WORLD_Y_LOC/2+1)));
}
else
{
max_node_num_s2 = max_node;
memcpy(node_matrix, reuse_node_matrix_ptr_s2, sizeof(short)*((MAX_WORLD_X_LOC/2+1)*(MAX_WORLD_Y_LOC/2+1)));
}
//--------- create the first node --------//
node_count = 0;
result_node_ptr = NULL;
NodeS2 *nodePtr = node_array + node_count++;
memset(nodePtr, 0, sizeof(NodeS2));
//-------- store the upper left coordinate of the node ----------//
upper_left_x = source_x_s2<<1;
upper_left_y = source_y_s2<<1;
//---------- calculate the node type -----------//
switch(source_locate_type)
{
case 1: nodePtr->node_type = 15;
break;
case 2: nodePtr->node_type = 10+can_move_to(vir_start_x_s2-1,vir_start_y_s2)+
can_move_to(vir_start_x_s2-1,vir_start_y_s2+1)*4;
break;
case 3: nodePtr->node_type = 12+can_move_to(vir_start_x_s2,vir_start_y_s2-1)+
can_move_to(vir_start_x_s2+1,vir_start_y_s2-1)*2;
break;
case 4: nodePtr->node_type = 8+can_move_to(vir_start_x_s2-1,vir_start_y_s2-1)+
can_move_to(vir_start_x_s2,vir_start_y_s2-1)*2+
can_move_to(vir_start_x_s2-1,vir_start_y_s2)*4;
break;
default: err_here();
break;
}
err_when(nodePtr->node_type>15 || nodePtr->node_type <0);
is_dest_blocked = !can_move_to_s2(final_dest_x_s2, final_dest_y_s2);
// whether the destination is blocked, if so, only search till the destination's neighbor locations
nodePtr->node_g = 0;
nodePtr->node_h = (source_x_s2-dest_x)*(source_x_s2-dest_x)+(source_y_s2-dest_y)*(source_y_s2-dest_y); // should really use sqrt().
nodePtr->node_f = nodePtr->node_g + nodePtr->node_h;
nodePtr->node_x = source_x_s2;
nodePtr->node_y = source_y_s2;
nodePtr->enter_direction = 0;
open_node_list=nodePtr; // make Open List point to first node
//--- if the destination is the current postion or next to it & the dest is occupied ---//
if(source_x_s2==dest_x && source_y_s2==dest_y)
{
path_status = PATH_FOUND;
result_node_ptr = nodePtr;
return path_status;
}
//------------ seek now ------------------//
if( !maxTries )
maxTries = max_node;
return continue_seek( maxTries, 1); // 1-first seek session of the current seek order
}
//-------- End of function SeekPathS2::seek ---------//
//---- Begin of function SeekPathS2::continue_seek ---------//
//
// If the last seek operation does not find the whole path,
// continue the search.
//
// maxTries - maximum path seeking tries
// [char] firstSeek - whether it's the first seek session of the seek order.
// (default: 0)
//
// return : seekStatus - PATH_FOUND, PATH_SEEKING, PATH_NODE_USED_UP,
// or PATH_IMPOSSIBLE
//
// You can call get_result() to retrieve the result.
//
int SeekPathS2::continue_seek(int maxTries, char firstSeek)
{
if( path_status != PATH_SEEKING )
return path_status;
//------- aliasing class member vars for fast access ------//
cur_seek_path_s2 = this;
cur_dest_x_s2 = dest_x;
cur_dest_y_s2 = dest_y;
cur_node_matrix_s2 = node_matrix;
cur_node_array_s2 = node_array;
cur_border_x1_s2 = border_x1;
cur_border_y1_s2 = border_y1;
cur_border_x2_s2 = border_x2;
cur_border_y2_s2 = border_y2;
//------ seek the path using the A star algorithm -----//
NodeS2 *bestNodePtr;
int maxNode = max_node-MAX_CHILD_NODE; // generate_successors() can generate a max of MAX_CHILD_NODE new nodes per call
if(maxTries < maxNode)
maxNode = maxTries-MAX_CHILD_NODE; // limit the nodes used in shortest path searching
for(int i=0; i= maxNode )
{
path_status = PATH_NODE_USED_UP;
break;
}
//------------------------------------------//
// If the path is found OR
//
// If the destination is blocked,
// consider it done when we are next to it.
//------------------------------------------//
if((bestNodePtr->node_x==dest_x && bestNodePtr->node_y==dest_y) ||
(is_dest_blocked && abs(bestNodePtr->node_x-dest_x)<=0 && abs(bestNodePtr->node_y-dest_y)<=0))
{
path_status = PATH_FOUND;
result_node_ptr = bestNodePtr;
break;
}
//--------- generate successors -------//
if(bestNodePtr->generate_successors(bestNodePtr->enter_direction))
{
path_status = PATH_REUSE_FOUND;
result_node_ptr = reuse_result_node_ptr_s2;
return path_status;
}
}
err_when( cur_stack_pos_s2!=0 ); // it should be zero all the times, all pushes should have been poped
return path_status;
}
//------ End of function SeekPathS2::continue_seek ---------//
//---- Begin of function SeekPathS2::get_result ---------//
//
// Compile the seek result nodes using results processed by
// seek() and continue_seek() and store the results in
// an array of ResultNode.
//
// resultNodeCount - a reference var for returning the no. of result nodes.
//
// return : an array of ResultNode.
// the caller function is responsible for
// freeing the memory of the array.
//
ResultNode* SeekPathS2::get_result(int& resultNodeCount, short& pathDist)
{
resultNodeCount = pathDist = 0;
short useClosestNode = 0;// indicate whether closest node is return instead of the actual node
if( !result_node_ptr ) // if PATH_IMPOSSIBLE or PATH_NODE_USED_UP, result_node_ptr is NULL, we need to call get_closest_node() to get the closest node.
{
result_node_ptr = return_closest_node();
useClosestNode = 1;
if( !result_node_ptr )
return NULL;
}
//--------------------------------------------------//
// Trace backwards to the starting node, and rationalize
// nodes (i.e. group nodes of the same direction into
// single nodes.)
//--------------------------------------------------//
NodeS2* nodePtr = result_node_ptr; // the node current being processed
NodeS2* baseNodePtr = result_node_ptr; // the first end node for connecting the other end node for the path in that direction.
NodeS2* parentNode = nodePtr->parent_node; // the parent node of nodePtr
NodeS2* childNodePtr = nodePtr; // it should point to the children node of nodePtr
//------------------------------------------------------------------------
// there are only one node, source & destination within the same 2x2 node
//------------------------------------------------------------------------
if( !parentNode ) // parentNode==0 when the source location is the desination already
{
if( (vir_start_x_s2!=final_dest_x_s2 || vir_start_y_s2!=final_dest_y_s2) &&
abs(vir_start_x_s2-final_dest_x_s2)<=1 && abs(vir_start_y_s2-final_dest_y_s2)<=1 &&
can_move_to_s2(vir_start_x_s2,vir_start_y_s2) && // for source
can_move_to_s2(final_dest_x_s2,final_dest_y_s2)) // for destination
{
pathDist = 1;
ResultNode* resultNodeArray1 = (ResultNode*) mem_add(sizeof(ResultNode)*2);
ResultNode* resultNodePtr1 = resultNodeArray1;
resultNodeCount=2;
resultNodePtr1->node_x = vir_start_x_s2 + shift_map_x_offset_s2;
resultNodePtr1->node_y = vir_start_y_s2 + shift_map_y_offset_s2;
resultNodePtr1++;
resultNodePtr1->node_x = final_dest_x_s2 + shift_map_x_offset_s2;
resultNodePtr1->node_y = final_dest_y_s2 + shift_map_y_offset_s2;
#ifdef DEBUG
debugPtr1 = resultNodeArray1;
debugPtr2 = resultNodeArray1+1;
err_when(debugPtr1->node_x==debugPtr2->node_x && debugPtr1->node_y==debugPtr2->node_y);
#endif
return resultNodeArray1;
}
else
return NULL;
}
resultNodeCount = 1;
//-----------------------------------
// count the number of 2x2 node
//-----------------------------------
int numOfNode=0;
NodeS2* curPtr = result_node_ptr;
while(curPtr != NULL)
{
curPtr = curPtr->parent_node;
numOfNode++;
}
sys_yield(); // update cursor position
//-----------------------------------------
// otherwise, there are more than one node
//-----------------------------------------
ResultNode* maxSizeResultNodeArray; // store all the result node in the reverse order, the turning point will be extracted later
int nodeAllocated, nodeCount=0;
int preNodeCount = nodeCount;
nodeAllocated = numOfNode*2+2;
maxSizeResultNodeArray = (ResultNode*) mem_add(nodeAllocated*sizeof(ResultNode));
max_size_result_node_ptr = maxSizeResultNodeArray;
parent_result_node_ptr = maxSizeResultNodeArray;
//----------------------------------
// start from the destination
//----------------------------------
memset(max_size_result_node_ptr, 0, sizeof(ResultNode)*nodeAllocated);
int upper_left_x = nodePtr->node_x<<1;
int upper_left_y = nodePtr->node_y<<1;
if(!useClosestNode && (search_mode_s2==SEARCH_MODE_TO_ATTACK || can_move_to_s2(final_dest_x_s2, final_dest_y_s2)))
{
max_size_result_node_ptr->node_x = final_dest_x_s2;
max_size_result_node_ptr->node_y = final_dest_y_s2;
max_size_result_node_ptr++; // note: parent_result_node_ptr don't change here
nodeCount++;
//---------------------------------------------------
// process the end node, may pass through two points
//---------------------------------------------------
if(search_mode_s2==SEARCH_MODE_REUSE)
process_end_node(upper_left_x, upper_left_y, nodePtr->node_type, nodePtr->enter_direction, nodeCount);
}
else // closest node is used
{
//------------------------------------------------------------------------//
// may generate duplicated node for the destination if closet node is used.
//------------------------------------------------------------------------//
switch(nodePtr->enter_direction)
{
case 1: max_size_result_node_ptr->node_x = upper_left_x-1;
max_size_result_node_ptr->node_y = upper_left_y;
break;
case 2: max_size_result_node_ptr->node_x = upper_left_x-1;
max_size_result_node_ptr->node_y = upper_left_y+1;
break;
case 3: max_size_result_node_ptr->node_x = upper_left_x;
max_size_result_node_ptr->node_y = upper_left_y+1;
break;
case 4: max_size_result_node_ptr->node_x = upper_left_x+1;
max_size_result_node_ptr->node_y = upper_left_y+1;
break;
case 5: max_size_result_node_ptr->node_x = upper_left_x+1;
max_size_result_node_ptr->node_y = upper_left_y;
break;
case 6: max_size_result_node_ptr->node_x = upper_left_x+1;
max_size_result_node_ptr->node_y = upper_left_y-1;
break;
case 7: max_size_result_node_ptr->node_x = upper_left_x;
max_size_result_node_ptr->node_y = upper_left_y-1;
break;
case 8: max_size_result_node_ptr->node_x = upper_left_x-1;
max_size_result_node_ptr->node_y = upper_left_y-1;
break;
default: err_here();
break;
}
max_size_result_node_ptr++; // note: parent_result_node_ptr don't change here
nodeCount++;
}
nodePtr = nodePtr->parent_node; // next 2x2 node
//--------------------------------------------------
// get the actual path, process from the second node
//--------------------------------------------------
int yieldCount = 0;
while( (parentNode=nodePtr->parent_node) != NULL )
{
upper_left_x = nodePtr->node_x<<1;
upper_left_y = nodePtr->node_y<<1;
err_when(nodePtr->enter_direction==(childNodePtr->enter_direction+3)%8+1);
get_real_result_node(nodeCount, nodePtr->enter_direction, (childNodePtr->enter_direction+3)%8+1,
nodePtr->node_type, upper_left_x, upper_left_y);
childNodePtr = nodePtr;
nodePtr = parentNode;
//err_when(nodeCount+nodePtr->node_g+2 > nodeAllocated);
yieldCount++;
if(yieldCount%20==0)
sys_yield(); // update cursor position
}
sys_yield(); // update cursor position
debug_check_paths2(maxSizeResultNodeArray, nodeCount);
/*#ifdef DEBUG
debugPtr1 = maxSizeResultNodeArray;
debugPtr2 = maxSizeResultNodeArray+1;
for(debugCount=1; debugCountnode_x - debugPtr1->node_x;
debugVY = debugPtr2->node_y - debugPtr1->node_y;
err_when(debugVX!=0 && debugVY!=0 && abs(debugVX)!=abs(debugVY));
debugPtr1++;
debugPtr2++;
}
#endif*/
//----------------------------------------------------
// process the starting node
// nodePtr points at the starting node now
//----------------------------------------------------
err_when(nodePtr->enter_direction); // it should be zero
upper_left_x = nodePtr->node_x<<1;
upper_left_y = nodePtr->node_y<<1;
//------------------------------------------------------------------------------------------//
// process the starting node
//------------------------------------------------------------------------------------------//
process_start_node(upper_left_x, upper_left_y, nodePtr->node_type, (childNodePtr->enter_direction+3)%8+1, nodeCount);
max_size_result_node_ptr->node_x = vir_start_x_s2;
max_size_result_node_ptr->node_y = vir_start_y_s2;
err_when((abs(max_size_result_node_ptr->node_x-parent_result_node_ptr->node_x)>1) ||
(abs(max_size_result_node_ptr->node_y-parent_result_node_ptr->node_y)>1));
nodeCount++;
sys_yield(); // update cursor position
debug_check_paths2(maxSizeResultNodeArray, nodeCount);
/*#ifdef DEBUG
debugPtr1 = maxSizeResultNodeArray;
debugPtr2 = maxSizeResultNodeArray+1;
for(debugCount=1; debugCountnode_x - debugPtr1->node_x;
debugVY = debugPtr2->node_y - debugPtr1->node_y;
err_when(debugVX!=0 && debugVY!=0 && (abs(debugVX)!=abs(debugVY)));
debugPtr1++;
debugPtr2++;
}
#endif*/
//--------------------------------------------------//
// smooth the path
//--------------------------------------------------//
maxSizeResultNodeArray = smooth_the_path(maxSizeResultNodeArray, nodeCount);
sys_yield(); // update cursor position
parent_result_node_ptr = maxSizeResultNodeArray;
max_size_result_node_ptr = maxSizeResultNodeArray+1;
ResultNode* result_node_pointer = max_size_result_node_ptr;
//----------------------------------
// get the turning point
//----------------------------------
short vectorX = max_size_result_node_ptr->node_x - parent_result_node_ptr->node_x;
short vectorY = max_size_result_node_ptr->node_y - parent_result_node_ptr->node_y;
short newVectorX, newVectorY;
for(int i=1; inode_x-parent_result_node_ptr->node_x);
newVectorY=(max_size_result_node_ptr->node_y-parent_result_node_ptr->node_y);
err_when(newVectorY!=0 && newVectorX!=0 && abs(newVectorX)!=abs(newVectorY));
//------ turning to another direction at this point ------//
if(vectorX!=newVectorX || vectorY!=newVectorY)
{
if(newVectorX!=0 || newVectorY!=0)
{
result_node_pointer->node_x = parent_result_node_ptr->node_x;
result_node_pointer->node_y = parent_result_node_ptr->node_y;
result_node_pointer++;
resultNodeCount++;
vectorX = newVectorX;
vectorY = newVectorY;
}
}
if(i%20==0)
sys_yield(); // update cursor position
}
result_node_pointer->node_x = vir_start_x_s2;
result_node_pointer->node_y = vir_start_y_s2;
result_node_pointer++;
resultNodeCount++;
//------------------------------------------------//
// After the above process, here we will have a
// link of rationalize nodes. Retrieve them in the
// backwards order
//------------------------------------------------//
ResultNode *resultNodeArray = (ResultNode*) mem_add( sizeof(ResultNode) * resultNodeCount );
ResultNode *resultNodePtr = resultNodeArray+resultNodeCount-1;
int processCount = 1;
ResultNode *preNodePtr = maxSizeResultNodeArray;
resultNodePtr->node_x = preNodePtr->node_x;
resultNodePtr->node_y = preNodePtr->node_y;
resultNodePtr--;
result_node_pointer = maxSizeResultNodeArray+1;
err_when(pathDist!=0);
int xDist, yDist;
while(processCount++ < resultNodeCount)
{
err_when(result_node_pointer->node_x<0 || result_node_pointer->node_x>=MAX_WORLD_X_LOC ||
result_node_pointer->node_y<0 || result_node_pointer->node_y>=MAX_WORLD_Y_LOC);
resultNodePtr->node_x = result_node_pointer->node_x;
resultNodePtr->node_y = result_node_pointer->node_y;
resultNodePtr--;
xDist = abs(result_node_pointer->node_x-preNodePtr->node_x);
yDist = abs(result_node_pointer->node_y-preNodePtr->node_y);
err_when((!xDist && !yDist) || (xDist && yDist && xDist!=yDist));
pathDist += (xDist) ? xDist : yDist;
preNodePtr = result_node_pointer;
result_node_pointer++;
if(processCount%20==0)
sys_yield(); // update cursor position
}
err_when(nodeAllocatednode_x += shift_map_x_offset_s2;
adjustNode->node_y += shift_map_y_offset_s2;
adjustNode++;
}
}
debug_check_paths2(resultNodeArray, resultNodeCount);
/*#ifdef DEBUG
debugPtr1 = resultNodeArray;
debugPtr2 = resultNodeArray+1;
for(debugCount=1; debugCountnode_x - debugPtr1->node_x;
debugVY = debugPtr2->node_y - debugPtr1->node_y;
err_when(debugVX!=0 && debugVY!=0 && (abs(debugVX)!=abs(debugVY)));
debugPtr1++;
debugPtr2++;
}
#endif*/
//--------------------------------------------------//
// return NULL if there are only two nodes and these
// nodes are equal
//--------------------------------------------------//
if(resultNodeCount == 2)
{
ResultNode *curTestNode1 = resultNodeArray;
ResultNode *curTestNode2 = resultNodeArray+1;
if(curTestNode1->node_x==curTestNode2->node_x &&
curTestNode1->node_y==curTestNode2->node_y)
{
mem_del(resultNodeArray);
resultNodeCount = 0;
pathDist = 0;
return NULL;
}
}
#ifdef DEBUG
if(resultNodeCount==2)
{
debugPtr1 = resultNodeArray;
debugPtr2 = resultNodeArray+1;
err_when(debugPtr1->node_x==debugPtr2->node_x && debugPtr1->node_y==debugPtr2->node_y);
}
#endif
sys_yield(); // update cursor position
return resultNodeArray;
}
//------ End of function SeekPathS2::get_result ---------//
//---- Begin of function SeekPathS2::process_end_node ---------//
void SeekPathS2::process_end_node(int xLoc, int yLoc, char nodeType, char enterDirection, int &nodeCount)
{
short usePathSuccess = 0; // if failure, use the last path in the checking
short destType = 1 + (final_dest_x_s2%2) + 2*(final_dest_y_s2%2);
switch(destType)
{
case 1:
break;
case 2:
switch(enterDirection)
{
case 1:
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2:
err_when(!(nodeType&0x1) && !can_move_to(xLoc+1,yLoc+2));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+!(nodeType&0x1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 3: case 4: case 6: case 7:
break;
case 5:
break;
case 8:
err_when(!(nodeType&0x4) && !can_move_to(xLoc+1,yLoc-1));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-!(nodeType&0x4);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
case 3:
switch(enterDirection)
{
case 1: case 2: case 4: case 5:
break;
case 3:
break;
case 6:
err_when(!(nodeType&0x1) && !can_move_to(xLoc+2,yLoc+1));
max_size_result_node_ptr->node_x = xLoc+!(nodeType&0x1);
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
err_when(!(nodeType&0x2) && !can_move_to(xLoc-1,yLoc+1));
max_size_result_node_ptr->node_x = xLoc-!(nodeType&0x2);
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
case 4:
switch(enterDirection)
{
case 1:
err_when(!(nodeType&0x2) && !can_move_to(xLoc,yLoc+2));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+can_move_to(xLoc,yLoc+2);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2:
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 3: case 4: case 5:
break;
case 6:
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
err_when(!(nodeType&0x4) && !can_move_to(xLoc+2,yLoc));
max_size_result_node_ptr->node_x = xLoc+can_move_to(xLoc+2,yLoc);
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
default: err_here();
break;
}
}
//------ End of function SeekPathS2::process_end_node ---------//
//---- Begin of function SeekPathS2::process_start_node ---------//
void SeekPathS2::process_start_node(int xLoc, int yLoc, char nodeType, char exitDirection, int &nodeCount)
{
short usePathSuccess = 0; // if failure, use the last path in the checking
switch(source_locate_type)
{
case 1:
switch(exitDirection)
{
case 1: // 3 possible paths
if(parent_result_node_ptr->node_ynode_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y>yLoc &&
can_move_to(xLoc-1,yLoc+2) && can_move_to(xLoc,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2: // 3 possible paths
if(parent_result_node_ptr->node_x==xLoc && //can_move_to(xLoc+1,yLoc+1) &&
can_move_to(xLoc+1,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc &&
can_move_to(xLoc-1,yLoc))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 3:
if(parent_result_node_ptr->node_x>xLoc && can_move_to(xLoc+2,yLoc+1) &&
can_move_to(xLoc+2,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_xnode_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 4:
if(parent_result_node_ptr->node_x==xLoc && //can_move_to(xLoc,yLoc+1) &&
can_move_to(xLoc,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc && //can_move_to(xLoc+1,yLoc) &&
can_move_to(xLoc+2,yLoc))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 5:
if(parent_result_node_ptr->node_ynode_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y>yLoc &&
can_move_to(xLoc+1,yLoc+2) && can_move_to(xLoc+2,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 6:
if(parent_result_node_ptr->node_y==yLoc && //can_move_to(xLoc+1,yLoc+1) &&
can_move_to(xLoc+2,yLoc+1))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_x==xLoc && can_move_to(xLoc,yLoc-1))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
if(parent_result_node_ptr->node_x>xLoc && can_move_to(xLoc+2,yLoc-1) &&
can_move_to(xLoc+2,yLoc))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_xnode_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
if(parent_result_node_ptr->node_x==xLoc && can_move_to(xLoc+1,yLoc-1))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc && can_move_to(xLoc-1,yLoc+1))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
case 2:
switch(exitDirection)
{
case 1:
if(parent_result_node_ptr->node_ynode_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y>yLoc && can_move_to(xLoc-1,yLoc+2) &&
can_move_to(xLoc,yLoc+2) && can_move_to(xLoc+1,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2:
if(parent_result_node_ptr->node_y==yLoc+1 && can_move_to(xLoc+1,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && can_move_to(xLoc+1,yLoc+2) &&
( (vir_start_x_s2-parent_result_node_ptr->node_x==parent_result_node_ptr->node_y-vir_start_y_s2) ||
(parent_result_node_ptr->node_x==xLoc) ) )
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc &&
can_move_to(xLoc-1,yLoc) && can_move_to(xLoc,yLoc))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x1) && !can_move_to(xLoc+1,yLoc+2));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+(!(nodeType&0x1));
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 3:
if(parent_result_node_ptr->node_x>xLoc && //can_move_to(xLoc+2,yLoc+1) &&
can_move_to(xLoc+2,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 4:
if(parent_result_node_ptr->node_x==xLoc && can_move_to(xLoc,yLoc+1) &&
can_move_to(xLoc,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
}
else
break;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 5:
break;
case 6:
if(parent_result_node_ptr->node_x==xLoc && can_move_to(xLoc,yLoc-1) &&
can_move_to(xLoc,yLoc))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess)
{
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
}
else
break;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
if(parent_result_node_ptr->node_x>xLoc && can_move_to(xLoc+2,yLoc-1) &&
can_move_to(xLoc+2,yLoc))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
if(parent_result_node_ptr->node_y==yLoc-1 && can_move_to(xLoc+1,yLoc-1))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && can_move_to(xLoc+1,yLoc-1) &&
( (vir_start_x_s2-parent_result_node_ptr->node_x==vir_start_y_s2-parent_result_node_ptr->node_y) ||
(parent_result_node_ptr->node_x==xLoc) ) )
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc &&
can_move_to(xLoc-1,yLoc+1) && can_move_to(xLoc,yLoc+1))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x4) && !can_move_to(xLoc+1,yLoc-1));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-(!(nodeType&0x4));
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
case 3:
switch(exitDirection)
{
case 1:
if(parent_result_node_ptr->node_y>yLoc && can_move_to(xLoc-1,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2:
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
}
break;
case 3:
break;
case 4:
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
}
break;
case 5:
if(parent_result_node_ptr->node_y>yLoc && can_move_to(xLoc+2,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 6:
if(parent_result_node_ptr->node_y==yLoc && can_move_to(xLoc+2,yLoc+1))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_x==xLoc &&
can_move_to(xLoc,yLoc-1) && can_move_to(xLoc,yLoc))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x1) && !can_move_to(xLoc+2, yLoc+1));
max_size_result_node_ptr->node_x = xLoc+!(nodeType&0x1);
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
if(parent_result_node_ptr->node_x>xLoc && can_move_to(xLoc+2,yLoc-1) &&
can_move_to(xLoc+2,yLoc))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_xnode_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
if(can_move_to(xLoc-1,yLoc+1) &&
( (vir_start_x_s2-parent_result_node_ptr->node_x==vir_start_y_s2-parent_result_node_ptr->node_y)||
(parent_result_node_ptr->node_y==yLoc) ) )
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_x==xLoc &&
can_move_to(xLoc+1,yLoc-1) && can_move_to(xLoc+1,yLoc))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x2) && !can_move_to(xLoc-1, yLoc+1));
max_size_result_node_ptr->node_x = xLoc-!(nodeType&0x2);
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
case 4:
switch(exitDirection)
{
case 1:
if(parent_result_node_ptr->node_y>yLoc && can_move_to(xLoc-1,yLoc+2) &&
can_move_to(xLoc,yLoc+2))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess && can_move_to(xLoc,yLoc+2) && parent_result_node_ptr->node_y==yLoc-1)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x2) && !can_move_to(xLoc, yLoc+2));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+!(nodeType&0x2);
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 2:
if(vir_start_x_s2-parent_result_node_ptr->node_x==parent_result_node_ptr->node_y+1-vir_start_y_s2)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
usePathSuccess++;
}
if(!usePathSuccess)
{
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
}
else
break;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 3:
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
}
break;
case 4:
break;
case 5:
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
}
break;
case 6:
if(parent_result_node_ptr->node_x+1-vir_start_x_s2==vir_start_y_s2-parent_result_node_ptr->node_y)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
if(abs(parent_result_node_ptr->node_x-vir_start_x_s2)>1 ||
abs(parent_result_node_ptr->node_y-vir_start_y_s2)>1)
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
}
else
break;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 7:
if(parent_result_node_ptr->node_x>xLoc && can_move_to(xLoc+2,yLoc-1) &&
can_move_to(xLoc+2,yLoc))
{
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_xnode_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
max_size_result_node_ptr->node_x = xLoc+1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!(nodeType&0x4) && !can_move_to(xLoc+2, yLoc));
max_size_result_node_ptr->node_x = xLoc+!(nodeType&0x4);
max_size_result_node_ptr->node_y = yLoc;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
case 8:
if(parent_result_node_ptr->node_x==xLoc && can_move_to(xLoc+1,yLoc-1))
{
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc-1;
usePathSuccess++;
}
if(!usePathSuccess && parent_result_node_ptr->node_y==yLoc && can_move_to(xLoc-1,yLoc+1))
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc;
usePathSuccess++;
}
if(!usePathSuccess)
{
max_size_result_node_ptr->node_x = xLoc-1;
max_size_result_node_ptr->node_y = yLoc-1;
}
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
err_when(!can_move_to(xLoc+1, yLoc) || !can_move_to(xLoc, yLoc+1));
max_size_result_node_ptr->node_x = xLoc;
max_size_result_node_ptr->node_y = yLoc;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, nodeCount);
break;
default: err_here();
break;
}
break;
default: err_here();
break;
}
}
//------ End of function SeekPathS2::process_start_node ---------//
//---- Begin of function SeekPathS2::get_real_result_node ---------//
//
// called by get_result to extract the point in a 2x2 node that is
// used in the shortest path
//
// count - a reference var for counting number of node in
// max_size_result_node_ptr
//
void SeekPathS2::get_real_result_node(int &count, short enterDirection, short exitDirection,
short nodeType, short xCoord, short yCoord)
{
prefer_upper_s2 = prefer_lower_s2 = prefer_left_s2 = prefer_right_s2 = 0;
switch(enterDirection)
{
case 0: err_here();
break;
case 1:
switch(exitDirection)
{
case 2: // 2 possible paths
if(parent_result_node_ptr->node_xnode_x = xCoord-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3: // 2 possible paths
if(parent_result_node_ptr->node_x>=xCoord)
prefer_right_s2 = 1;
else
{
if(can_move_to(xCoord-1,yCoord+2))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x2) && !can_move_to(xCoord, yCoord+2));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord + !(nodeType&0x2);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord + can_move_to(xCoord, yCoord+2);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5: // 2 points, 2 paths
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord,yCoord+2) || !can_move_to(xCoord+1,yCoord+2) ||
!can_move_to(xCoord+2,yCoord+2))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x8) && !can_move_to(xCoord, yCoord-1));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord-can_move_to(xCoord, yCoord-1);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord-!(nodeType&0x8);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7: // 2 possible paths
if(parent_result_node_ptr->node_x>=xCoord)
prefer_right_s2 = 1;
else
{
if(can_move_to(xCoord-1,yCoord-1))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 possible paths
if(parent_result_node_ptr->node_xnode_x = xCoord-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 2:
switch(exitDirection)
{
case 1:
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3:
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_y<=yCoord+1)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord, yCoord+3) || !can_move_to(xCoord+1, yCoord+3) ||
!can_move_to(xCoord+2, yCoord+3))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+1+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5: // 2 points, 2 paths
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord+2,yCoord+2) || !can_move_to(xCoord+1,yCoord+2))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x1) && !can_move_to(xCoord+1, yCoord+2));
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+(prefer_lower_s2 || !(nodeType&0x1));
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 points
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(nodeType != 15);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!can_move_to(xCoord-1,yCoord) && !(nodeType&0x8));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord-can_move_to(xCoord-1,yCoord);
else
max_size_result_node_ptr->node_x = xCoord-!(nodeType&0x8);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_x>=xCoord-1)
prefer_right_s2 = 1;
else
{
if(!can_move_to(xCoord-2,yCoord-1) || !can_move_to(xCoord-2,yCoord) ||
!can_move_to(xCoord-2,yCoord+1)) // must check for all 3 points to avoid problems in dummy node generated in path-reuse
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord-1-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 3: switch(exitDirection)
{
case 1: // 2 possible paths
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(can_move_to(xCoord-1,yCoord+2))
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 possible paths
if(parent_result_node_ptr->node_y>yCoord)
prefer_lower_s2 = 1;
else
{
if(!can_move_to(xCoord, yCoord) || !can_move_to(xCoord-1,yCoord))
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 possible paths
if(parent_result_node_ptr->node_y>yCoord)
prefer_lower_s2 = 1;
else
{
if(!can_move_to(xCoord+1,yCoord) || !can_move_to(xCoord+2,yCoord))
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5: // 2 possible paths
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(can_move_to(xCoord+2,yCoord+2))
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 points. 2 paths
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x1) && !can_move_to(xCoord+2, yCoord+1));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord + !(nodeType&0x1);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord + can_move_to(xCoord+2, yCoord+1);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7: // 2 points, 2 paths
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_x<=xCoord)
prefer_left_s2 = 1;
else
{
if(!can_move_to(xCoord+2,yCoord-1) || !can_move_to(xCoord+2,yCoord) ||
!can_move_to(xCoord+2,yCoord+1))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x2) && !can_move_to(xCoord-1, yCoord+1));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord - can_move_to(xCoord-1, yCoord+1);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord - !(nodeType&0x2);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 4: switch(exitDirection)
{
case 1: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord-1,yCoord+2) || !can_move_to(xCoord,yCoord+2))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x2) && !can_move_to(xCoord, yCoord+2));
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+(prefer_lower_s2 || !(nodeType&0x2));
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_y<=yCoord+1)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord-1, yCoord+3) || !can_move_to(xCoord, yCoord+3) ||
!can_move_to(xCoord+1, yCoord+3))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+1+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1+prefer_lower_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3:
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5:
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_x<=xCoord+1)
prefer_left_s2 = 1;
else
{
if(!can_move_to(xCoord+3,yCoord-1) || !can_move_to(xCoord+3,yCoord) ||
!can_move_to(xCoord+3,yCoord+1))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord+1+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7: // 2 points, 2 paths
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_x<=xCoord)
prefer_left_s2 = 1;
else
{
if(!can_move_to(xCoord+2,yCoord-1) || !can_move_to(xCoord+2,yCoord))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x4) && !can_move_to(xCoord+2, yCoord));
max_size_result_node_ptr->node_x = xCoord+(prefer_right_s2 || !(nodeType&0x4));
max_size_result_node_ptr->node_y = yCoord;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 points
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(nodeType!=15);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 5: switch(exitDirection)
{
case 1: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_y<=yCoord)
prefer_upper_s2 = 1;
else
{
if(!can_move_to(xCoord-1,yCoord+2) || !can_move_to(xCoord,yCoord+2) ||
!can_move_to(xCoord+1,yCoord+2))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+prefer_lower_s2;
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x1) && !can_move_to(xCoord+1, yCoord+2));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord + !(nodeType&0x1);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord + can_move_to(xCoord+1, yCoord+2);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3: // 2 possible paths
if(parent_result_node_ptr->node_x<=xCoord)
prefer_left_s2 = 1;
else
{
if(can_move_to(xCoord+2,yCoord+2))
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 possible paths
if(parent_result_node_ptr->node_x>xCoord)
prefer_right_s2 = 1;
else
{
if(!can_move_to(xCoord,yCoord+1) || !can_move_to(xCoord,yCoord+2))
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 possible paths
if(parent_result_node_ptr->node_x>xCoord)
prefer_right_s2 = 1;
else
{
if(!can_move_to(xCoord,yCoord-1) || !can_move_to(xCoord,yCoord))
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7: // 2 possible paths
if(parent_result_node_ptr->node_x<=xCoord)
prefer_left_s2 = 1;
else
{
if(can_move_to(xCoord+2,yCoord-1))
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 points
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x4) && !can_move_to(xCoord+1, yCoord-1));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord - can_move_to(xCoord+1, yCoord-1);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord - !(nodeType&0x4);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 6: switch(exitDirection)
{
case 1: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x8) && !can_move_to(xCoord, yCoord-1));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord - can_move_to(xCoord, yCoord-1);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord - !(nodeType&0x8);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 points
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(nodeType != 15);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x1) && !can_move_to(xCoord+2, yCoord+1));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord + !(nodeType&0x1);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord + can_move_to(xCoord+2, yCoord+1);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_x<=xCoord+1)
prefer_left_s2 = 1;
else
{
if(!can_move_to(xCoord+3,yCoord) || !can_move_to(xCoord+3,yCoord+1) ||
!can_move_to(xCoord+3,yCoord+2))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord+1+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5:
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7:
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_y>=yCoord-1)
prefer_lower_s2 = 1;
else
{
if(!can_move_to(xCoord-1,yCoord-2) || !can_move_to(xCoord,yCoord-2) ||
!can_move_to(xCoord+1,yCoord-2)) // must check for all 3 points to avoid problems in dummy node generated in path-reuse
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-1-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord-1-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 7: switch(exitDirection)
{
case 1: // 2 possible paths
if(parent_result_node_ptr->node_y>=yCoord)
prefer_lower_s2 = 1;
else
{
if(can_move_to(xCoord-1,yCoord-1))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x8) && !can_move_to(xCoord-1, yCoord));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord - can_move_to(xCoord-1, yCoord);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord - !(nodeType&0x8);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3: // 2 points, 2 paths
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if(parent_result_node_ptr->node_x<=xCoord)
prefer_left_s2 = 1;
else
{
if(!can_move_to(xCoord+2,yCoord) || !can_move_to(xCoord+2,yCoord+1) ||
!can_move_to(xCoord+2,yCoord+2))
prefer_left_s2 = 1;
else
prefer_right_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord+prefer_right_s2;
max_size_result_node_ptr->node_y = yCoord;
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x4) && !can_move_to(xCoord+2, yCoord));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord + !(nodeType&0x4);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord + can_move_to(xCoord+2, yCoord);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord+1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5: // 2 possible paths
if(parent_result_node_ptr->node_y>=yCoord)
prefer_lower_s2 = 1;
else
{
if(can_move_to(xCoord+1,yCoord-1))
prefer_upper_s2 = 1;
else
prefer_lower_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 possible paths
if(parent_result_node_ptr->node_ynode_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 8: // 2 possible paths
if(parent_result_node_ptr->node_ynode_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
case 8: switch(exitDirection)
{
case 1:
max_size_result_node_ptr->node_x = xCoord-1;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 2: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_x>=xCoord-1)
prefer_right_s2 = 1;
else
{
if(!can_move_to(xCoord-2,yCoord) || !can_move_to(xCoord-2,yCoord+1) ||
!can_move_to(xCoord-2,yCoord+2))
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord-1-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord-1-prefer_left_s2;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 3: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord+1;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_right_s2 = 1;
else
prefer_left_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x2) && !can_move_to(xCoord-1, yCoord+1));
max_size_result_node_ptr->node_y = yCoord;
if(prefer_left_s2)
max_size_result_node_ptr->node_x = xCoord - can_move_to(xCoord-1, yCoord+1);
else // prefer_right_s2
max_size_result_node_ptr->node_x = xCoord - !(nodeType&0x2);
err_when(max_size_result_node_ptr->node_x!=xCoord && max_size_result_node_ptr->node_x!=xCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 4: // 2 points
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord+1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(nodeType!=15);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 5: // 2 points, 2 paths
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord;
//----------- process path selection ---------------//
if( (parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x==0) ||
(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y==0) )
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
err_when(!(nodeType&0x4) && !can_move_to(xCoord+1, yCoord-1));
max_size_result_node_ptr->node_x = xCoord;
if(prefer_upper_s2)
max_size_result_node_ptr->node_y = yCoord - can_move_to(xCoord+1, yCoord-1);
else // prefer_lower_s2
max_size_result_node_ptr->node_y = yCoord - !(nodeType&0x4);
err_when(max_size_result_node_ptr->node_y!=yCoord && max_size_result_node_ptr->node_y!=yCoord-1);
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 6: // 2 points, 2 possible paths
if(parent_result_node_ptr->node_y>=yCoord-1)
prefer_lower_s2 = 1;
else
{
if(!can_move_to(xCoord,yCoord-2) || !can_move_to(xCoord+1,yCoord-2) ||
!can_move_to(xCoord+2,yCoord-2))
prefer_lower_s2 = 1;
else
prefer_upper_s2 = 1;
}
max_size_result_node_ptr->node_x = xCoord+1;
max_size_result_node_ptr->node_y = yCoord-1-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord-1-prefer_upper_s2;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
case 7:
max_size_result_node_ptr->node_x = xCoord;
max_size_result_node_ptr->node_y = yCoord-1;
add_result_node(&max_size_result_node_ptr, &parent_result_node_ptr, count);
break;
default: err_here();
break;
}
break;
default: err_here();
break;
}
}
//------ End of function SeekPathS2::get_real_result_node ---------//
//-------- Begin of function SeekPathS2::return_best_node -------//
//
// return : the best node.
// NULL if no more node on the open node list. There is no
// possible path between the starting and destination points.
//
NodeS2* SeekPathS2::return_best_node()
{
NodeS2 *tempNode;
if( !open_node_list )
return NULL;
//------------------------------------------------------------------//
// Pick Node with lowest f, in this case it's the first node in list
// Because we sort the open_node_list list wrt lowest f. Call it BESTNode.
//------------------------------------------------------------------//
tempNode=open_node_list; // point to first node on open_node_list
open_node_list=tempNode->next_node; // Make open_node_list point to nextnode or NULL.
//------------------------------------------------------------------//
// Next take BESTNode (or temp in this case) and put it on closed_node_list
//------------------------------------------------------------------//
tempNode->next_node=closed_node_list;
closed_node_list=tempNode;
return tempNode;
}
//-------- End of function SeekPathS2::return_best_node ---------//
//----- Begin of function SeekPathS2::return_closest_node -------//
//
// Return the node that is closest to the destination.
//
NodeS2* SeekPathS2::return_closest_node()
{
NodeS2* nodePtr;
NodeS2* shortestNode=NULL;
int nodeDistance, shortestDistance=0x7FFF;
int disX, disY;
//------------ search open_node_list ----------//
nodePtr = open_node_list;
int yieldCount = 0;
while(nodePtr)
{
//--- the distance between this node and the destination node ----//
nodeDistance = (disX=cur_dest_x_s2-nodePtr->node_x)*disX + (disY=cur_dest_y_s2-nodePtr->node_y)*disY;
//--- if the distance is shorter than the current shortest distance ---//
if( nodeDistance < shortestDistance )
{
shortestDistance = nodeDistance;
shortestNode = nodePtr;
}
nodePtr=nodePtr->next_node;
yieldCount++;
if(yieldCount%25==0)
sys_yield();
}
//------------ search closed_node_list ----------//
nodePtr = closed_node_list;
yieldCount = 0;
while(nodePtr)
{
//--- the distance between this node and the destination node ----//
nodeDistance = (disX=cur_dest_x_s2-nodePtr->node_x)*disX + (disY=cur_dest_y_s2-nodePtr->node_y)*disY;
//--- if the distance is shorter than the current shortest distance ---//
if( nodeDistance < shortestDistance )
{
shortestDistance = nodeDistance;
shortestNode = nodePtr;
}
nodePtr=nodePtr->next_node;
yieldCount++;
if(yieldCount%25==0)
sys_yield();
}
//------------------------------------------------------//
// there may be some nodes with the same shortest Distance
// from the destination node. However, one should be closer
// to the starting node. The following is used to find
// out the closer node.
//------------------------------------------------------//
nodePtr = shortestNode->parent_node;
yieldCount = 0;
while(nodePtr)
{
//--- the distance between the parent node and the destination node ----//
nodeDistance = (disX=cur_dest_x_s2-nodePtr->node_x)*disX + (disY=cur_dest_y_s2-nodePtr->node_y)*disY;
//--- if the distance is shorter than the current shortest distance ---//
if( nodeDistance <= shortestDistance )
{
shortestDistance = nodeDistance;
shortestNode = nodePtr;
}
else
break;
nodePtr=nodePtr->parent_node;
yieldCount++;
if(yieldCount%25==0)
sys_yield();
}
return shortestNode;
}
//----- End of function SeekPathS2::return_closest_node -------//
//----- Begin of function SeekPathS2::insert_open_node -------//
void SeekPathS2::insert_open_node(NodeS2 *succNode)
{
if (open_node_list == NULL)
{
open_node_list=succNode;
return;
}
//---- insert into open_node_list successor wrt f ----//
register int f=succNode->node_f;
if( open_node_list && open_node_list->node_f < f )
{
NodeS2 *tempNode1, *tempNode2;
tempNode1=open_node_list;
tempNode2=tempNode1->next_node;
int yieldCount = 0;
while( tempNode2 && tempNode2->node_f < f )
{
tempNode1=tempNode2;
tempNode2=tempNode2->next_node;
yieldCount++;
if(yieldCount%200==0)
sys_yield();
}
err_when(succNode!=NULL && tempNode2!=NULL && succNode->node_x==tempNode2->node_x &&
succNode->node_y==tempNode2->node_y); // avoid pointer pointing back to itself
succNode->next_node = tempNode2;
tempNode1->next_node = succNode;
}
else
{
succNode->next_node = open_node_list;
open_node_list = succNode;
}
}
//----- End of function SeekPathS2::insert_open_node -------//
//-------- Begin of function SeekPath::smooth_the_path ---------//
ResultNode* SeekPathS2::smooth_the_path(ResultNode* nodeArray, int& nodeCount)
{
//--------------------------------------------------//
// to remove duplicate or useless node
//--------------------------------------------------//
int i, j, curNodeCount = 1;
parent_result_node_ptr = nodeArray;
max_size_result_node_ptr = nodeArray+1;
for(i=0; inode_x!=max_size_result_node_ptr->node_x ||
parent_result_node_ptr->node_y!=max_size_result_node_ptr->node_y)
{
parent_result_node_ptr++;
parent_result_node_ptr->node_x = max_size_result_node_ptr->node_x;
parent_result_node_ptr->node_y = max_size_result_node_ptr->node_y;
curNodeCount++;
}
max_size_result_node_ptr++;
if(i%50==0)
sys_yield();
}
nodeCount = curNodeCount;
//return nodeArray;
//---------- declare variables ---------------//
int checkedNodeCount;
short vectorX, vectorY, newVectorX, newVectorY, newVectorX2, newVectorY2;
short changed, caseNum, processed;
ResultNode *curUsefulNodePtr = nodeArray+1;
ResultNode *ptr1;
ResultNode *ptr2;
ResultNode *ptr3;
ResultNode *ptr4;
//--------------------------------------------------//
// smooth the path
//--------------------------------------------------//
parent_result_node_ptr = nodeArray;
max_size_result_node_ptr = nodeArray+1;
changed = 1;
checkedNodeCount = 1;
curNodeCount = nodeCount;
ptr1 = parent_result_node_ptr;
ptr2 = max_size_result_node_ptr;
ptr3 = max_size_result_node_ptr+1;
int yieldCount = 1;
while(changed && curNodeCount>=3)
{
yieldCount++;
if(yieldCount%20==0)
sys_yield();
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
changed = 0;
for(j=1; jnode_x - ptr2->node_x;
newVectorY= ptr3->node_y - ptr2->node_y;
//----------------------------------------------------------//
// reverse direction
//----------------------------------------------------------//
if(vectorX==-newVectorX && vectorY==-newVectorY)
{
if(j+2node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
processed = 1;
j++;
continue;
}
else //-------- already the end of the array ----------//
{
ptr3++;
changed++;
break; // break the for loop
}
}
//----------------------------------------------------------//
// turning 45 degree angle
//----------------------------------------------------------//
if(abs(vectorX+newVectorX)<=1 && abs(vectorY+newVectorY)<=1 && // if so, turning 45 or 90 degree
vectorX*newVectorX+vectorY*newVectorY!=0) // reject turning 90 degree
{
ptr2=ptr3;
ptr3++;
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
processed = 1;
continue;
}
//----------------------------------------------------------//
// turning at 90 degree clockwise / anti-clockwise
//----------------------------------------------------------//
if((vectorX==0 && vectorY!=0 && newVectorX!=0 && newVectorY==0) || // + case
(vectorX!=0 && vectorY==0 && newVectorX==0 && newVectorY!=0))
{
ptr2=ptr3;
ptr3++;
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
processed = 1;
continue;
}
if((vectorX!=0 && vectorY!=0 && newVectorX!=0 && newVectorY!=0) && // x case
((vectorX==newVectorX && vectorY==-newVectorY) || (vectorX==-newVectorX && vectorY==newVectorY)))
{
ptr2->node_x = (ptr1->node_x+ptr3->node_x)/2;
ptr2->node_y = (ptr1->node_y+ptr3->node_y)/2;
curUsefulNodePtr->node_x = ptr2->node_x;
curUsefulNodePtr->node_y = ptr2->node_y;
curUsefulNodePtr++;
checkedNodeCount++;
ptr1 = ptr2;
ptr2 = ptr3;
ptr3++;
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
processed = 1;
continue;
}
//----------------------------------------------------------//
// check for the 4-point case
//----------------------------------------------------------//
if(jnode_x - ptr3->node_x;
newVectorY2 = ptr4->node_y - ptr3->node_y;
caseNum = 0;
if(!caseNum && vectorX==-1 && vectorY==0 && newVectorX==-1 && newVectorX2==0)
{
if(newVectorY==1 && newVectorY2==1 && can_move_to(ptr1->node_x, ptr4->node_y))
caseNum = 1;
if(!caseNum && newVectorY==-1 && newVectorY2==-1 && can_move_to(ptr1->node_x, ptr4->node_y-1))
caseNum = 5;
}
if(!caseNum && vectorX==1 && vectorY==0 && newVectorX==1 && newVectorX2==0)
{
if(newVectorY==1 && newVectorY2==1 && can_move_to(ptr1->node_x+1, ptr4->node_y))
caseNum = 3;
if(!caseNum && newVectorY==-1 && newVectorY2==-1 && can_move_to(ptr1->node_x+1, ptr4->node_y-1))
caseNum = 7;
}
if(!caseNum && vectorX==0 && vectorY==-1 && newVectorY==-1 && newVectorY2==0)
{
if(newVectorX==1 && newVectorX2==1 && can_move_to(ptr4->node_x, ptr1->node_y))
caseNum = 2;
if(!caseNum && newVectorX==-1 && newVectorX2==-1 && can_move_to(ptr4->node_x+1, ptr1->node_y))
caseNum = 4;
}
if(!caseNum && vectorX==0 && vectorY==1 && newVectorY==1 && newVectorY2==0)
{
if(newVectorX==1 && newVectorX2==1 && can_move_to(ptr4->node_x, ptr1->node_y+1))
caseNum = 6;
if(!caseNum && newVectorX==-1 && newVectorX2==-1 && can_move_to(ptr4->node_x+1, ptr1->node_y+1))
caseNum = 8;
}
if(caseNum)
{
switch(caseNum)
{
case 1:
if(can_move_to(ptr1->node_x, ptr4->node_y))
{
//ptr2->node_x = ptr2->node_x;
ptr2->node_y++; //ptr2->node_y = ptr3->node_y;
processed = 1;
}
break;
case 2:
if(can_move_to(ptr4->node_x, ptr1->node_y))
{
ptr2->node_x++; //ptr2->node_x = ptr3->node_x;
//ptr2->node_y = ptr2->node_y;
processed = 1;
}
break;
case 3:
if(can_move_to(ptr2->node_x, ptr4->node_y))
{
//ptr2->node_x = ptr2->node_x;
ptr2->node_y++; //ptr2->node_y = ptr3->node_y;
processed = 1;
}
break;
case 4:
if(can_move_to(ptr3->node_x, ptr1->node_y))
{
ptr2->node_x--; //ptr2->node_x = ptr3->node_x;
//ptr2->node_y = ptr2->node_y;
processed = 1;
}
break;
case 5:
if(can_move_to(ptr1->node_x, ptr3->node_y))
{
//ptr2->node_x = ptr2->node_x;
ptr2->node_y--; //ptr2->node_y = ptr3->node_y;
processed = 1;
}
break;
case 6:
if(can_move_to(ptr4->node_x, ptr2->node_y))
{
ptr2->node_x++; //ptr2->node_x = ptr3->node_x;
//ptr2->node_y = ptr2->node_y;
processed = 1;
}
break;
case 7:
if(can_move_to(ptr2->node_x, ptr3->node_y))
{
//ptr2->node_x = ptr2->node_x;
ptr2->node_y--; //ptr2->node_y = ptr3->node_y;
processed = 1;
}
break;
case 8:
if(can_move_to(ptr3->node_x, ptr2->node_y))
{
ptr2->node_x--; //ptr2->node_x = ptr3->node_x;
//ptr2->node_y = ptr2->node_y;
processed = 1;
}
break;
default:
err_here();
break;
}
if(processed)
{
ptr3 = ptr4;
curUsefulNodePtr->node_x = ptr2->node_x;
curUsefulNodePtr->node_y = ptr2->node_y;
curUsefulNodePtr++;
checkedNodeCount++;
ptr1 = ptr2;
ptr2 = ptr3;
ptr3++;
j++;
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
continue;
}
}
}
//------ none of the above case ---------//
if(!processed)
{
curUsefulNodePtr->node_x = ptr2->node_x;
curUsefulNodePtr->node_y = ptr2->node_y;
curUsefulNodePtr++;
checkedNodeCount++;
}
else
changed = 1;
ptr1 = ptr2;
ptr2 = ptr3;
ptr3++;
vectorX = ptr2->node_x - ptr1->node_x;
vectorY = ptr2->node_y - ptr1->node_y;
}
//---- end checking and then reset parameters----//
curUsefulNodePtr->node_x = ptr2->node_x;
curUsefulNodePtr->node_y = ptr2->node_y;
curUsefulNodePtr++;
checkedNodeCount++;
curNodeCount = checkedNodeCount;
checkedNodeCount = 1;
ptr1 = parent_result_node_ptr;
ptr2 = ptr1+1;
ptr3 = ptr2+1;
}
nodeCount = curNodeCount;
return nodeArray;
}
//------- End of function SeekPathS2::smooth_the_path -------//
//-------- Begin of function NodeS2::generate_successors ---------//
// Note: In fact, the cost of the starting node should be 0 or 1
// and the parentEnterDirection is 0. Now the cost in this
// case is set to 2. The difference can be ignored as it will
// not affect the search after generating the second level
// children.
// The advantage to ignore this case is that less comparsion
// effort in checking parentEnterDirection.
//
short NodeS2::generate_successors(short parentEnterDirection)
{
int hasLeft = node_x > cur_border_x1_s2;
int hasRight = node_x < cur_border_x2_s2;
int hasUp = node_y > cur_border_y1_s2;
int hasDown = node_y < cur_border_y2_s2;
int upperLeftX,upperLeftY;
short cost;
upperLeftX = node_x<<1;
upperLeftY = node_y<<1;
err_when(upperLeftX != node_x+node_x || upperLeftY != node_y+node_y);
//-------------------------------------------
// enter_direction = (exit_direction+3)%8+1
//-------------------------------------------
if( hasLeft )
{
//--------- Left, exit_direction=1 --------//
if(can_move_to(upperLeftX-1, upperLeftY) && node_type&0x1 &&
can_move_to(upperLeftX-1, upperLeftY+1) && node_type&0x4 )
{
if(parentEnterDirection==2 || parentEnterDirection==3 || parentEnterDirection==7 || parentEnterDirection==8)
cost = 1;
else
{
if((parentEnterDirection==4 && (node_type&0x2 || can_move_to(upperLeftX,upperLeftY+2))) ||
parentEnterDirection==5 ||
(parentEnterDirection==6 && (node_type&0x8 || can_move_to(upperLeftX,upperLeftY-1))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[0]) // direction 1
{
if(source_locate_type==1 || source_locate_type==3)
cost = 1;
else
cost = 2;
}
else
cost = 0;
}
}
if(cost)
{
err_when(parentEnterDirection==1);
if(generate_succ(node_x-1,node_y,5,cost))
return 1;
}
}
if( hasUp )
{
//------- Upper-Left, exit_direction=8 ---------//
if(can_move_to(upperLeftX-1, upperLeftY-1) && can_move_to(upperLeftX, upperLeftY-1) &&
can_move_to(upperLeftX-1, upperLeftY) && node_type&0x1)
{
if(parentEnterDirection==1 || parentEnterDirection==2 || parentEnterDirection==6 || parentEnterDirection==7)
cost = 1;
else
{
if((parentEnterDirection==3 && (node_type&0x2 || can_move_to(upperLeftX-1, upperLeftY+1))) ||
(parentEnterDirection==4 && node_type==15) ||
(parentEnterDirection==5 && (node_type&0x4 || can_move_to(upperLeftX+1, upperLeftY-1))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[7]) // direction 8
{
if(source_locate_type==1)
cost = 1;
else
cost = 2;
}
else
cost = 0;
}
}
if(cost)
{
err_when(parentEnterDirection==8);
if(generate_succ(node_x-1,node_y-1,4,cost))
return 1;
}
}
}
if( hasDown )
{
//--------- Lower-Left, exit_direction=2 ----------//
if(can_move_to(upperLeftX-1,upperLeftY+1) && node_type&0x4 &&
can_move_to(upperLeftX-1,upperLeftY+2) && can_move_to(upperLeftX,upperLeftY+2))
{
if(parentEnterDirection==1 || parentEnterDirection==3 || parentEnterDirection==4 || parentEnterDirection==8)
cost = 1;
else
{
if((parentEnterDirection==5 && (node_type&0x1 || can_move_to(upperLeftX+1,upperLeftY+2))) ||
(parentEnterDirection==6 && node_type==15) ||
(parentEnterDirection==7 && (node_type&0x8 || can_move_to(upperLeftX-1,upperLeftY))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[1]) // direction 2
{
if(source_locate_type==1||source_locate_type==3)
cost = 1;
else
cost = 2;
}
else
cost = 0;
}
}
if(cost || (parentEnterDirection==0 && source_locate_type==3 && !source_blocked_exit_direction[1]))
{
err_when(parentEnterDirection==2);
if(generate_succ(node_x-1,node_y+1,6,cost))
return 1;
}
}
}
}
if( hasRight )
{
//----------- Right, exit_direction=5 -----------//
if(node_type&0x2 && can_move_to(upperLeftX+2,upperLeftY) &&
node_type&0x8 && can_move_to(upperLeftX+2,upperLeftY+1))
{
if(parentEnterDirection==3 || parentEnterDirection==4 || parentEnterDirection==6 || parentEnterDirection==7)
cost = 1;
else
{
if(parentEnterDirection==1 ||
(parentEnterDirection==2 && (node_type&0x1 || can_move_to(upperLeftX+1,upperLeftY+2))) ||
(parentEnterDirection==8 && (node_type&0x4 || can_move_to(upperLeftX+1,upperLeftY-1))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[4] && //direction 5
(source_locate_type==1||source_locate_type==3))
cost = 1;
else
cost = 0;
}
}
if(cost||(parentEnterDirection==0&&!source_blocked_exit_direction[4]&&(source_locate_type==2||source_locate_type==4)))
{
err_when(parentEnterDirection==5);
if(generate_succ(node_x+1,node_y,1,cost))
return 1;
}
}
if( hasUp )
{
//-------- Upper-Right, exit_direction=6 ---------//
if(can_move_to(upperLeftX+1,upperLeftY-1) && can_move_to(upperLeftX+2,upperLeftY-1) &&
node_type&0x2 && can_move_to(upperLeftX+2,upperLeftY))
{
if(parentEnterDirection==4 || parentEnterDirection==5 || parentEnterDirection==7 || parentEnterDirection==8)
cost = 1;
else
{
if((parentEnterDirection==1 && (node_type&0x8 || can_move_to(upperLeftX,upperLeftY-1))) ||
(parentEnterDirection==2 && node_type==15) ||
(parentEnterDirection==3 && (node_type&0x1 || can_move_to(upperLeftX+2,upperLeftY+1))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[5]) // direction 6
{
if(source_locate_type==1||source_locate_type==2)
cost = 1;
else
cost = 2;
}
else
cost = 0;
}
}
if(cost)
{
err_when(parentEnterDirection==6);
if(generate_succ(node_x+1,node_y-1,2,cost))
return 1;
}
}
}
if( hasDown )
{
//--------- Lower-Right, exit_direction=4 ---------//
if(node_type&0x8 && can_move_to(upperLeftX+2,upperLeftY+1) &&
can_move_to(upperLeftX+1,upperLeftY+2) && can_move_to(upperLeftX+2,upperLeftY+2))
{
if(parentEnterDirection==2 || parentEnterDirection==3 || parentEnterDirection==5 || parentEnterDirection==6)
cost = 1;
else
{
if((parentEnterDirection==1 && (node_type&0x2 || can_move_to(upperLeftX,upperLeftY+2))) ||
(parentEnterDirection==8 && node_type==15) ||
(parentEnterDirection==7 && (node_type&0x4 || can_move_to(upperLeftX+2,upperLeftY))))
cost = 2;
else
{
if(parentEnterDirection==0&&source_locate_type!=4&&!source_blocked_exit_direction[3]) // direction 4
cost = 1;
else
cost = 0;
}
}
if(cost||(parentEnterDirection==0&&source_locate_type==4&&!source_blocked_exit_direction[3]))
{
err_when(parentEnterDirection==4);
if(generate_succ(node_x+1,node_y+1,8,cost))
return 1;
}
}
}
}
if( hasUp )
{
//---------- Upper, exit_direction=7 -----------//
if(can_move_to(upperLeftX,upperLeftY-1) && can_move_to(upperLeftX+1,upperLeftY-1) &&
node_type&0x1 && node_type&0x2)
{
if(parentEnterDirection==1 || parentEnterDirection==5 || parentEnterDirection==6 || parentEnterDirection==8)
cost = 1;
else
{
if((parentEnterDirection==2 && (node_type&0x8 || can_move_to(upperLeftX-1,upperLeftY))) ||
parentEnterDirection==3 ||
(parentEnterDirection==4 && (node_type&0x4 || can_move_to(upperLeftX+2,upperLeftY))))
cost = 2;
else
{
if(parentEnterDirection==0 && !source_blocked_exit_direction[6]) // direction 7
{
if(source_locate_type==1||source_locate_type==2)
cost = 1;
else
cost = 2;
}
else
cost = 0;
}
}
if(cost)
{
err_when(parentEnterDirection==7);
if(generate_succ(node_x,node_y-1,3,cost))
return 1;
}
}
}
if( hasDown )
{
//---------- Lower, exit_direction=3 -----------//
if(node_type&0x4 && node_type&0x8 &&
can_move_to(upperLeftX,upperLeftY+2) && can_move_to(upperLeftX+1,upperLeftY+2))
{
if(parentEnterDirection==1 || parentEnterDirection==2 || parentEnterDirection==4 || parentEnterDirection==5)
cost = 1;
else
{
if((parentEnterDirection==6 && (node_type&0x1 || can_move_to(upperLeftX+2,upperLeftY+1))) ||
parentEnterDirection==7 ||
(parentEnterDirection==8 && (node_type&0x2 || can_move_to(upperLeftX-1,upperLeftY+1))))
cost = 2;
else
{
if(parentEnterDirection==0&&(source_locate_type==1||source_locate_type==2)&&!source_blocked_exit_direction[2]) // direction 3
cost = 1;
else
cost = 0;
}
}
if(cost||(parentEnterDirection==0&&(source_locate_type==3||source_locate_type==4)&&!source_blocked_exit_direction[2]))
{
err_when(parentEnterDirection==3);
if(generate_succ(node_x,node_y+1,7,cost))
return 1;
}
}
}
return 0;
}
//------- End of function NodeS2::generate_successors -------//
//-------- Begin of function NodeS2::generate_succ ---------//
short NodeS2::generate_succ(short x, short y, short enter_direct,short cost)
{
int upperLeftX, upperLeftY;
upperLeftX = x<<1;
upperLeftY = y<<1;
//----- if it points back to this node's parent ----//
if( parent_node )
{
if( parent_node->node_x==x && parent_node->node_y==y )
return 0;
}
//----- if there is an existing node at the given position ----//
short c, g = node_g+cost; // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor
short nodeRecno;
//if( (nodeRecno=cur_node_matrix_s2[y*(MAX_WORLD_X_LOC/2+1)+x]) > 0 )
if( (nodeRecno=cur_node_matrix_s2[y*(MAX_WORLD_X_LOC/2+1)+x]) > 0 &&
nodeRecnonode_g)
{
//-------------check whether the oldNode can process propagate down -----------//
char canPropagateDown=1;
if(oldNode->node_type!=15 && enter_direct%2==0)
{
NodeS2* oldChildNode;
short xShift1 = x_shift_array[enter_direct-1];
short yShift1 = y_shift_array[enter_direct-1];
short xShift2, yShift2, xShift3, yShift3;
if(enter_direct>1)
{
xShift2 = x_shift_array[enter_direct-2];
yShift2 = y_shift_array[enter_direct-2];
}
else
{
xShift2 = x_shift_array[7];
yShift2 = y_shift_array[7];
}
if(enter_direct<8)
{
xShift3 = x_shift_array[enter_direct];
yShift3 = y_shift_array[enter_direct];
}
else
{
xShift3 = x_shift_array[0];
yShift3 = y_shift_array[0];
}
for(c=0; cchild_node[c]; c++) // for each child of oldNode
{
oldChildNode = oldNode->child_node[c];
if(oldNode->parent_node != oldChildNode)
{
switch(enter_direct) // for entering at corner
{
case 2:
if(oldChildNode->enter_direction==enter_direct &&
oldChildNode->node_x-oldNode->node_x==xShift1 &&
oldChildNode->node_y-oldNode->node_y==yShift1 &&
(!can_move_to(upperLeftX, upperLeftY) ||
!can_move_to(upperLeftX+1, upperLeftY+1)))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct-1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX,upperLeftY) &&
!can_move_to(upperLeftX+1,upperLeftY+2))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct+1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX+1,upperLeftY+1) &&
!can_move_to(upperLeftX-1,upperLeftY))
canPropagateDown = 0;
break;
case 4:
if(oldChildNode->enter_direction==enter_direct &&
oldChildNode->node_x-oldNode->node_x==xShift1 &&
oldChildNode->node_y-oldNode->node_y==yShift1 &&
(!can_move_to(upperLeftX+1, upperLeftY) ||
!can_move_to(upperLeftX, upperLeftY+1)))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct-1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX,upperLeftY+1)&&
!can_move_to(upperLeftX+2,upperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct+1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX,upperLeftY+2) &&
!can_move_to(upperLeftX+1,upperLeftY))
canPropagateDown = 0;
break;
case 6:
if(oldChildNode->enter_direction==enter_direct &&
oldChildNode->node_x-oldNode->node_x==xShift1 &&
oldChildNode->node_y-oldNode->node_y==yShift1 &&
(!can_move_to(upperLeftX, upperLeftY) ||
!can_move_to(upperLeftX+1, upperLeftY+1)))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct-1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX,upperLeftY-1)&&
!can_move_to(upperLeftX+1,upperLeftY+1))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct+1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX,upperLeftY) &&
!can_move_to(upperLeftX+2,upperLeftY+1))
canPropagateDown = 0;
break;
case 8:
if(oldChildNode->enter_direction==enter_direct &&
oldChildNode->node_x-oldNode->node_x==xShift1 &&
oldChildNode->node_y-oldNode->node_y==yShift1 &&
(!can_move_to(upperLeftX+1, upperLeftY) ||
!can_move_to(upperLeftX, upperLeftY+1)))
canPropagateDown = 0;
if(oldChildNode->enter_direction==enter_direct-1 &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX-1,upperLeftY+1)&&
!can_move_to(upperLeftX+1,upperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==(enter_direct%8+1) &&
oldChildNode->node_x-oldNode->node_x==xShift2 &&
oldChildNode->node_x-oldNode->node_y==yShift2 &&
!can_move_to(upperLeftX+1,upperLeftY-1) &&
!can_move_to(upperLeftX,upperLeftY+1))
canPropagateDown = 0;
break;
default: err_here();
break;
}
}
}
}
if(canPropagateDown)
{
oldNode->parent_node = this;
oldNode->node_g = g;
oldNode->node_f = g+oldNode->node_h;
oldNode->enter_direction = (char)enter_direct;
//-------- if it's a closed node ---------//
if( oldNode->child_node[0] )
{
//-------------------------------------------------//
// Since we changed the g value of oldNode, we need
// to propagate this new value downwards, i.e.
// do a Depth-First traversal of the tree!
//-------------------------------------------------//
oldNode->propagate_down();
sys_yield();
}
}
}
}
else //------------ add a new node -----------//
{
NodeS2* succNode = cur_node_array_s2 + cur_seek_path_s2->node_count++;
memset(succNode, 0, sizeof(NodeS2));
succNode->parent_node = this;
succNode->node_g = g;
succNode->node_h = (x-cur_dest_x_s2)*(x-cur_dest_x_s2)+(y-cur_dest_y_s2)*(y-cur_dest_y_s2); // should do sqrt(), but since we don't really
succNode->node_f = g+succNode->node_h; // care about the distance but just which branch looks
succNode->node_x = x; // better this should suffice. Anyayz it's faster.
succNode->node_y = y;
succNode->enter_direction = (char)enter_direct;
succNode->node_type =can_move_to(upperLeftX,upperLeftY)+(can_move_to(upperLeftX+1,upperLeftY)<<1)+
(can_move_to(upperLeftX,upperLeftY+1)<<2)+(can_move_to(upperLeftX+1,upperLeftY+1)<<3);
/*if(search_mode_s2==4 && nodeRecno>max_node_num_s2)
{
reuse_connect_node_exit_direction = nodeRecno - max_node_num_s2;
reuse_result_node_ptr_s2 = succNode;
return 1;
}*/
if(search_mode_s2==SEARCH_MODE_REUSE && nodeRecno>max_node_num_s2) // path-reuse node found, but checking of can_walk(final_dest_?) is requested
{
int destIndex = nodeRecno - max_node_num_s2;
int addNode = 1;
switch(destIndex)
{
case 1:
final_dest_x_s2 = x<<1;
final_dest_y_s2 = y<<1;
break;
case 2:
if(enter_direct==2 && (!succNode->node_type&0x1 || !can_move_to((x<<1)+1,(y<<1)+2) ) )
addNode = 0;
if(addNode && enter_direct==8 && (!succNode->node_type&0x4 || !can_move_to((x<<1)+1,(y<<1)-1) ) )
addNode = 0;
if(addNode) // not the two blocked cases
{
final_dest_x_s2 = (x<<1) + 1;
final_dest_y_s2 = y<<1;
}
break;
case 3:
if(enter_direct==6 && (!succNode->node_type&0x1 || !can_move_to((x<<1)+2,(y<<1)+1) ) )
addNode = 0;
if(addNode && enter_direct==8 && (!succNode->node_type&0x2 || !can_move_to((x<<1)-1,(y<<1)+1) ) )
addNode = 0;
if(addNode) // not the two blocked cases
{
final_dest_x_s2 = x<<1;
final_dest_y_s2 = (y<<1)+1;
}
break;
case 4:
if(enter_direct==1 && (!succNode->node_type&0x2 || !can_move_to(x<<1,(y<<1)+2) ) )
addNode = 0;
if(addNode && enter_direct==7 && (!succNode->node_type&0x4 || !can_move_to((x<<1)+2,y<<1) ) )
addNode = 0;
if(addNode && enter_direct==8 && (!succNode->node_type&0x2 || !succNode->node_type&0x4) )
addNode = 0;
if(addNode) // not the two blocked cases
{
final_dest_x_s2 = (x<<1)+1;
final_dest_y_s2 = (y<<1)+1;
}
break;
default: err_here();
break;
}
if(addNode)
{
reuse_result_node_ptr_s2 = succNode;
err_when(!can_move_to_s2(final_dest_x_s2, final_dest_y_s2));
return 1; // PATH_REUSE_FOUND
}
else // add nothing
{
memset(succNode, 0, sizeof(NodeS2));
cur_seek_path_s2->node_count--;
return 0;
}
}
cur_node_matrix_s2[y*(MAX_WORLD_X_LOC/2+1)+x] = cur_seek_path_s2->node_count;
cur_seek_path_s2->insert_open_node(succNode); // insert succNode on open_node_list list wrt f
for(c=0 ; cparent_node==this)
break;
cost = 2; // in fact, may be 1 or 2
if (g+cost <= childNode->node_g) // first checking
{
char canMove = 0;
int childUpperLeftX = childNode->node_x<<1;
int childUpperLeftY = childNode->node_y<<1;
xShift = childNode->node_x-node_x;
yShift = childNode->node_y-node_y;
err_when(abs(xShift)>1 || abs(yShift)>1);
//---------- calulate the new enter direction ------------//
switch(yShift)
{
case -1:
childEnterDirection = char(3-xShift);
break;
case 0:
childEnterDirection = char(3-(xShift<<1));
break;
case 1:
childEnterDirection = char(7+xShift);
break;
}
//---------- decide can move or not and use special case or not --------//
switch(childEnterDirection)
{
case 1:
err_when(node_x!=childNode->node_x-1 || node_y!=childNode->node_y);
if(can_move_to(childUpperLeftX-1,childUpperLeftY) && childNode->node_type&0x1 &&
can_move_to(childUpperLeftX-1,childUpperLeftY+1) && childNode->node_type&0x4) //if the entering location is walkable
{
switch(enter_direction)
{
case 5: canMove = 0; //reverse direction
break;
case 1:case 3:case 4:case 6:case 7: // obviously
canMove = 1;
break;
case 2: if(node_type&0x1 || can_move_to(childUpperLeftX-1, childUpperLeftY+2))
canMove = 1;
break;
case 8: if(node_type&0x4 || can_move_to(childUpperLeftX-1, childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 2:
err_when(node_x!=childNode->node_x-1 || node_y!=childNode->node_y+1);
if(can_move_to(childUpperLeftX-1,childUpperLeftY+1) && childNode->node_type&0x4 &&
can_move_to(childUpperLeftX-1,childUpperLeftY+2) && can_move_to(childUpperLeftX,childUpperLeftY+2))
{
switch(enter_direction)
{
case 6: canMove = 0; //reverse direction
break;
case 4:case 5:case 7:case 8:
canMove = 1;
break;
case 1: if(node_type&0x8 || can_move_to(childUpperLeftX-2, childUpperLeftY+1))
canMove = 1;
break;
case 2: if(node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 3: if(node_type&0x1 || can_move_to(childUpperLeftX, childUpperLeftY+3))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 3:
err_when(node_x!=childNode->node_x || node_y!=childNode->node_y+1);
if(childNode->node_type&0x4 && childNode->node_type&0x8 &&
can_move_to(childUpperLeftX,childUpperLeftY+2) && can_move_to(childUpperLeftX+1,childUpperLeftY+2))
{
switch(enter_direction)
{
case 7: canMove = 0; //reverse direction
break;
case 1:case 3:case 5:case 6:case 8:
canMove = 1;
break;
case 2: if(node_type&0x8 || can_move_to(childUpperLeftX-1, childUpperLeftY+2))
canMove = 1;
break;
case 4: if(node_type&0x4 || can_move_to(childUpperLeftX+2, childUpperLeftY+2))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 4:
err_when(node_x!=childNode->node_x+1 || node_y!=childNode->node_y+1);
if(childNode->node_type&0x8 && can_move_to(childUpperLeftX+2,childUpperLeftY+1) &&
can_move_to(childUpperLeftX+1,childUpperLeftY+2) && can_move_to(childUpperLeftX+2,childUpperLeftY+2))
{
switch(enter_direction)
{
case 8: canMove = 0; //reverse direction
break;
case 1:case 2:case 6:case 7:
canMove = 1;
break;
case 3: if(node_type&0x2 || can_move_to(childUpperLeftX+1, childUpperLeftY+3))
canMove = 1;
break;
case 4: if(node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 5: if(node_type&0x4 || can_move_to(childUpperLeftX+3, childUpperLeftY+1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 5:
err_when(node_x!=childNode->node_x+1 || node_y!=childNode->node_y);
if(childNode->node_type&0x2 && can_move_to(childUpperLeftX+2,childUpperLeftY) &&
childNode->node_type&0x8 && can_move_to(childUpperLeftX+2,childUpperLeftY+1))
{
switch(enter_direction)
{
case 1: canMove = 0; //reverse direction
break;
case 2:case 3:case 5:case 7:case 8:
canMove = 1;
break;
case 4: if(node_type&0x2 || can_move_to(childUpperLeftX+2, childUpperLeftY+2))
canMove = 1;
break;
case 6: if(node_type&0x8 || can_move_to(childUpperLeftX+2, childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 6:
err_when(node_x!=childNode->node_x+1 || node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX+1,childUpperLeftY-1) && can_move_to(childUpperLeftX+2,childUpperLeftY-1) &&
childNode->node_type&0x2 && can_move_to(childUpperLeftX+2,childUpperLeftY))
{
switch(enter_direction)
{
case 2: canMove = 0; //reverse direction
break;
case 1:case 3:case 4:case 8:
canMove = 1;
break;
case 5: if(node_type&0x1 || can_move_to(childUpperLeftX+3, childUpperLeftY))
canMove = 1;
break;
case 6: if(node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 7: if(node_type&0x8 || can_move_to(childUpperLeftX+1, childUpperLeftY-2))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 7:
err_when(node_x!=childNode->node_x || node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX,childUpperLeftY-1) && can_move_to(childUpperLeftX+1,childUpperLeftY-1) &&
childNode->node_type&0x1 && childNode->node_type&0x2)
{
switch(enter_direction)
{
case 3: canMove = 0; //reverse direction
break;
case 1:case 2:case 4:case 5:case 7:
canMove = 1;
break;
case 6: if(node_type&0x1 || can_move_to(childUpperLeftX+2, childUpperLeftY-1))
canMove = 1;
break;
case 8: if(node_type&0x2 || can_move_to(childUpperLeftX-1, childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 8:
err_when(node_x!=childNode->node_x-1 || node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX-1,childUpperLeftY-1) && can_move_to(childUpperLeftX,childUpperLeftY-1) &&
can_move_to(childUpperLeftX-1,childUpperLeftY) && childNode->node_type&0x1)//can_move_to(childUpperLeftX,childUpperLeftY))
{
switch(enter_direction)
{
case 4: canMove = 0; //reverse direction
break;
case 2:case 3:case 5:case 6:
canMove = 1;
break;
case 1: if(node_type&0x2 || can_move_to(childUpperLeftX-2, childUpperLeftY))
canMove = 1;
break;
case 7: if(node_type&0x4 || can_move_to(childUpperLeftX, childUpperLeftY-2))
canMove = 1;
break;
case 8: if(node_type==15)
canMove = 1;
else
canMove = 0;
break;
default: err_here();
break;
}
}
break;
default: err_here();
break;
}
if(canMove) // can move in the child node
{
exitDirection = (childEnterDirection+3)%8+1;
if(enter_direction > exitDirection)
{
if((enter_direction==8 && (exitDirection==1 || exitDirection==2)) ||
(enter_direction==7 && exitDirection==1))
testResult = exitDirection + 8 - enter_direction;
else
testResult = enter_direction - exitDirection;
}
else
{
if((exitDirection==8 && (enter_direction==1 || enter_direction==2)) ||
(exitDirection==7 && enter_direction==1))
testResult = enter_direction + 8 - exitDirection;
else
testResult = exitDirection - enter_direction;
}
if((exitDirection%2 && testResult<=2) || (!exitDirection%2 && testResult<=1))
cost = 1;
else
cost = 2;
err_when(cost>2 || cost<1);
if(g+cost < childNode->node_g) // second checking, mainly for cost = 2;
{
char canPropagateDown=1;
if(childNode->node_type!=15 && childEnterDirection%2==0)
{
NodeS2* oldChildNode;
short xShift1 = x_shift_array[childEnterDirection-1];
short yShift1 = y_shift_array[childEnterDirection-1];
short xShift2, yShift2, xShift3, yShift3;
if(childEnterDirection>1)
{
xShift2 = x_shift_array[childEnterDirection-2];
yShift2 = y_shift_array[childEnterDirection-2];
}
else
{
xShift2 = x_shift_array[7];
yShift2 = y_shift_array[7];
}
if(childEnterDirection<8)
{
xShift3 = x_shift_array[childEnterDirection];
yShift3 = y_shift_array[childEnterDirection];
}
else
{
xShift3 = x_shift_array[0];
yShift3 = y_shift_array[0];
}
for(c=0; cchild_node[c]; c++) // for each child of oldNode
{
oldChildNode = childNode->child_node[c];
if(childNode->parent_node != oldChildNode)
{
switch(childEnterDirection)
{
case 2:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY+2))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX+1,childUpperLeftY+1) &&
!can_move_to(childUpperLeftX-1,childUpperLeftY))
canPropagateDown = 0;
break;
case 4:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY+1)&&
!can_move_to(childUpperLeftX+2,childUpperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY+2) &&
!can_move_to(childUpperLeftX+1,childUpperLeftY))
canPropagateDown = 0;
break;
case 6:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY-1)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY+1))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY) &&
!can_move_to(childUpperLeftX+2,childUpperLeftY+1))
canPropagateDown = 0;
break;
case 8:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX-1,childUpperLeftY+1)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX+1,childUpperLeftY-1) &&
!can_move_to(childUpperLeftX,childUpperLeftY+1))
canPropagateDown = 0;
break;
default: err_here();
break;
}
}
}
}
if(canPropagateDown)
{
childNode->node_g = g+cost;
childNode->node_f = childNode->node_g+childNode->node_h;
childNode->parent_node = this;// reset parent to new path.
childNode->enter_direction = childEnterDirection;
stack_push(childNode); // Now the childNode's branch need to be checked out. Remember the new cost must be propagated down.
}
}
}
}
}
while( cur_stack_pos_s2>0 )
{
fatherNode=stack_pop();
g = fatherNode->node_g;
for(c=0;c<8;c++)
{
if ((childNode=fatherNode->child_node[c])==NULL) // we may stop the propagation 2 ways: either
break;
if(childNode->parent_node==fatherNode)
break;
cost = 2; // in fact, may be 1 or 2
if (g+cost <= childNode->node_g) // first checking
// there are no children, or that the g value of the child is equal or better than the cost we're propagating
{
char canMove = 0;
int childUpperLeftX = childNode->node_x<<1;
int childUpperLeftY = childNode->node_y<<1;
xShift = childNode->node_x-fatherNode->node_x;
yShift = childNode->node_y-fatherNode->node_y;
err_when(abs(xShift)>1 || abs(yShift)>1);
//---------- calulate the new enter direction ------------//
switch(yShift)
{
case -1:
childEnterDirection = char(3-xShift);
break;
case 0:
childEnterDirection = char(3-(xShift<<1));
break;
case 1:
childEnterDirection = char(7+xShift);
break;
}
switch(childEnterDirection)
{
case 1:
err_when(fatherNode->node_x!=childNode->node_x-1 || fatherNode->node_y!=childNode->node_y);
if(can_move_to(childUpperLeftX-1,childUpperLeftY) && childNode->node_type&0x1 && //can_move_to(childUpperLeftX,childUpperLeftY) &&
can_move_to(childUpperLeftX-1,childUpperLeftY+1) && childNode->node_type&0x4)//can_move_to(childUpperLeftX,childUpperLeftY+1))
{
switch(fatherNode->enter_direction)
{
case 5: canMove = 0; //reverse direction
break;
case 1:case 3:case 4:case 6:case 7:
canMove = 1;
break;
case 2: if(fatherNode->node_type&0x1 || can_move_to(childUpperLeftX-1, childUpperLeftY+2))
canMove = 1;
break;
case 8: if(fatherNode->node_type&0x4 || can_move_to(childUpperLeftX-1, childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 2:
err_when(fatherNode->node_x!=childNode->node_x-1 || fatherNode->node_y!=childNode->node_y+1);
if(can_move_to(childUpperLeftX-1,childUpperLeftY+1) && childNode->node_type&0x4 &&//can_move_to(childUpperLeftX,childUpperLeftY+1) &&
can_move_to(childUpperLeftX-1,childUpperLeftY+2) && can_move_to(childUpperLeftX,childUpperLeftY+2))
{
switch(fatherNode->enter_direction)
{
case 6: canMove = 0; //reverse direction
break;
case 4:case 5:case 7:case 8:
canMove = 1;
break;
case 1: if(fatherNode->node_type&0x8 || can_move_to(childUpperLeftX-2,childUpperLeftY+1))
canMove = 1;
break;
case 2: if(fatherNode->node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 3: if(fatherNode->node_type&0x1 || can_move_to(childUpperLeftX,childUpperLeftY+3))
canMove = 1;
break;
default: err_here();
break;
}
canMove = 1;
}
break;
case 3:
err_when(fatherNode->node_x!=childNode->node_x || fatherNode->node_y!=childNode->node_y+1);
if(childNode->node_type&0x4 && childNode->node_type&0x8 &&
can_move_to(childUpperLeftX,childUpperLeftY+2) && can_move_to(childUpperLeftX+1,childUpperLeftY+2))
{
switch(fatherNode->enter_direction)
{
case 7: canMove = 0; //reverse direction
break;
case 1:case 3:case 5:case 6:case 8:
canMove = 1;
break;
case 2: if(fatherNode->node_type&0x8 || can_move_to(childUpperLeftX-1,childUpperLeftY+2))
canMove = 1;
break;
case 4: if(fatherNode->node_type&0x4 || can_move_to(childUpperLeftX+2,childUpperLeftY+2))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 4:
err_when(fatherNode->node_x!=childNode->node_x+1 || fatherNode->node_y!=childNode->node_y+1);
if(childNode->node_type&0x8 && can_move_to(childUpperLeftX+2,childUpperLeftY+1) &&
can_move_to(childUpperLeftX+1,childUpperLeftY+2) && can_move_to(childUpperLeftX+2,childUpperLeftY+2))
{
switch(fatherNode->enter_direction)
{
case 8: canMove = 0; //reverse direction
break;
case 1:case 2:case 6:case 7:
canMove = 1;
break;
case 3: if(fatherNode->node_type&0x2 || can_move_to(childUpperLeftX+1,childUpperLeftY+3))
canMove = 1;
break;
case 4: if(fatherNode->node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 5: if(fatherNode->node_type&0x4 && can_move_to(childUpperLeftX+3,childUpperLeftY+1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 5:
err_when(fatherNode->node_x!=childNode->node_x+1 || fatherNode->node_y!=childNode->node_y);
if(childNode->node_type&0x2 && can_move_to(childUpperLeftX+2,childUpperLeftY) &&
childNode->node_type&0x8 && can_move_to(childUpperLeftX+2,childUpperLeftY+1))
{
switch(fatherNode->enter_direction)
{
case 1: canMove = 0; //reverse direction
break;
case 2:case 3:case 5:case 7:case 8:
canMove = 1;
break;
case 4: if(fatherNode->node_type&0x2 || can_move_to(childUpperLeftX+2,childUpperLeftY+2))
canMove = 1;
break;
case 6: if(fatherNode->node_type&0x8 || can_move_to(childUpperLeftX+2,childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 6:
err_when(fatherNode->node_x!=childNode->node_x+1 || fatherNode->node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX+1,childUpperLeftY-1) && can_move_to(childUpperLeftX+2,childUpperLeftY-1) &&
childNode->node_type&0x2 && can_move_to(childUpperLeftX+2,childUpperLeftY))
{
switch(fatherNode->enter_direction)
{
case 2: canMove = 0; //reverse direction
break;
case 1:case 3:case 4:case 8:
canMove = 1;
break;
case 5: if(fatherNode->node_type&0x1 || can_move_to(childUpperLeftX+3,childUpperLeftY))
canMove = 1;
break;
case 6: if(fatherNode->node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 7: if(fatherNode->node_type&0x8 || can_move_to(childUpperLeftX+1,childUpperLeftY-2))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 7:
err_when(fatherNode->node_x!=childNode->node_x || fatherNode->node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX,childUpperLeftY-1) && can_move_to(childUpperLeftX+1,childUpperLeftY-1) &&
childNode->node_type&0x1 && childNode->node_type&0x2)
{
switch(fatherNode->enter_direction)
{
case 3: canMove = 0; //reverse direction
break;
case 1:case 2:case 4:case 5:case 7:
canMove = 1;
break;
case 6: if(fatherNode->node_type&0x1 || can_move_to(childUpperLeftX+2,childUpperLeftY-1))
canMove = 1;
break;
case 8: if(fatherNode->node_type&0x2 || can_move_to(childUpperLeftX-1,childUpperLeftY-1))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
case 8:
err_when(fatherNode->node_x!=childNode->node_x-1 || fatherNode->node_y!=childNode->node_y-1);
if(can_move_to(childUpperLeftX-1,childUpperLeftY-1) && can_move_to(childUpperLeftX,childUpperLeftY-1) &&
can_move_to(childUpperLeftX-1,childUpperLeftY) && childNode->node_type&0x1)//can_move_to(childUpperLeftX,childUpperLeftY))
{
switch(fatherNode->enter_direction)
{
case 4: canMove = 0; //reverse direction
break;
case 2:case 3:case 5:case 6:
canMove = 1;
break;
case 1: if(fatherNode->node_type&0x2 || can_move_to(childUpperLeftX-2,childUpperLeftY))
canMove = 1;
break;
case 8: if(fatherNode->node_type==15)
canMove = 1;
else
canMove = 0;
break;
case 7: if(fatherNode->node_type&0x4 || can_move_to(childUpperLeftX,childUpperLeftY-2))
canMove = 1;
break;
default: err_here();
break;
}
}
break;
default: err_here();
break;
}
if(canMove)
{
exitDirection = (childEnterDirection+3)%8+1;
if(fatherNode->enter_direction > exitDirection)
{
if((fatherNode->enter_direction==8 && (exitDirection==1 || exitDirection==2)) ||
(fatherNode->enter_direction==7 && exitDirection==1))
testResult = exitDirection + 8 - fatherNode->enter_direction;
else
testResult = fatherNode->enter_direction - exitDirection;
}
else
{
if((exitDirection==8 && (fatherNode->enter_direction==1 || fatherNode->enter_direction==2)) ||
(exitDirection==7 && fatherNode->enter_direction==1))
testResult = fatherNode->enter_direction + 8 - exitDirection;
else
testResult = exitDirection - fatherNode->enter_direction;
}
if((exitDirection%2 && testResult<=2) || (!exitDirection%2 && testResult<=1))
cost = 1;
else
cost = 2;
err_when(cost>2 || cost<1);
if(g+cost < childNode->node_g) // second checking, mainly for cost = 2;
{
char canPropagateDown=1;
if(childNode->node_type!=15 && childEnterDirection%2==0)
{
NodeS2* oldChildNode;
short xShift1 = x_shift_array[childEnterDirection-1];
short yShift1 = y_shift_array[childEnterDirection-1];
short xShift2, yShift2, xShift3, yShift3;
if(childEnterDirection>1)
{
xShift2 = x_shift_array[childEnterDirection-2];
yShift2 = y_shift_array[childEnterDirection-2];
}
else
{
xShift2 = x_shift_array[7];
yShift2 = y_shift_array[7];
}
if(childEnterDirection<8)
{
xShift3 = x_shift_array[childEnterDirection];
yShift3 = y_shift_array[childEnterDirection];
}
else
{
xShift3 = x_shift_array[0];
yShift3 = y_shift_array[0];
}
for(c=0; cchild_node[c]; c++) // for each child of oldNode
{
oldChildNode = childNode->child_node[c];
if(childNode->parent_node != oldChildNode)
{
switch(childEnterDirection)
{
case 2:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY+2))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX+1,childUpperLeftY+1) &&
!can_move_to(childUpperLeftX-1,childUpperLeftY))
canPropagateDown = 0;
break;
case 4:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY+1)&&
!can_move_to(childUpperLeftX+2,childUpperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY+2) &&
!can_move_to(childUpperLeftX+1,childUpperLeftY))
canPropagateDown = 0;
break;
case 6:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY-1)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY+1))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX,childUpperLeftY) &&
!can_move_to(childUpperLeftX+2,childUpperLeftY+1))
canPropagateDown = 0;
break;
case 8:
if(oldChildNode->enter_direction==childEnterDirection &&
oldChildNode->node_x-childNode->node_x==xShift1 &&
oldChildNode->node_y-childNode->node_y==yShift1)
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection-1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX-1,childUpperLeftY+1)&&
!can_move_to(childUpperLeftX+1,childUpperLeftY))
canPropagateDown = 0;
if(oldChildNode->enter_direction==childEnterDirection+1 &&
oldChildNode->node_x-childNode->node_x==xShift2 &&
oldChildNode->node_x-childNode->node_y==yShift2 &&
!can_move_to(childUpperLeftX+1,childUpperLeftY-1) &&
!can_move_to(childUpperLeftX,childUpperLeftY+1))
canPropagateDown = 0;
break;
default: err_here();
break;
}
}
}
}
if(canPropagateDown)
{
childNode->node_g = g+cost;
childNode->node_f = childNode->node_g+childNode->node_h;
childNode->parent_node = fatherNode;
childNode->enter_direction = childEnterDirection;
stack_push(childNode);
}
}
}
}
}
}
}
//------- End of function NodeS2::propagate_down -------//
//-------- Begin of static function stack_push ---------//
static void stack_push(NodeS2 *nodePtr)
{
stack_array[cur_stack_pos_s2++] = nodePtr;
err_when( cur_stack_pos_s2 >= MAX_STACK_NUM );
}
//--------- End of static function stack_push ---------//
//-------- Begin of static function stack_pop ---------//
static NodeS2* stack_pop()
{
return stack_array[--cur_stack_pos_s2];
}
//--------- End of static function stack_pop ---------//