123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- #include <OSPREUSE.h>
- #include <OUNIT.h>
- #include <OWORLD.h>
- #include <OMISC.h>
- #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 <OSYS.h>
- #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; i<connectResultNodeNum; i++)
- {
- add_result(curResultNode->node_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<MAX_WORLD_X_LOC && unitNodeYLoc>=0 && unitNodeYLoc<MAX_WORLD_Y_LOC &&
- ((move_scale==1 && can_walk(unitNodeXLoc, unitNodeYLoc)) ||
- (move_scale==2 && can_walk(unitNodeXLoc, unitNodeYLoc) &&
- can_walk(unitNodeXLoc-leader_vec_x, unitNodeYLoc-leader_vec_y)) ))
- {
- //----------------------------------------------------------------------------//
- // offset node exists, so add it to the result path
- //----------------------------------------------------------------------------//
- add_result(unitNodeXLoc, unitNodeYLoc); // add result if location can be reached
- if(unitNodeXLoc==vir_dest_x && unitNodeYLoc==vir_dest_y)
- break;
- }
- else
- {
- //----------------------------------------------------------------------------//
- // get the next non-blocked location calculated by offset
- //----------------------------------------------------------------------------//
- nextNonblockedLeaderXLoc = leaderNodeXLoc; // used as reference
- nextNonblockedLeaderYLoc = leaderNodeYLoc;
- preLeaderVecX = leader_vec_x;
- preLeaderVecY = leader_vec_y;
- //========================================================================//
- //========================================================================//
- if(get_next_nonblocked_offset_loc(nextNonblockedLeaderXLoc, nextNonblockedLeaderYLoc)) // get the next nonblocked location for joining
- {
- if(is_node_avail_empty())
- {
- incomplete_search++;
- reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH;
- return;
- }
- //--- seek from the current location to the next non-blocked location ---//
- err_when(num_of_result_node<1);
- preNonblockedXLoc = (cur_result_node_ptr-1)->node_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<MAX_WORLD_X_LOC && unitDestY>=0 && unitDestY<MAX_WORLD_Y_LOC &&
- can_walk(unitDestX, unitDestY))
- found = 1;
- }
- return found;*/
- while(!found)
- {
- if(nextXLoc != cur_leader_node_ptr->node_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<MAX_WORLD_X_LOC && unitDestY>=0 && unitDestY<MAX_WORLD_Y_LOC &&
- can_walk(unitDestX, unitDestY))
- found = 1;
- }
- else
- {
- if(cur_leader_node_num < reuse_leader_path_node_num)
- {
- 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;
- 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<MAX_WORLD_X_LOC && unitDestY>=0 && unitDestY<MAX_WORLD_Y_LOC &&
- can_walk(unitDestX, unitDestY))
- found = 1;
- }
- else
- break; // or return 0;
- }
- sys_yield(); // update cursor position
- }
- return found;
- }
- //--------- End of function SeekPathReuse::get_next_nonblocked_offset_loc ---------//
- //-------- Begin of function SeekPathReuse::get_next_offset_loc ---------//
- // get the next location along the main path (reuse reference path)
- // return 1 if found, 0 for end of the path
- //
- int SeekPathReuse::get_next_offset_loc(int& nextXLoc, int& nextYLoc)
- {
- if(nextXLoc != cur_leader_node_ptr->node_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++<reuse_leader_path_node_num)
- {
- curXLoc = curNodePtr->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<MAX_WORLD_X_LOC && curYLoc>=0 && curYLoc<MAX_WORLD_Y_LOC) // inside map
- {
- //----------------------------------------------------------------------//
- // checking passable condition
- //----------------------------------------------------------------------//
- if(reuse_search_sub_mode==SEARCH_SUB_MODE_PASSABLE)
- {
- vecX = curXLoc-preXLoc;
- vecY = curYLoc-preYLoc;
- magn = ((magnX=abs(vecX)) > (magnY=abs(vecY))) ? magnX : magnY;
- if(magnX) vecX /= magnX;
- if(magnY) vecY /= magnY;
- checkXLoc = preXLoc;
- checkYLoc = preYLoc;
- quitLoop = 0;
- for(i=0; i<magn; ++i)
- {
- checkXLoc += vecX;
- checkYLoc += vecY;
- locPtr = world.get_loc(checkXLoc, checkYLoc);
- if(locPtr->power_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 ---------//
|