/* * 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 . * */ #include #include #include #include #ifdef NO_DEBUG_SEARCH #undef err_when #undef err_here #undef err_if #undef err_else #undef err_now #define err_when(cond) #define err_here() #define err_if(cond) #define err_else #define err_now(msg) #undef debug_reuse_check_path #define debug_reuse_check_path() #undef DEBUG #endif #ifdef DEBUG #include #endif //------------------- static function --------------------// // check whether a location can be walked. This function is // similar to that in SeekPath. However, only several search // mode is useful here. i.e. search mode 1 and 2. // int SeekPathReuse::can_walk(int xLoc, int yLoc) { if(xLoc>=MAX_WORLD_X_LOC || yLoc>=MAX_WORLD_Y_LOC) return 0; Location *locPtr = world.get_loc(xLoc, yLoc); short recno = (mobile_type!=UNIT_AIR) ? locPtr->cargo_recno : locPtr->air_cargo_recno; Unit *unitPtr; UCHAR unitCurAction; //------ check terrain id. -------// switch(mobile_type) { case UNIT_LAND: if(reuse_search_sub_mode==SEARCH_SUB_MODE_PASSABLE && locPtr->power_nation_recno && !reuse_nation_passable[locPtr->power_nation_recno]) return 0; if(!locPtr->walkable()) return 0; if(!recno) return 1; unitPtr = unit_array[recno]; if(search_mode==SEARCH_MODE_A_UNIT_IN_GROUP) return unitPtr->cur_action==SPRITE_MOVE; else { unitCurAction = unitPtr->cur_action; return (unitPtr->unit_group_id==cur_group_id && unitCurAction!=SPRITE_ATTACK) || (unitCurAction==SPRITE_MOVE && unitPtr->cur_x-unitPtr->next_x<=ZOOM_LOC_WIDTH/2 && unitPtr->cur_y-unitPtr->next_y<=ZOOM_LOC_HEIGHT/2) || (unitPtr->nation_recno==unit_nation_recno && unitCurAction==SPRITE_IDLE); } break; case UNIT_SEA: if(!locPtr->sailable()) return 0; if(!recno) return 1; unitPtr = unit_array[recno]; if(search_mode==SEARCH_MODE_A_UNIT_IN_GROUP) return unitPtr->cur_action==SPRITE_MOVE; else { unitCurAction = unitPtr->cur_action; return (unitPtr->unit_group_id==cur_group_id && unitCurAction!=SPRITE_ATTACK) || unitCurAction==SPRITE_MOVE || (unitPtr->nation_recno==unit_nation_recno && unitCurAction==SPRITE_IDLE); } break; case UNIT_AIR: if(!recno) return 1; unitPtr = unit_array[recno]; if(search_mode==SEARCH_MODE_A_UNIT_IN_GROUP) return unitPtr->cur_action==SPRITE_MOVE; else { unitCurAction = unitPtr->cur_action; return (unitPtr->unit_group_id==cur_group_id && unitCurAction!=SPRITE_ATTACK) || unitCurAction==SPRITE_MOVE || (unitPtr->nation_recno==unit_nation_recno && unitCurAction==SPRITE_IDLE); } break; } return 0; } //------------ End of static function ----------------// //------------------- static function --------------------// int SeekPathReuse::can_walk_s2(int xLoc, int yLoc) { if(xLoc>=MAX_WORLD_X_LOC-1 || yLoc>=MAX_WORLD_Y_LOC-1) return 0; if(can_walk(xLoc, yLoc) && can_walk(xLoc+1,yLoc) && can_walk(xLoc,yLoc+1) && can_walk(xLoc+1,yLoc+1)) return 1; else return 0; } //------------ End of static function ----------------// //------------------- static function --------------------// void SeekPathReuse::sys_yield() { //sys.yield(); } //------------ End of static function ----------------// //-------- Begin of function SeekPathReuse::seek_path_offset ---------// void SeekPathReuse::seek_path_offset() { if(!is_leader_path_valid()) return; if(is_node_avail_empty()) { copy_leader_path_offset(); return; } //------------ construct data structure to store result node ----------------// result_node_array_def_size += result_node_array_reset_amount; path_reuse_result_node_ptr = (ResultNode*) mem_add(sizeof(ResultNode)* result_node_array_def_size); memset(path_reuse_result_node_ptr, 0, sizeof(ResultNode)* result_node_array_def_size); cur_result_node_ptr = path_reuse_result_node_ptr; num_of_result_node = 0; //---------------- set starting point ----------------------// add_result(start_x, start_y); //-----------------initialize offset path reuse ------------// cur_leader_node_ptr = reuse_leader_path_backup+1; cur_leader_node_num = 2; use_offset_method(reuse_leader_path_backup[0].node_x, reuse_leader_path_backup[0].node_y); // using offset path method directly //----------------------------------------------------------------------// // checking for incomplete searching //----------------------------------------------------------------------// ResultNode *lastNode = path_reuse_result_node_ptr + num_of_result_node - 1; if((lastNode->node_x!=vir_dest_x || lastNode->node_y!=vir_dest_y) && is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; } } //--------- End of function SeekPathReuse::seek_path_offset ---------// //-------- Begin of function SeekPathReuse::seek_path_join_offset ---------// // The join-offset-path method. // void SeekPathReuse::seek_path_join_offset() { if(!is_leader_path_valid()) return; //----------------------------------------------------------------------// // checking for incomplete searching //----------------------------------------------------------------------// if(is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; return; } err_when(unit_size!=1); memset(reuse_node_matrix, 0, sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4); path_reuse_result_node_ptr = NULL; //--------------------------------------------------------------// // initialization and declaring variables //--------------------------------------------------------------// int connectResultNodeNum; ResultNode* connectResultNodePtr=NULL; cur_leader_node_ptr = reuse_leader_path_backup; cur_leader_node_num = 1; int leaderNodeXLoc = cur_leader_node_ptr->node_x; int leaderNodeYLoc = cur_leader_node_ptr->node_y; #ifdef DEBUG int debugLoopCount = 0; #endif do { err_when(++debugLoopCount>10000); set_index_in_node_matrix(leaderNodeXLoc+x_offset, leaderNodeYLoc+y_offset); }while(get_next_offset_loc(leaderNodeXLoc, leaderNodeYLoc)); //--------------------------------------------------------------// // copy the node_matrix to that node_matrix used in class SeekPath //--------------------------------------------------------------// err_when(unit_size!=1); seek_path.set_node_matrix(reuse_node_matrix); //--------------------------------------------------------------// // process shortest path searching to find a walkable point in // the offset path for connection //--------------------------------------------------------------// //--- if the starting location is already in the offset path, process it immediately ---// err_when(unit_size!=1); short *locNode = reuse_node_matrix + MAX_WORLD_X_LOC/2*(start_y/2) + (start_x/2); if(*locNode > max_node && mobile_type==UNIT_LAND) // starting point on the reuse offset path { connectResultNodePtr = (ResultNode*) mem_add(sizeof(ResultNode)*2); ResultNode* curNode = connectResultNodePtr; curNode->node_x = start_x; curNode->node_y = start_y; connectResultNodeNum = 1; curNode++; switch(*locNode-max_node) { case 1: if(start_x%2 || start_y%2) { curNode->node_x = (start_x%2) ? start_x-1 : start_x; curNode->node_y = (start_y%2) ? start_y-1 : start_y; connectResultNodeNum++; } break; case 2: if(!(start_x%2 && start_y%2==0)) { curNode->node_x = (start_x%2) ? start_x : start_x+1; curNode->node_y = (start_y%2) ? start_y-1 : start_y; connectResultNodeNum++; } break; case 3: if(!(start_x%2==0 && start_y%2)) { curNode->node_x = (start_x%2) ? start_x-1 : start_x; curNode->node_y = (start_y%2) ? start_y : start_y+1; connectResultNodeNum++; } break; case 4: if(start_x%2==0 || start_y%2==0) { curNode->node_x = (start_x%2) ? start_x : start_x+1; curNode->node_y = (start_y%2) ? start_y : start_y+1; connectResultNodeNum++; } break; } //********BUGHERE // unable to handle this blocked case now, abort path-reuse and seeking instead if(connectResultNodeNum>1 && !can_walk(curNode->node_x, curNode->node_y)) { path_reuse_result_node_ptr = call_seek(start_x, start_y, vir_dest_x, vir_dest_y, cur_group_id, mobile_type, SEARCH_MODE_IN_A_GROUP, num_of_result_node); mem_del(connectResultNodePtr); return; } } else { //------------- seek for connection point ------------// connectResultNodePtr = call_seek(start_x, start_y, vir_dest_x, vir_dest_y, cur_group_id, mobile_type, SEARCH_MODE_REUSE, connectResultNodeNum); err_when(connectResultNodePtr!=NULL && connectResultNodeNum<2); if(connectResultNodePtr==NULL || connectResultNodeNum==0) // cannot reach the destination { if(connectResultNodePtr!=NULL) mem_del(connectResultNodePtr); return; } } //--------------------------------------------------------------// // constructing data structure //--------------------------------------------------------------// result_node_array_def_size += result_node_array_reset_amount; path_reuse_result_node_ptr = (ResultNode*) mem_add(sizeof(ResultNode)* result_node_array_def_size); memset(path_reuse_result_node_ptr, 0, sizeof(ResultNode)* result_node_array_def_size); cur_result_node_ptr = path_reuse_result_node_ptr; num_of_result_node = 0; //--------------------------------------------------------------// // add the result path //--------------------------------------------------------------// ResultNode* curResultNode = connectResultNodePtr; for(int i=0; inode_x, curResultNode->node_y); curResultNode++; } //--------------------------------------------------------------// // determine the joining point in the offset path //--------------------------------------------------------------// cur_leader_node_ptr = reuse_leader_path_backup; cur_leader_node_num = 1; ResultNode *endNode = connectResultNodePtr + connectResultNodeNum - 1; short findConnectionPoint = 0; if(endNode->node_x==vir_dest_x && endNode->node_y==vir_dest_y) { if(connectResultNodePtr!=NULL); mem_del(connectResultNodePtr); return; // already the destination location } //------------------------------------------------------------------------------------// // find a offset-reference point in leader path //------------------------------------------------------------------------------------// leaderNodeXLoc = cur_leader_node_ptr->node_x; leaderNodeYLoc = cur_leader_node_ptr->node_y; short notEnd = 1; sys_yield(); // update cursor position int unitDestX, unitDestY; // for the current searching unit, using the leader path do { //---------- boundary checking -----------// bound_check_x((unitDestX = leaderNodeXLoc+x_offset)); bound_check_y((unitDestY = leaderNodeYLoc+y_offset)); if(endNode->node_x==unitDestX && endNode->node_y==unitDestY) findConnectionPoint = 1; // ok, connected else notEnd = get_next_offset_loc(leaderNodeXLoc, leaderNodeYLoc); if(!notEnd) break; }while(!findConnectionPoint); sys_yield(); // update cursor position //-------------- clear the temporary path ------------// if(connectResultNodePtr!=NULL) mem_del(connectResultNodePtr); //-----------------------------------------------------------------------------// // return since cannot find a connection point //-----------------------------------------------------------------------------// if(!findConnectionPoint) { //----------------------------------------------------------------------// // checking for incomplete searching //----------------------------------------------------------------------// if(is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; } if(num_of_result_node==1) { mem_del(path_reuse_result_node_ptr); path_reuse_result_node_ptr = NULL; num_of_result_node = 0; } return; } //-----------------------------------------------------------------------------// // update pointer cur_leader_node_ptr if necessary //-----------------------------------------------------------------------------// if(leaderNodeXLoc==cur_leader_node_ptr->node_x && leaderNodeYLoc==cur_leader_node_ptr->node_y) // at the turning point { if(cur_leader_node_num < reuse_leader_path_node_num) { cur_leader_node_num++; cur_leader_node_ptr++; } else // join at the end of the offset path, search finished return; } //----------------------------------------------------------------------------------------// // at this moment, the searching unit has a offset path to the leader path. // There are not processed leader nodes. These nodes are pointed by cur_leader_node_ptr. //----------------------------------------------------------------------------------------// use_offset_method(leaderNodeXLoc, leaderNodeYLoc); // changed to offset method for the rest //----------------------------------------------------------------------// // checking for incomplete searching //----------------------------------------------------------------------// ResultNode *lastNode = path_reuse_result_node_ptr + num_of_result_node - 1; if((lastNode->node_x!=vir_dest_x || lastNode->node_y!=vir_dest_y) && is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; } } //--------- End of function SeekPathReuse::seek_path_join_offset ---------// //-------- Begin of function SeekPathReuse::use_offset_method ---------// void SeekPathReuse::use_offset_method(int xLoc, int yLoc) { //----------------------------------------------------------------------// // checking for incomplete searching //----------------------------------------------------------------------// if(is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; return; } //-----------------------------------------------------// int leaderNodeXLoc = xLoc; // hold the currently referred leader node int leaderNodeYLoc = yLoc; leader_vec_x = cur_leader_node_ptr->node_x - leaderNodeXLoc; leader_vec_y = cur_leader_node_ptr->node_y - leaderNodeYLoc; if(leader_vec_x!=0) leader_vec_x /= abs(leader_vec_x); if(leader_vec_y!=0) leader_vec_y /= abs(leader_vec_y); ResultNode *partOfResultNodePtr, *curNodePtr; int partOfResultNodeNum, restNode; partOfResultNodePtr = NULL; partOfResultNodeNum = 0; //-----------------------------------------------------// int unitNodeXLoc, unitNodeYLoc; int preNonblockedXLoc, preNonblockedYLoc; int nextNonblockedLeaderXLoc, nextNonblockedLeaderYLoc; int preLeaderVecX, preLeaderVecY; int virDestX, virDestY; int pathSeekResult, canReach; //-----------------------------------------------------// // start walking along the leader path //-----------------------------------------------------// #ifdef DEBUG int debugPreLeaderNodeXLoc, debugPreLeaderNodeYLoc; while(debugPreLeaderNodeXLoc=leaderNodeXLoc, debugPreLeaderNodeYLoc=leaderNodeYLoc, get_next_offset_loc(leaderNodeXLoc, leaderNodeYLoc)) // get next location in the leader path #else while(get_next_offset_loc(leaderNodeXLoc, leaderNodeYLoc)) // get next location in the leader path #endif { err_when(leaderNodeXLoc<0 || leaderNodeXLoc>=MAX_WORLD_X_LOC); err_when(leaderNodeYLoc<0 || leaderNodeYLoc>=MAX_WORLD_Y_LOC); err_when(partOfResultNodePtr!=NULL); sys_yield(); // update cursor position unitNodeXLoc = leaderNodeXLoc+x_offset; // calculate the corresponding location in the offset path. unitNodeYLoc = leaderNodeYLoc+y_offset; if(unitNodeXLoc>=0 && unitNodeXLoc=0 && unitNodeYLocnode_x; preNonblockedYLoc = (cur_result_node_ptr-1)->node_y; //bound_check_x((preNonblockedXLoc = unitNodeXLoc-preLeaderVecX*move_scale)); //bound_check_y((preNonblockedYLoc = unitNodeYLoc-preLeaderVecY*move_scale)); err_when(preNonblockedXLoc<0 || preNonblockedXLoc>=MAX_WORLD_X_LOC); err_when(preNonblockedYLoc<0 || preNonblockedYLoc>=MAX_WORLD_Y_LOC); //-------- find a path to the next non-blocked location ----------// bound_check_x((virDestX = nextNonblockedLeaderXLoc+x_offset)); bound_check_y((virDestY = nextNonblockedLeaderYLoc+y_offset)); err_when(partOfResultNodePtr!=NULL); err_when(unit_size!=1); pathSeekResult = seek_path.seek(preNonblockedXLoc, preNonblockedYLoc, virDestX, virDestY, cur_group_id, mobile_type, SEARCH_MODE_IN_A_GROUP); partOfResultNodePtr = seek_path.get_result(partOfResultNodeNum, reuse_path_dist); //--------------------------------------------------------------------------// // go to destination directly if cannot reach the next nonblocked lcoation //--------------------------------------------------------------------------// if(partOfResultNodePtr==NULL || partOfResultNodeNum==0) canReach = 0; else { #ifdef DEBUG int ddX = abs((cur_result_node_ptr-1)->node_x-partOfResultNodePtr[0].node_x); int ddY = abs((cur_result_node_ptr-1)->node_y-partOfResultNodePtr[0].node_y); err_when(ddX && ddY && ddX!=ddY); #endif ResultNode *curNode = partOfResultNodePtr + partOfResultNodeNum-1; if(curNode->node_x==virDestX && curNode->node_y==virDestY) canReach = 1; else { canReach = 0; mem_del(partOfResultNodePtr); partOfResultNodePtr = NULL; } } if(canReach==0) // unable to reach the location specified { if(is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; return; } bound_check_x((virDestX = dest_x)); bound_check_y((virDestY = dest_y)); err_when(partOfResultNodePtr!=NULL); err_when(unit_size!=1); int pathSeekResult= seek_path.seek(preNonblockedXLoc, preNonblockedYLoc, virDestX, virDestY, cur_group_id, mobile_type, SEARCH_MODE_IN_A_GROUP); partOfResultNodePtr = seek_path.get_result(partOfResultNodeNum, reuse_path_dist); #ifdef DEBUG if(partOfResultNodePtr!=NULL) { int ddX = abs((cur_result_node_ptr-1)->node_x-partOfResultNodePtr[0].node_x); int ddY = abs((cur_result_node_ptr-1)->node_y-partOfResultNodePtr[0].node_y); err_when(ddX && ddY && ddX!=ddY); } #endif } //---------------------- connect the two paths ----------------------// if(partOfResultNodePtr!=NULL) { restNode = partOfResultNodeNum; curNodePtr = partOfResultNodePtr; err_when(preNonblockedXLoc!=partOfResultNodePtr->node_x || preNonblockedYLoc!=partOfResultNodePtr->node_y); restNode--; curNodePtr++; while(restNode) { add_result(curNodePtr->node_x, curNodePtr->node_y); curNodePtr++; restNode--; } debug_reuse_check_path(); //-************** debug checking mem_del(partOfResultNodePtr); partOfResultNodePtr = NULL; } err_when(partOfResultNodePtr!=NULL); if(canReach) { leaderNodeXLoc = nextNonblockedLeaderXLoc; leaderNodeYLoc = nextNonblockedLeaderYLoc; } else { //------------------------------------------------// // incomplete search //------------------------------------------------// if(is_node_avail_empty()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; return; } break; } if(pathSeekResult!=PATH_FOUND && pathSeekResult!=PATH_REUSE_FOUND) break; } //========================================================================// //========================================================================// else // no next non-blocked offset location, searching directly to the destinaton { //-------------------------------------------------------------// // move directly to the destination from the current location // // This case occurs when the destination cannot be reached. //-------------------------------------------------------------// //--- seek from the current location to the destination ---// //bound_check_x((preNonblockedXLoc = unitNodeXLoc-preLeaderVecX*move_scale)); //bound_check_y((preNonblockedYLoc = unitNodeYLoc-preLeaderVecY*move_scale)); err_when(num_of_result_node<1); preNonblockedXLoc = (cur_result_node_ptr-1)->node_x; preNonblockedYLoc = (cur_result_node_ptr-1)->node_y; err_when(preNonblockedXLoc<0 || preNonblockedXLoc>=MAX_WORLD_X_LOC); err_when(preNonblockedYLoc<0 || preNonblockedYLoc>=MAX_WORLD_Y_LOC); bound_check_x((virDestX = nextNonblockedLeaderXLoc+x_offset)); bound_check_y((virDestY = nextNonblockedLeaderYLoc+y_offset)); err_when(partOfResultNodePtr!=NULL); //------------------------------------------------// // set to incomplete_search for later searching //------------------------------------------------// incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; #ifdef DEBUG int ddX1 = abs((cur_result_node_ptr-1)->node_x-preNonblockedXLoc); int ddY1 = abs((cur_result_node_ptr-1)->node_y-preNonblockedYLoc); err_when(ddX1 && ddY1 && ddX1!=ddY1); #endif err_when(unit_size!=1); seek_path.seek(preNonblockedXLoc, preNonblockedYLoc, virDestX, virDestY, cur_group_id, mobile_type, 1); partOfResultNodePtr = seek_path.get_result(partOfResultNodeNum, reuse_path_dist); //---------------- connect the two paths together ----------------// if(partOfResultNodePtr!=NULL) { #ifdef DEBUG int ddX = abs((cur_result_node_ptr-1)->node_x-partOfResultNodePtr[0].node_x); int ddY = abs((cur_result_node_ptr-1)->node_y-partOfResultNodePtr[0].node_y); err_when(ddX && ddY && ddX!=ddY); #endif err_when(preNonblockedXLoc!=partOfResultNodePtr->node_x || preNonblockedYLoc!=partOfResultNodePtr->node_y); restNode = partOfResultNodeNum-1; curNodePtr = partOfResultNodePtr+1; while(restNode) { add_result(curNodePtr->node_x, curNodePtr->node_y); curNodePtr++; restNode--; } debug_reuse_check_path(); //-************** debug checking mem_del(partOfResultNodePtr); partOfResultNodePtr = NULL; } }//end if get_next_nonblocked_offset_loc() //-------------------------------------------------------------------------------------------------// // update leaderNode?Loc since it may be changed after calling get_next_nonblocked_offset_loc() //-------------------------------------------------------------------------------------------------// leaderNodeXLoc = nextNonblockedLeaderXLoc; leaderNodeYLoc = nextNonblockedLeaderYLoc; } debug_reuse_check_path(); //-************** debug checking err_when(partOfResultNodePtr!=NULL); } // end while err_when(partOfResultNodePtr!=NULL); debug_reuse_check_path(); //-************** debug checking } //--------- End of function SeekPathReuse::use_offset_method ---------// //-------- Begin of function SeekPathReuse::get_next_nonblocked_offset_loc ---------// // find the next nonblocked offset location if the inputed location is blocked // return 1 if found, 0 for none // int SeekPathReuse::get_next_nonblocked_offset_loc(int& nextXLoc, int&nextYLoc) { int found = 0; int unitDestX, unitDestY; /*#ifdef DEBUG int debugLoopCount = 0; #endif while(!found) { err_when(++debugLoopCount>10000); if(!get_next_offset_loc(nextXLoc, nextYLoc)) break; // all nodes visited unitDestX = nextXLoc+x_offset; unitDestY = nextYLoc+y_offset; err_when(unit_size!=1); if(unitDestX>=0 && unitDestX=0 && unitDestYnode_x || nextYLoc != cur_leader_node_ptr->node_y) { nextXLoc += leader_vec_x; nextYLoc += leader_vec_y; unitDestX = nextXLoc+x_offset; unitDestY = nextYLoc+y_offset; err_when(unit_size!=1); if(unitDestX>=0 && unitDestX=0 && unitDestYnode_x - nextXLoc; leader_vec_y = cur_leader_node_ptr->node_y - nextYLoc; if(leader_vec_x!=0) { leader_vec_x /= abs(leader_vec_x); nextXLoc += leader_vec_x; } if(leader_vec_y!=0) { leader_vec_y /= abs(leader_vec_y); nextYLoc += leader_vec_y; } unitDestX = nextXLoc+x_offset; unitDestY = nextYLoc+y_offset; err_when(unit_size!=1); if(unitDestX>=0 && unitDestX=0 && unitDestYnode_x || nextYLoc != cur_leader_node_ptr->node_y) { //--------- point in a the middle of two nodes ----------// nextXLoc += leader_vec_x*move_scale; nextYLoc += leader_vec_y*move_scale; return 1; } else if(cur_leader_node_num < reuse_leader_path_node_num) { //------------- the end of a node ----------// cur_leader_node_num++; cur_leader_node_ptr++; leader_vec_x = cur_leader_node_ptr->node_x - nextXLoc; leader_vec_y = cur_leader_node_ptr->node_y - nextYLoc; err_when(leader_vec_x!=0 && leader_vec_y!=0 && abs(leader_vec_x)!=abs(leader_vec_y)); if(leader_vec_x!=0) { leader_vec_x /= abs(leader_vec_x); nextXLoc += leader_vec_x*move_scale; } if(leader_vec_y!=0) { leader_vec_y /= abs(leader_vec_y); nextYLoc += leader_vec_y*move_scale; } err_when(nextXLoc<0 || nextXLoc>=MAX_WORLD_X_LOC); err_when(nextYLoc<0 || nextYLoc>=MAX_WORLD_Y_LOC); return 1; } else return 0; } //--------- End of function SeekPathReuse::get_next_offset_loc ---------// //-------- Begin of function SeekPathReuse::copy_leader_path_offset ---------// void SeekPathReuse::copy_leader_path_offset() { if(!is_leader_path_valid()) { incomplete_search++; reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH; return; } err_when(leader_path_num<0 || leader_path_num>total_num_of_path); cur_leader_node_ptr = reuse_leader_path_backup; cur_leader_node_num = 1; ResultNode *curNodePtr = cur_leader_node_ptr; err_when(curNodePtr->node_x+x_offset<0 || curNodePtr->node_x+x_offset>=MAX_WORLD_X_LOC || curNodePtr->node_y+y_offset<0 || curNodePtr->node_y+y_offset>=MAX_WORLD_Y_LOC); int preXLoc = curNodePtr->node_x+x_offset; int preYLoc = curNodePtr->node_y+y_offset; add_result(preXLoc, preYLoc); int curXLoc, curYLoc; curNodePtr++; int status = 0; // 0 for current position inside map, 1 for outside map int checkXLoc, checkYLoc; int vecX, vecY, magnX, magnY, magn; int i, quitLoop; Location *locPtr; while(cur_leader_node_num++node_x+x_offset; curYLoc = curNodePtr->node_y+y_offset; //----------------------------------------------------------------------// // offset method is terminated when the path leaves the map region for // this version. //----------------------------------------------------------------------// if(curXLoc>=0 && curXLoc=0 && curYLoc (magnY=abs(vecY))) ? magnX : magnY; if(magnX) vecX /= magnX; if(magnY) vecY /= magnY; checkXLoc = preXLoc; checkYLoc = preYLoc; quitLoop = 0; for(i=0; ipower_nation_recno && !reuse_nation_passable[locPtr->power_nation_recno]) { quitLoop = 1; break; // can't handle this case: not passable and copying leader path } } if(quitLoop) break; } status = 0; if(!status) // inside move_within_map(preXLoc, preYLoc, curXLoc, curYLoc); else // outside //move_inside_map(preXLoc, preYLoc, curXLoc, curYLoc); break; } else // outside { //----------------------------------------------------------------------// // checking passable condition //----------------------------------------------------------------------// if(reuse_search_sub_mode==SEARCH_SUB_MODE_PASSABLE) break; status = 1; if(!status) // inside { move_outside_map(preXLoc, preYLoc, curXLoc, curYLoc); break; } else // outside //move_beyond_map(preXLoc, preYLoc, curXLoc, curYLoc); break; } debug_reuse_check_path(); //-************** debug checking preXLoc = curXLoc; preYLoc = curYLoc; curNodePtr++; } debug_reuse_check_path(); //-************** debug checking } //--------- End of function SeekPathReuse::copy_leader_path_offset ---------//