void impasse(t_lidar *lidar) { int i; int count; static int stop = 0; i = 3; count = 0; while (i <= 34) { if (lidar->speed > 0.2) { if (i >= 14 && i <= 18) { if (my_getnbr(lidar->nbrs[i]) < 1050) count++; } else if (my_getnbr(lidar->nbrs[i]) < 1150) count++; } i++; } stop_move(lidar, count, &stop); }
//--------- Begin of function Unit::completed_order ---------// // // The current order is completed. // void Unit::completed_order() { stop_move(); // a UnitB function //----- if the order is initiated by an AI --// if( cur_order.ai_action_id && nation_recno ) nation_array[nation_recno]->action_finished(cur_order.ai_action_id, sprite_recno); cur_order.set(UNIT_STOP); }
//--------- Begin of function Unit::pop_order ---------// // // Note: the stack only has space for one Order object. // void Unit::pop_order() { stop_move(); // stop the current action first err_when( has_pushed_order() == 0 ); // cannot push when the only one stack space is used cur_order = pushed_order; pushed_order.set(-1); set_original_target(-1, -1); // clear the original target }
void UnitB::process_wait() { err_when(cur_action != SPRITE_WAIT); //move if the next tile is ready int stepMagn = move_step_magn(); if(can_move((cur_x+stepMagn*move_x_pixel_array[final_dir])/LOCATE_WIDTH, (cur_y+stepMagn*move_y_pixel_array[final_dir])/LOCATE_WIDTH)) { wait_state = 0; cur_action = SPRITE_MOVE; return; } else //find a new path if the thing occupying the next tile no longer move { /* int occUnitNum; Unit* occStuff; occUnitNum = checking_who_occupy_my_next_tile((cur_x+stepMagn*move_x_pixel_array[final_dir])/LOCATE_WIDTH, (cur_y+stepMagn*move_y_pixel_array[final_dir])/LOCATE_WIDTH); //##### begin trevor 21/1 #####// enum{ SEARCH_NEW_PATH_PROBABILITY = 10 }; if( (!occUnitNum || (occUnitNum && (occStuff=unit_array[occUnitNum]) && (occStuff->cur_action != SPRITE_MOVE && occStuff->cur_action != SPRITE_WAIT))) || (SEARCH_NEW_PATH_PROBABILITY > m.random(100) && sprite_speed() <= occStuff->sprite_speed() && !is_in_formation()) ) { wait_state = 0; move_to(move_to_loc_x, move_to_loc_y); // retry_state++; return; } //##### end trevor 21/1 #####//*/ } //find a new path if wait too long // ####### begin Gilbert 28/4 ########// if(wait_state++ > (retry_state <= MAX_UNIT_WAIT_STATE ? retry_state+MAX_UNIT_WAIT_STATE_FIRST : MAX_UNIT_WAIT_STATE) ) { wait_state = 0; int backupRetryState = retry_state; move_to(move_to_loc_x, move_to_loc_y); retry_state = backupRetryState + 1; // restore and increase } // ####### end Gilbert 28/4 ########// //if retrying too many times, stop move if(retry_state > MAX_RETRY_STATE) { stop_move(); retry_state = 0; } }
//---------- Begin of function UnitB::process_blocked -----// // // retry move to destination if the unit is blocked // void UnitB::process_blocked() { if(number_of_times_being_blocked++ > MAX_UNIT_BLOCKED_TIME || (next_x_loc() == move_to_loc_x && next_y_loc() == move_to_loc_y) || ((abs(move_to_loc_x - next_x_loc()) <= obj_loc_width()) && (abs(move_to_loc_y - next_y_loc()) <= obj_loc_height()) && !can_move(move_to_loc_x, move_to_loc_y) && !checking_who_occupy_the_place_i_want_to_go(move_to_loc_x, move_to_loc_y))) { set_no_longer_blocked(); stop_move(); } else move_to(move_to_loc_x, move_to_loc_y); }
//--------- Begin of function Unit::stop_order ---------// // // Stop the current order without completion. // void Unit::stop_order() { stop_move(); // a UnitB function //----- if the order is initiated by an AI --// if( cur_order.ai_action_id && nation_recno ) nation_array[nation_recno]->action_failure(cur_order.ai_action_id, sprite_recno); cur_order.set(UNIT_STOP); clear_pushed_order(); // clear pushed orders if there are any set_original_target(-1, -1); // clear the original target force_move_flag = false; }
//--------- Begin of function Unit::push_order ---------// // // Note: the stack only has space for one Order object. // void Unit::push_order() { err_when( has_pushed_order() > 0 ); // cannot push when the only one stack space is used pushed_order = cur_order; // ##### begin Gilbert 31/5 ########// // if the unit is stopped, store current location, used when resuming the action if( pushed_order.mode == UNIT_STOP ) { pushed_order.set(UNIT_STOP, -2, next_x_loc(), next_y_loc() ); // para = -2; to identify resume move, see execute_attack } // ##### end Gilbert 31/5 ########/ cur_order.set(UNIT_STOP); stop_move(); }
//--------- Begin of function Unit::stop_cur_order ---------// // // Stop the current order without completion. // void Unit::stop_cur_order() { stop_move(); cur_order.set(UNIT_STOP); }
//--------- Begin of function UnitB::move_to ---------// // // Move a unit to a specified location // // <int> destXLoc - the x-coordinate of the destination // <int> destYLoc - the y-coordinate of the destination // <bool> raiseDest - default is true, if not want to raise destination, false // void UnitB::move_to(int destXLoc, int destYLoc, bool raiseDest) { // ###### begin Gilbert 22/3 #######// // other people may ask this unit to move away while it is dead if( hit_points <= 0 || cur_action == SPRITE_DIE ) return; // ###### end Gilbert 22/3 #######// // err_when(destXLoc < 0 || destXLoc >= MAX_WORLD_X_LOC || destYLoc < 0 || destYLoc >= MAX_WORLD_Y_LOC); destXLoc = min(destXLoc, MAX_WORLD_X_LOC-1); destXLoc = max(destXLoc, 0); destYLoc = min(destYLoc, MAX_WORLD_Y_LOC-1); destYLoc = max(destYLoc, 0); stop_move(); //--- save the destination for later possible retries in searching when it is blocked ----// move_to_loc_x = destXLoc; move_to_loc_y = destYLoc; if((destXLoc == next_x_loc()) && (destYLoc == next_y_loc())) return; //------- search the path ---------// //#ifdef DEBUG // unsigned long pathFinderStartTime = m.get_time(); //#endif path_finder.set_attribute(loc_width, loc_height, mobile_type, 0); // ###### begin Gilbert 31/5 #######// err_when( cur_order.mode == UNIT_ATTACK && !cast_to_Unit() ); int stopAtRange = cur_order.mode == UNIT_ATTACK ? cast_to_Unit()->attack_range()-1 : 0; // subtract one attack_range so close attack can search near the target // and range attack search a little closer // ###### end Gilbert 31/5 #######// //----- code for handle nation power option -----// bool handlePowerNationFlag = false; path_finder.set_handle_power_nation(0); if( nation_recno ) { Nation *nationPtr = nation_array[nation_recno]; int srcLocPowerNation = world.get_loc(next_x_loc(), next_y_loc())->power_nation_recno; int destLocPowerNation = world.get_loc(destXLoc, destYLoc)->power_nation_recno; //--- only if unit stands on a passable location and the destination is passable, we handle power nation ---// if( (!srcLocPowerNation || nationPtr->get_relation_passable(srcLocPowerNation)) && (!destLocPowerNation || nationPtr->get_relation_passable(destLocPowerNation)) ) { path_finder.set_handle_power_nation(1, nationPtr->relation_passable_array ); handlePowerNationFlag = true; } } //--------- find the path now ---------// int rangeX1, rangeY1, rangeX2, rangeY2; get_object_range(destXLoc, destYLoc, rangeX1, rangeY1, rangeX2, rangeY2); // ######## begin Gilbert 31/5 ##########// path_finder.find_path(next_x_loc(), next_y_loc(), destXLoc, destYLoc, rangeX1, rangeY1, rangeX2, rangeY2, 1, raiseDest, 0, stopAtRange ); // ######## end Gilbert 31/5 ##########// if( path_finder.is_path_found() ) { set_no_longer_blocked(); seek_path_fail_count=0; // reset the failure counter } else //---- path searching failed ----// { if(!is_blocked()) set_not_seriously_blocked(); //--- if the path search failed, increase the failure counter ---// // if( seek_path_fail_count < 100 ) // prevent numeric overflow // seek_path_fail_count++; } //-----------------------------------------// int pathNodeCount; int totalSteps; // total number of steps to walk through the whole path. if( cur_path ) mem_del( cur_path ); cur_path = path_finder.retrieve(pathNodeCount, totalSteps); // retrieves the path // ###### begin Gilbert 11/5 #########// if( cur_path ) { cur_path_result_id = pathNodeCount; // start with the last node steps_remaining = totalSteps; } else { cur_path_result_id = 0; steps_remaining = 0; } // ###### end Gilbert 11/5 #########// //#ifdef DEBUG // // ######## begin Gilbert 27/4 #######// // pathFinderStartTime = m.get_time() - pathFinderStartTime; // pathfind_profile_time += pathFinderStartTime; // pathfind_count++; // if( pathFinderStartTime > longest_pathfind_profile_time ) // { // longest_pathfind_profile_time = pathFinderStartTime; // longest_pathfind_unit_recno = sprite_recno; // } // // ######## begin Gilbert 27/4 #######// //#endif if(!cur_path) { if(handlePowerNationFlag) { // ##### begin Gilber 27/4 ########// //#ifdef DEBUG // unsigned long pathFinderStartTime = m.get_time(); // pathFinderStartTime = m.get_time(); //#endif // ##### end Gilber 27/4 ########// // ###### begin Gilbert 12/5 ########// // path_finder.set_attribute(loc_width, loc_height, mobile_type, PFIND_IGNORE_UNIT ); // ###### end Gilbert 12/5 ########// path_finder.set_handle_power_nation(0); handlePowerNationFlag = false; // ######## begin Gilbert 31/5 ##########// path_finder.find_path(next_x_loc(), next_y_loc(), destXLoc, destYLoc, rangeX1, rangeY1, rangeX2, rangeY2, 1, raiseDest, 0, stopAtRange ); // ######## end Gilbert 31/5 ##########// if( path_finder.is_path_found() ) { set_no_longer_blocked(); seek_path_fail_count=0; // reset the failure counter } else //---- path searching failed ----// { if(!is_blocked()) set_not_seriously_blocked(); } if( cur_path ) mem_del( cur_path ); cur_path = path_finder.retrieve(pathNodeCount, totalSteps); // retrieves the path // ###### begin Gilbert 11/5 #########// if( cur_path ) { cur_path_result_id = pathNodeCount; // start with the last node steps_remaining = totalSteps; } else { cur_path_result_id = 0; steps_remaining = 0; } // ###### end Gilbert 11/5 #########// //#ifdef DEBUG // // ######## begin Gilbert 27/4 #######// // pathFinderStartTime = m.get_time() - pathFinderStartTime; // pathfind_profile_time += pathFinderStartTime; // pathfind_count++; // if( pathFinderStartTime > longest_pathfind_profile_time ) // { // longest_pathfind_profile_time = pathFinderStartTime; // longest_pathfind_unit_recno = sprite_recno; // } // // ######## begin Gilbert 27/4 #######// //#endif if(!cur_path) { if(!handle_blocking()) set_no_longer_blocked(); if(seek_path_fail_count <= 100*SEEK_PATH_FAIL_INCREMENT) seek_path_fail_count+=SEEK_PATH_FAIL_INCREMENT; // 10 is the single increment unit. It will be reduce by 1 each time in Unit::attack() } } else { if(!handle_blocking()) set_no_longer_blocked(); if(seek_path_fail_count <= 100*SEEK_PATH_FAIL_INCREMENT) seek_path_fail_count+=SEEK_PATH_FAIL_INCREMENT; } } //--------- start the first move ---------// if( cur_path && cur_action != SPRITE_MOVE ) // if it is previously moving, don't call next_move() as it has still yet to finish its remaining pixel move to snap to grids { cur_action = SPRITE_MOVE; cur_frame = 1; retry_state = 0; } else { // ###### begin Gilbert 15/5 #########// if( cur_x == next_x && cur_y == next_y ) { wait_count = 0; set_wait(); } // ###### end Gilbert 15/5 #########// } }
//--------- 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::handle_blocking-------------// // //This function function handles blocking situation // return type <bool> - return true if handle successfully // return false if handle unsuccessfully bool UnitB::handle_blocking() { //---------Defining and initializing local variables-----------// int occupyingUnitRecordNumber; Unit* theOccupyingObject=NULL; int occLocX, occLocY; int theMoveToPlaceX, theMoveToPlaceY; bool handleSuccessfully=false; int is, js; //--------------------------------------------------------------// //setting the unit himself as not occupying the tile, otherwise it will found out that //he himself occupying the tile int lX = next_x_loc(); int lY = next_y_loc(); for(is = 0; is<obj_loc_width(); is++) for(js=0; js<obj_loc_height(); js++) world.get_loc(lX+is, lY+js)->remove_unit(mobile_type); //some local variables for use int checkingLocX=lX; int checkingLocY=lY; int directionX=0, directionY=0; int directionAngle; int destX = move_to_loc_x; int destY = move_to_loc_y; //would like to check first the direction of the destination, it makes more sense int diffX = destX-lX; int diffY = destY-lY; int stepSizeX=0, stepSizeY=0; if(diffX >= 0) { if(diffY<=0) { if(diffY >= -diffX) { checkingLocX++; directionX=1; } else { checkingLocY--; directionY=-1; } } else { if(diffY <= diffX) { checkingLocX++; directionX=1; } else { checkingLocY++; directionY =1; } } } else { if(diffY<=0) { if(diffY <= diffX) { checkingLocX--; directionX = -1; } else { checkingLocY--; directionY = -1; } } else { if(diffY <= -diffX) { checkingLocX--; directionX = -1; } else { checkingLocY++; directionY = 1; } } } if(!diffX && !diffY) { lX = next_x_loc(); lY = next_y_loc(); for(is = 0; is< obj_loc_width(); is++) for(js=0; js<obj_loc_height(); js++) world.get_loc(lX+is, lY+js)->set_unit(sprite_recno, mobile_type); return false; } directionAngle = m.angle_lookup(directionX, directionY); int firstTimeAngle = directionAngle; //loop over all the directiion of the blocked unit while(!handleSuccessfully && directionAngle < (firstTimeAngle+360)) { occupyingUnitRecordNumber = checking_who_occupy_the_place_i_want_to_go(checkingLocX, checkingLocY); if(occupyingUnitRecordNumber) theOccupyingObject = unit_array[occupyingUnitRecordNumber]; else theOccupyingObject = NULL; //do it only when it is of the same nationality and is a unit and is not a troop //let the blocking unit to move to the direction of the blocked unit want to go to if(theOccupyingObject && theOccupyingObject->nation_recno == nation_recno) { stepSizeX = obj_loc_width(); stepSizeY = obj_loc_height(); occLocX = theOccupyingObject->next_x_loc(); occLocY = theOccupyingObject->next_y_loc(); stepSizeX *= directionX; stepSizeY *= directionY; theMoveToPlaceX = occLocX+stepSizeX; theMoveToPlaceY = occLocY+stepSizeY; Location* locPtr = world.get_loc(theMoveToPlaceX, theMoveToPlaceY); //if the blocking unit successfully walk away, the blocked unit can then try to find a new path to the destination if( theOccupyingObject->can_move(theMoveToPlaceX, theMoveToPlaceY) || theOccupyingObject->checking_who_occupy_the_place_i_want_to_go(theMoveToPlaceX, theMoveToPlaceY)) { theOccupyingObject->move_to(theMoveToPlaceX, theMoveToPlaceY, false); if(theOccupyingObject->cur_action == SPRITE_MOVE || theOccupyingObject->cur_action == SPRITE_WAIT) { stop_move(); set_first_time_blocked(); handleSuccessfully = true; } } } directionAngle+=45; m.xy_lookup(directionAngle, directionX, directionY); checkingLocX = lX+directionX; checkingLocY = lY+directionY; } //set back the unit to occupy the tile after handling blocking. lX = next_x_loc(); lY = next_y_loc(); for(is = 0; is< obj_loc_width(); is++) for(js=0; js<obj_loc_height(); js++) world.get_loc(lX+is, lY+js)->set_unit(sprite_recno, mobile_type); return handleSuccessfully; }