//------------ Begin of function Unit::can_move2 -------------------// // // check a specific location can be walk, taking care that if that location is occupied // by a walking or waiting unit, that location will later on be freed. // // <int> locX - x-coordinate // <int> locY - y-coordinate // // return: <bool> - true if the location ccan be walked to // false otherwise // bool UnitB::can_move2(int locX, int locY) { Location* locPtr; int occRecno; Unit* unitPtr; int i, j; for(i=0; i<obj_loc_width(); i++) { for(j=0; j<obj_loc_height(); j++) { locPtr = world.get_loc(locX+i, locY+j); if(locX+i>= MAX_WORLD_X_LOC || locX+i <0 || locY+j >= MAX_WORLD_Y_LOC || locY+j < 0 ) return false; else if(!locPtr->can_move(mobile_type)) { occRecno = locPtr->unit_recno(mobile_type); if(!occRecno) //not a unit return false; else if(occRecno != sprite_recno) { unitPtr = unit_array[occRecno]; if(unitPtr->cur_action == SPRITE_WAIT || unitPtr->cur_action == SPRITE_MOVE) continue; else return false; } } } } return true; }
//--------- Begin of function Unit::ship_leave_beach ---------// void Unit::ship_leave_beach(int shipOldXLoc, int shipOldYLoc) { err_when(cur_x!=next_x || cur_y!=next_y); UnitMarine *shipPtr = (UnitMarine*) this; err_when(!shipPtr->in_beach && shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH); //--------------------------------------------------------------------------------// // scan for location to leave the beach //--------------------------------------------------------------------------------// int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); int xShift, yShift, checkXLoc, checkYLoc, found=0; Location *locPtr; //------------- find a location to leave the beach ------------// for(int i=2; i<=9; i++) { misc.cal_move_around_a_point(i, 3, 3, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; if(checkXLoc%2 || checkYLoc%2) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN && locPtr->can_move(mobile_type)) { found++; break; } } if(!found) return; // no suitable location, wait until finding suitable location //---------------- leave now --------------------// set_dir(shipOldXLoc, shipOldYLoc, checkXLoc, checkYLoc); set_ship_extra_move(); go_x = checkXLoc*ZOOM_LOC_WIDTH; go_y = checkYLoc*ZOOM_LOC_HEIGHT; err_when(cur_x==go_x && cur_y==go_y); }
//--------- Begin of function Unit::search_or_stop ---------// // process searching or stop the units // // <int> destX - x location to move to // <int> destY - y location to move to // <int> preserveAction - preserve action when calling to stop // <short> searchMode - search mode for searching // <short> miscNo - miscenllaneous information // void Unit::search_or_stop(int destX, int destY, int preserveAction, short searchMode, short miscNo) { Location *locPtr = world.get_loc(destX, destY); if(!locPtr->can_move(mobile_type)) { stop(KEEP_PRESERVE_ACTION); // let reactivate..() call searching later //waiting_term = MAX_SEARCH_OT_STOP_WAIT_TERM; } else { search(destX, destY, preserveAction, searchMode, miscNo); /*if(mobile_type==UNIT_LAND) search(destX, destY, preserveAction, searchMode, miscNo); else waiting_term = 0;*/ } }
//------------ Begin of function Unit::can_move -------------------// // // check whether a specific location can go walk to // // <int> locX - x-coordinate // <int> locY - y-coordinate // // return: <bool> - return true if the lcoation can be walk // return false if the location cannot be walk bool UnitB::can_move(int locX, int locY) { // ###### begin Gilbert 20/4 ##########// Location* locPtr; // int i, j; // for(i=0; i<obj_loc_width(); i++) // { // for(j=0; j<obj_loc_height(); j++) // { // locPtr = world.get_loc(locX+i, locY+j); // if(locX+i>= MAX_WORLD_X_LOC || locX+i <0 || locY+j >= MAX_WORLD_Y_LOC || locY+j < 0 || (!locPtr->can_move(obj_mobile_type()) && (locPtr->unit_recno(obj_mobile_type()) != sprite_recno))) // return false; // } // } if( loc_width == 1 ) { err_when( loc_height != 1); if( locX<0 || locY<0 || locX >= MAX_WORLD_X_LOC || locY >= MAX_WORLD_Y_LOC ) return false; if( !(locPtr=world.get_loc(locX, locY))->can_move(mobile_type) && locPtr->unit_recno(mobile_type) != sprite_recno ) return false; } else { int i, j; if( locX<0 || locY<0 || locX+loc_width > MAX_WORLD_X_LOC || locY+loc_height > MAX_WORLD_Y_LOC ) return false; for( j = 0; j < loc_height; ++j ) { locPtr = world.get_loc( locX, locY+j); for( i = 0; i < loc_width; ++i, ++locPtr ) { if( !locPtr->can_move(mobile_type) && locPtr->unit_recno(mobile_type) != sprite_recno ) return false; } } } // ###### end Gilbert 20/4 ##########// return true; }
//-------- Begin of static function is_space --------// // // Check whether all locations in the given area are space // // return : <int> 1 - all are space // 0 - not all are space // static int is_space(int xLoc1, int yLoc1, int xLoc2, int yLoc2, char mobileType) { int xLoc, yLoc; Location* locPtr; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = world.get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { if( !locPtr->can_move(mobileType) ) return 0; } } return 1; }
//--------- Begin of function Unit::ai_escape_fire --------// // // Move away if the unit currently stands on a burning ground. // int Unit::ai_escape_fire() { if(cur_action!=SPRITE_IDLE) return 0; if(mobile_type!=UNIT_LAND) return 0; Location *locPtr = world.get_loc(next_x_loc(), next_y_loc()); if( !locPtr->fire_str() ) return 0; //--------------------------------------------// int checkLimit = 400; // checking for 400 location int xShift, yShift, checkXLoc, checkYLoc; int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); for(int i=2; i<checkLimit; i++) { misc.cal_move_around_a_point(i, 20, 20, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; if(!locPtr->can_move(mobile_type)) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if( locPtr->fire_str()==0 ) // move to a safe place now { move_to(checkXLoc, checkYLoc); return 1; } } return 0; }
static int is_location_walkable(int xLoc, int yLoc) { err_when(xLoc < 0); err_when(xLoc >= MAX_WORLD_X_LOC); err_when(yLoc < 0); err_when(yLoc >= MAX_WORLD_Y_LOC); Location* locPtr = world.get_loc(xLoc, yLoc); if( handle_power_nation_flag ) { int powerNationRecno=locPtr->power_nation_recno; if( powerNationRecno && !nation_passable[powerNationRecno] ) return 0; } return locPtr->can_move(mobile_type); }
//--------- Begin of function UnitMarine::unloading_unit ---------// // // <int> isAll - 1 for unload all the units // - otherwise 0 // <int> unitSeqId - if(isAll==0) unitSeqId+1 is the recno of the // selected unit in unit_recno_array[] // int UnitMarine::unloading_unit(int isAll, int unitSeqId) { if( !is_on_coast() ) return 0; //-------------------------------------------------------------------------// // return if no territory is nearby the ship //-------------------------------------------------------------------------// int curXLoc = next_x_loc(); // ship location int curYLoc = next_y_loc(); int unprocess = isAll ? unit_count : 1; Unit *unitPtr = isAll ? unit_array[unit_recno_array[unprocess-1]] : unit_array[unit_recno_array[unitSeqId]]; Location *locPtr; int xShift, yShift, checkXLoc, checkYLoc; int regionId = 0; // unload all the units in the same territory int found, i = 2; int sqtSize = 3, sqtArea = sqtSize*sqtSize; #ifdef DEBUG long debugCount = 0L; #endif if(isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. power.reset_selection(); while(unprocess) // using the calculated 'i' to reduce useless calculation { err_when(debugCount++ > 4*long(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC)); m.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift); checkXLoc = curXLoc+xShift; checkYLoc = curYLoc+yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) { i++; continue; } locPtr = world.get_loc(checkXLoc, checkYLoc); //-------------------------------------------------------------------------// // check for space to unload the unit //-------------------------------------------------------------------------// if(!regionId || locPtr->region_id == regionId) { if(locPtr->walkable()) found = 1; if(locPtr->can_move(UNIT_LAND))//unitPtr->mobile_type)) { regionId = locPtr->region_id; unitPtr->init_sprite(checkXLoc, checkYLoc); unitPtr->set_mode(0); if( isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. { unitPtr->selected_flag = 1; // mark selected if unload all unit_array.selected_count++; if( !unit_array.selected_recno ) unit_array.selected_recno = unitPtr->sprite_recno; } unprocess--; unit_count--; if(unprocess) unitPtr = unit_array[unit_recno_array[unprocess-1]]; // point to next unit else break; // finished, all have been unloaded } } //-------------------------------------------------------------------------// // stop checking if there is totally bouned by unacessible location //-------------------------------------------------------------------------// if(i==sqtArea) { if(found) { found = 0; // reset found sqtSize += 2; sqtArea = sqtSize*sqtSize; } else // no continuous location for the unit to unload, some units can't be unloaded return 0; } i++; } //-------- display info --------// if( nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. info.disp(); return 1; }
//--------- Begin of function Unit::ship_to_beach_path_edit ---------// // find a path to the beach // // <int&> resultXLoc - reference to return final x location the ship move to // <int&> resultYLoc - reference to return final y location the ship move to // <UCHAR> regionId - region id of the destination location // // return 1 if normal execution // return 0 if calling move_to() instead // int Unit::ship_to_beach_path_edit(int& resultXLoc, int& resultYLoc, UCHAR regionId) { int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); if(abs(curXLoc-resultXLoc)<=1 && abs(curYLoc-resultYLoc)<=1) return 1; //--------------- find a path to land area -------------------// UnitMarine *shipPtr = (UnitMarine*) this; int result = search(resultXLoc, resultYLoc, 1, SEARCH_MODE_TO_LAND_FOR_SHIP, regionId); if(!result) return 1; //----------- update cur location --------// curXLoc = next_x_loc(); curYLoc = next_y_loc(); err_when(shipPtr->extra_move_in_beach!=NO_EXTRA_MOVE); //------------------------------------------------------------------------------// // edit the result path to get a location for embarking //------------------------------------------------------------------------------// err_when(result_node_array==NULL && result_node_count); if(result_node_array && result_node_count) { err_when(result_node_count<2); ResultNode *curNodePtr = result_node_array; ResultNode *nextNodePtr = curNodePtr + 1; int moveScale = move_step_magn(); int nodeCount = result_node_count; Location *locPtr; int i, j, found, pathDist; int preXLoc, preYLoc; int checkXLoc = curXLoc; int checkYLoc = curYLoc; int hasMoveStep = 0; if(checkXLoc!=curNodePtr->node_x || checkYLoc!=curNodePtr->node_y) { err_when(abs(checkXLoc-curNodePtr->node_x)>moveScale || abs(checkYLoc-curNodePtr->node_y)>moveScale); hasMoveStep += moveScale; checkXLoc = curNodePtr->node_x; checkYLoc = curNodePtr->node_y; } //-----------------------------------------------------------------// // find the pair of points that one is in ocean and one in land //-----------------------------------------------------------------// err_when(terrain_res[world.get_loc(curNodePtr->node_x, curNodePtr->node_y)->terrain_id]->average_type!=TERRAIN_OCEAN); int vecX, vecY, xMagn, yMagn, magn; #ifdef DEBUG int debugLoop1=0, debugLoop2=0; #endif for(pathDist=0, found=0, i=1; i<nodeCount; ++i, curNodePtr++, nextNodePtr++) { #ifdef DEBUG err_when(++debugLoop1>10000); #endif vecX = nextNodePtr->node_x - curNodePtr->node_x; vecY = nextNodePtr->node_y - curNodePtr->node_y; magn = ((xMagn=abs(vecX)) > (yMagn=abs(vecY))) ? xMagn : yMagn; if(xMagn) { vecX /= xMagn; vecX *= moveScale; } if(yMagn) { vecY /= yMagn; vecY *= moveScale; } err_when(abs(vecX)>moveScale && abs(vecY)>moveScale); //------------- check each location bewteen editNode1 and editNode2 -------------// for(j=0; j<magn; j+=moveScale) { #ifdef DEBUG err_when(++debugLoop2>10000); #endif preXLoc = checkXLoc; preYLoc = checkYLoc; checkXLoc += vecX; checkYLoc += vecY; locPtr = world.get_loc(checkXLoc, checkYLoc); if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN) // found { found++; break; } } if(found) { //------------ a soln is found ---------------// if(!j) // end node should be curNodePtr pointed at { pathDist -= hasMoveStep; result_node_count = i; result_path_dist = pathDist; } else { nextNodePtr->node_x = checkXLoc; nextNodePtr->node_y = checkYLoc; if(i==1) // first editing { ResultNode *firstNodePtr = result_node_array; if(cur_x==firstNodePtr->node_x*ZOOM_LOC_WIDTH && cur_y==firstNodePtr->node_y*ZOOM_LOC_HEIGHT) { go_x = checkXLoc * ZOOM_LOC_WIDTH; go_y = checkYLoc * ZOOM_LOC_HEIGHT; } } pathDist += (j+moveScale); pathDist -= hasMoveStep; result_node_count = i+1; result_path_dist = pathDist; } move_to_x_loc = preXLoc; move_to_y_loc = preYLoc; locPtr = world.get_loc((preXLoc+checkXLoc)/2, (preYLoc+checkYLoc)/2); if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN) { resultXLoc = (preXLoc+checkXLoc)/2; resultYLoc = (preYLoc+checkYLoc)/2; } else { resultXLoc = checkXLoc; resultYLoc = checkYLoc; } break; } else pathDist += magn; } if(!found) { ResultNode *endNodePtr = result_node_array + result_node_count - 1; if(abs(endNodePtr->node_x-resultXLoc)>1 || abs(endNodePtr->node_y-resultYLoc)>1) { move_to(resultXLoc, resultYLoc, -1); return 0; } } } else { //------------- scan for the surrounding for a land location -----------// int xShift, yShift, checkXLoc, checkYLoc; Location *locPtr; for(int i=2; i<=9; ++i) { misc.cal_move_around_a_point(i, 3, 3, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(locPtr->region_id!=regionId) continue; if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && locPtr->can_move(UNIT_LAND)) { resultXLoc = checkXLoc; resultYLoc = checkYLoc; return 1; } } return 0; } return 1; }
//--------- Begin of function UnitB::set_next --------// // // set the next coordinates to move to // // <int> newNextX, newNextY - next coordinate to move to // <int> para - used to count the result_path_dist // <int> ignoreBlockCheck - whether ignore blocking check or not // int UnitB::set_next(int newNextX, int newNextY, int para, int ignoreBlockCheck) { static char callingCount=0; int curNextXLoc = next_x_loc(); int curNextYLoc = next_y_loc(); int newNextXLoc = newNextX >> ZOOM_X_SHIFT_COUNT; int newNextYLoc = newNextY >> ZOOM_Y_SHIFT_COUNT; //------begin Juliet 14/10-----// int tempEndX = newNextXLoc+obj_loc_width()-1; int tempEndY = newNextYLoc+obj_loc_height()-1; //------end Juliet 14/10-------// short w, h, x, y; callingCount++; // this function is being called, prevent recursive calling if(curNextXLoc!=newNextXLoc || curNextYLoc!=newNextYLoc) { if(!is_dir_correct()) { set_turn(); return 1; } } //----------- blocking check ---------// if( !ignoreBlockCheck ) { int isBlocked=0; for(h=0, y=newNextYLoc; h<loc_height && !isBlocked ; h++, y++) { for(w=0, x=newNextXLoc; w<loc_width; w++, x++) { Location* locPtr = world.get_loc(x,y); if( locPtr->can_move(mobile_type) ) continue; //--- this location is occupied by the unit itself ---// if( locPtr->unit_recno(mobile_type) == sprite_recno ) continue; isBlocked = 1; break; } } if( isBlocked ) { //----- if we have already reach the destination -----// int rangeX1, rangeY1, rangeX2, rangeY2; get_object_range(move_to_loc_x, move_to_loc_y, rangeX1, rangeY1, rangeX2, rangeY2); if( m.is_touch( rangeX1, rangeY1, rangeX2, rangeY2, newNextXLoc, newNextYLoc, newNextXLoc+loc_width-1, newNextYLoc+loc_height-1 ) ) { stop_move(); } else //------- otherwise wait ---------// { set_wait(); } callingCount--; return 0; } } //--------- set the sprite_recno in new locations -----------// for(h=0, y=curNextYLoc; h<loc_height; h++, y++) { for(w=0, x=curNextXLoc; w<loc_width; w++, x++) world.get_loc(x,y)->remove_unit(mobile_type); } for(h=0, y=newNextYLoc; h<loc_height; h++, y++) { for(w=0, x=newNextXLoc; w<loc_width; w++, x++) world.get_loc(x,y)->set_unit(sprite_recno,mobile_type); } //----- set the new next coordinate ------// next_x = newNextX; next_y = newNextY; callingCount--; if( steps_remaining > 0 ) // steps_remaining can be decreased to negative as set_next() is called when stopping a unit, which is an addition to the steps it is supposed to move steps_remaining--; // --------- explore map ---------// if( cast_to_Unit() ) cast_to_Unit()->explore_on_move(curNextXLoc, curNextYLoc, newNextXLoc, newNextYLoc ); return 1; }
//------------ Begin of function Unit::can_move2 -------------------// // // check a specific location can be walk, taking care that if that location is occupied // by a walking or waiting unit, that location will later on be freed. // // <int> locX - x-coordinate // <int> locY - y-coordinate // // return: <bool> - true if the location ccan be walked to // false otherwise // bool UnitB::can_move2(int locX, int locY) { Location* locPtr; int occRecno; Unit* unitPtr; int i, j; // ####### begin Gilbert 20/4 ########// // for(i=0; i<obj_loc_width(); i++) // { // for(j=0; j<obj_loc_height(); j++) // { // locPtr = world.get_loc(locX+i, locY+j); // if(locX+i>= MAX_WORLD_X_LOC || locX+i <0 || locY+j >= MAX_WORLD_Y_LOC || locY+j < 0 ) // return false; // else if(!locPtr->can_move(mobile_type)) // { // occRecno = locPtr->unit_recno(mobile_type); // if(!occRecno) //not a unit // return false; // else if(occRecno != sprite_recno) // { // unitPtr = unit_array[occRecno]; // if(unitPtr->cur_action == SPRITE_WAIT || unitPtr->cur_action == SPRITE_MOVE) // continue; // else // return false; // } // } // } // } if( locX < 0 || locY < 0 || locX+loc_width > MAX_WORLD_X_LOC || locY+loc_height > MAX_WORLD_Y_LOC ) return false; for(i=0; i<loc_width; i++) { for(j=0; j<loc_height; j++) { locPtr = world.get_loc(locX+i, locY+j); if(!locPtr->can_move(mobile_type)) { occRecno = locPtr->unit_recno(mobile_type); if(!occRecno) //not a unit return false; if(occRecno != sprite_recno) { unitPtr = unit_array[occRecno]; if(unitPtr->cur_action != SPRITE_WAIT && unitPtr->cur_action != SPRITE_MOVE) return false; } } } } // ####### end Gilbert 20/4 ########// return true; }
//------------ Begin of function Unit::can_move -------------------// // // check whether a specific location can go walk to // // <int> locX - x-coordinate // <int> locY - y-coordinate // // return: <bool> - return true if the lcoation can be walk // return false if the location cannot be walk bool UnitB::can_move(int locX, int locY) { Location* locPtr; int i, j; for(i=0; i<obj_loc_width(); i++) { for(j=0; j<obj_loc_height(); j++) { locPtr = world.get_loc(locX+i, locY+j); if(locX+i>= MAX_WORLD_X_LOC || locX+i <0 || locY+j >= MAX_WORLD_Y_LOC || locY+j < 0 || (!locPtr->can_move(obj_mobile_type()) && (locPtr->unit_recno(obj_mobile_type()) != sprite_recno))) return false; } } return true; }