//--------- Begin of function UnitB::get_object_range ---------// // // Get the full range of the area occupied by the object. // // <int> objXLoc, objYLoc - the location of the object // <int&> rangeX1, rangeY1, rangeX2, rangeY2 - vars for returning the range // void UnitB::get_object_range(int objXLoc, int objYLoc, int &rangeX1, int &rangeY1, int &rangeX2, int &rangeY2) { Location* locPtr; if(can_move(objXLoc, objYLoc)) { rangeX1 = objXLoc; rangeY1 = objYLoc; rangeX2 = objXLoc + loc_width - 1; rangeY2 = objYLoc + loc_height - 1; return; } //---------------------------------------// int* objLocFlag = (int*) mem_add_clear(loc_width*loc_height*sizeof(int)); int* objCargoRecno = (int*) mem_add_clear(loc_width*loc_height*sizeof(int)); int is, js; is = 0; int ind = 0; while(is<obj_loc_width()) { js = 0; while(js < obj_loc_height()) { locPtr = world.get_loc(objXLoc+is, objYLoc+js); ind = is*loc_height+js; if(mobile_type == UNIT_AIR) objCargoRecno[ind] = locPtr->air_cargo_recno; else objCargoRecno[ind] = locPtr->cargo_recno; objLocFlag[ind] = locPtr->loc_flag; if(!objLocFlag[ind] && objCargoRecno[ind] == sprite_recno) //it is myself objCargoRecno[ind] = 0; js++; } is++; } #ifdef DEBUG int checkCargo = 0; int checkFlag = 0; int index = 0; while(!checkCargo && !checkFlag && index < (loc_width*loc_height)) { checkCargo = objCargoRecno[index]; checkFlag = objLocFlag[index]; index++; } err_when(!checkCargo && !checkFlag); #endif //------ scan up -------// if(loc_width == 1 && loc_height == 1) { for( rangeY1=((objYLoc>=1)?(objYLoc-1):0) ; rangeY1>=0 ; rangeY1-- ) { if((world.get_loc(objXLoc, rangeY1)->loc_flag) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, rangeY1)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(objXLoc, rangeY1)->cargo_recno != objCargoRecno[0]))) { rangeY1++; // go back to the last one which is valid break; } } //------ scan down -------// for( rangeY2=((objYLoc<MAX_WORLD_Y_LOC-1)?(objYLoc+1):(MAX_WORLD_Y_LOC-1)) ; rangeY2<MAX_WORLD_Y_LOC ; rangeY2++ ) { if((world.get_loc(objXLoc, rangeY2)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, rangeY2)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(objXLoc, rangeY2)->cargo_recno != objCargoRecno[0]))) { rangeY2--; // go back to the last one which is valid break; } } //------ scan left -------// for( rangeX1=((objXLoc>=1)?(objXLoc-1):0) ; rangeX1>=0 ; rangeX1-- ) { if((world.get_loc(rangeX1, objYLoc)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(rangeX1, objYLoc)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(rangeX1, objYLoc)->cargo_recno != objCargoRecno[0]))) { rangeX1++; // go back to the last one which is valid break; } } //------ scan right -------// for( rangeX2=((objXLoc<MAX_WORLD_X_LOC-1)?(objXLoc+1):(MAX_WORLD_X_LOC-1)) ; rangeX2<MAX_WORLD_X_LOC ; rangeX2++ ) { if((world.get_loc(rangeX2, objYLoc)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(rangeX2, objYLoc)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(rangeX2, objYLoc)->cargo_recno != objCargoRecno[0]))) { rangeX2--; // go back to the last one which is valid break; } } } else //2 x 2 BUGHERE: only for 2x2 but not for other size other than 2x2 and 1x1 ( 3x3 may not work) { //it is very hard coded ! //scan up// if(objCargoRecno[0] == objCargoRecno[(loc_width-1)*loc_height] && objLocFlag[0] == objLocFlag[(loc_width-1)*loc_height]) { if(objCargoRecno[0] && (objLocFlag[0] & LOCATE_BLOCK_MASK)) { for(rangeY1=((objYLoc>=1)?(objYLoc-1):0); rangeY1 >= 0; rangeY1--) { if((world.get_loc(objXLoc, rangeY1)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, rangeY1)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(objXLoc, rangeY1)->cargo_recno != objCargoRecno[0]))) { rangeY1++; break; } } } else rangeY1 = objYLoc; } else { int tmpRangeY1, tmpRangeY2; if(objCargoRecno[0] && (objLocFlag[0] & LOCATE_BLOCK_MASK)) { for(tmpRangeY1=((objYLoc>=1)?(objYLoc-1):0); tmpRangeY1 >= 0; tmpRangeY1--) { if((world.get_loc(objXLoc, tmpRangeY1)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, tmpRangeY1)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(objXLoc, tmpRangeY1)->cargo_recno != objCargoRecno[0]))) { tmpRangeY1++; break; } } } else tmpRangeY1 = objYLoc; if(objCargoRecno[(loc_width-1)*loc_height] && (objLocFlag[(loc_width-1)*loc_height] & LOCATE_BLOCK_MASK)) { for(tmpRangeY2=((objYLoc>=1)?(objYLoc-1):0); tmpRangeY2 >= 0; tmpRangeY2--) { if((world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->loc_flag ) != objLocFlag[(loc_width-1)*loc_height] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->air_cargo_recno != objCargoRecno[(loc_width-1)*loc_height]) : (world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->cargo_recno != objCargoRecno[(loc_width-1)*loc_height]))) { tmpRangeY2++; break; } } } else tmpRangeY2 = objYLoc; rangeY1 = min(tmpRangeY1, tmpRangeY2); } //scan down// if(objCargoRecno[loc_height-1] == objCargoRecno[loc_width*loc_height-1] && objLocFlag[loc_height-1] == objLocFlag[loc_width*loc_height-1]) { if(objCargoRecno[loc_height-1] && (objLocFlag[loc_height-1] & LOCATE_BLOCK_MASK)) { for(rangeY2=((objYLoc+loc_height<MAX_WORLD_Y_LOC)?objYLoc+loc_height:MAX_WORLD_Y_LOC-1); rangeY2<MAX_WORLD_Y_LOC; rangeY2++) { if((world.get_loc(objXLoc, rangeY2)->loc_flag ) != objLocFlag[loc_height-1] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, rangeY2)->air_cargo_recno != objCargoRecno[loc_height-1]) : (world.get_loc(objXLoc, rangeY2)->cargo_recno != objCargoRecno[loc_height-1]))) { rangeY2--; break; } } } else rangeY2 = objYLoc+loc_height-1; } else { int tmpRangeY1, tmpRangeY2; if(objCargoRecno[loc_height-1] && (objLocFlag[loc_height-1] & LOCATE_BLOCK_MASK)) { for(tmpRangeY1=((objYLoc+loc_height<MAX_WORLD_Y_LOC)?objYLoc+loc_height:MAX_WORLD_Y_LOC-1); tmpRangeY1<MAX_WORLD_Y_LOC; tmpRangeY1++) { if((world.get_loc(objXLoc, tmpRangeY1)->loc_flag ) != objLocFlag[loc_height-1] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc, tmpRangeY1)->air_cargo_recno != objCargoRecno[loc_height-1]) : (world.get_loc(objXLoc, tmpRangeY1)->cargo_recno != objCargoRecno[loc_height-1]))) { tmpRangeY1--; break; } } } else tmpRangeY1 = objYLoc+loc_height-1; if(objCargoRecno[loc_width*loc_height-1] && (objLocFlag[loc_width*loc_height-1] & LOCATE_BLOCK_MASK)) { for(tmpRangeY2=((objYLoc+loc_height<MAX_WORLD_Y_LOC)?objYLoc+loc_height:MAX_WORLD_Y_LOC-1); tmpRangeY2<MAX_WORLD_Y_LOC; tmpRangeY2++) { if((world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->loc_flag ) != objLocFlag[loc_width*loc_height-1] || (mobile_type == UNIT_AIR ? (world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->air_cargo_recno != objCargoRecno[loc_width*loc_height-1]) : (world.get_loc(objXLoc+loc_width-1, tmpRangeY2)->cargo_recno != objCargoRecno[loc_width*loc_height-1]))) { tmpRangeY2--; break; } } } else tmpRangeY2 = objYLoc+loc_height-1; rangeY2 = max(tmpRangeY1, tmpRangeY2); } //scan left// if(objCargoRecno[0] == objCargoRecno[loc_height-1] && objLocFlag[0] == objLocFlag[loc_height-1]) { if(objCargoRecno[0] && (objLocFlag[0] & LOCATE_BLOCK_MASK)) { for(rangeX1=((objXLoc>=1)?(objXLoc-1):0); rangeX1 >= 0; rangeX1--) { if((world.get_loc(rangeX1, objYLoc)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(rangeX1, objYLoc)->air_cargo_recno != objCargoRecno[0]) : (world.get_loc(rangeX1, objYLoc)->cargo_recno != objCargoRecno[0]))) { rangeX1++; break; } } } else rangeX1 = objXLoc; } else { int tmpRangeX1, tmpRangeX2; if(objCargoRecno[0] && (objLocFlag[0] & LOCATE_BLOCK_MASK)) { for(tmpRangeX1=((objXLoc>=1)?(objXLoc-1):0); tmpRangeX1>=0; tmpRangeX1--) { if((world.get_loc(tmpRangeX1, objYLoc)->loc_flag ) != objLocFlag[0] || (mobile_type == UNIT_AIR ? (world.get_loc(tmpRangeX1, objYLoc)->air_cargo_recno != objCargoRecno[0]): (world.get_loc(tmpRangeX1, objYLoc)->cargo_recno != objCargoRecno[0]))) { tmpRangeX1++; break; } } } else tmpRangeX1 = objXLoc; if(objCargoRecno[loc_height-1] && (objLocFlag[loc_height-1] & LOCATE_BLOCK_MASK)) { for(tmpRangeX2=((objXLoc>=1)?(objXLoc-1):0); tmpRangeX2>=0; tmpRangeX2--) { if((world.get_loc(tmpRangeX2, objYLoc+loc_height-1)->loc_flag ) != objLocFlag[loc_height-1] || (mobile_type == UNIT_AIR ? (world.get_loc(tmpRangeX2, objYLoc+loc_height-1)->air_cargo_recno != objCargoRecno[loc_height-1]):(world.get_loc(tmpRangeX2, objYLoc+loc_height-1)->cargo_recno != objCargoRecno[loc_height-1]))) { tmpRangeX2++; break; } } } else tmpRangeX2 = objXLoc; rangeX1 = min(tmpRangeX1, tmpRangeX2); } //scan right// if(objCargoRecno[(loc_width-1)*loc_height] == objCargoRecno[loc_width*loc_height-1] && objLocFlag[(loc_width-1)*loc_height] == objLocFlag[loc_width*loc_height-1]) { if(objCargoRecno[(loc_width-1)*loc_height] && (objLocFlag[(loc_width-1)*loc_height] & LOCATE_BLOCK_MASK)) { for(rangeX2=((objXLoc+loc_width<MAX_WORLD_X_LOC)?objXLoc+loc_width:MAX_WORLD_X_LOC-1); rangeX2<MAX_WORLD_X_LOC; rangeX2++) { if((world.get_loc(rangeX2, objYLoc)->loc_flag ) != objLocFlag[(loc_width-1)*loc_height] || (mobile_type == UNIT_AIR ? (world.get_loc(rangeX2, objYLoc)->air_cargo_recno != objCargoRecno[(loc_width-1)*loc_height]):(world.get_loc(rangeX2, objYLoc)->cargo_recno != objCargoRecno[(loc_width-1)*loc_height]))) { rangeX2--; break; } } } else rangeX2 = objXLoc+loc_width-1; } else { int tmpRangeX1, tmpRangeX2; if(objCargoRecno[(loc_width-1)*loc_height] && (objLocFlag[(loc_width-1)*loc_height] & LOCATE_BLOCK_MASK)) { for(tmpRangeX1 = ((objXLoc+loc_width<MAX_WORLD_X_LOC)?objXLoc+loc_width:MAX_WORLD_X_LOC-1); tmpRangeX1<MAX_WORLD_X_LOC; tmpRangeX1++) { if((world.get_loc(tmpRangeX1, objYLoc)->loc_flag ) != objLocFlag[(loc_width-1)*loc_height] || (mobile_type == UNIT_AIR ? (world.get_loc(tmpRangeX1, objYLoc)->air_cargo_recno != objCargoRecno[(loc_width-1)*loc_height]):(world.get_loc(tmpRangeX1, objYLoc)->cargo_recno != objCargoRecno[(loc_width-1)*loc_height]))) { tmpRangeX1--; break; } } } else tmpRangeX1 = objXLoc+loc_width-1; if(objCargoRecno[loc_width*loc_height-1] && (objLocFlag[loc_width*loc_height-1] & LOCATE_BLOCK_MASK)) { for(tmpRangeX2 = ((objXLoc+loc_width<MAX_WORLD_X_LOC)?objXLoc+loc_width:MAX_WORLD_X_LOC-1); tmpRangeX2<MAX_WORLD_X_LOC; tmpRangeX2++) { if((world.get_loc(tmpRangeX2, objYLoc+loc_height-1)->loc_flag ) != objLocFlag[loc_width*loc_height-1] || world.get_loc(tmpRangeX2, objYLoc+loc_height-1)->cargo_recno != objCargoRecno[loc_width*loc_height-1]) { tmpRangeX2--; break; } } } else tmpRangeX2 = objXLoc+loc_width-1; rangeX2 = max(tmpRangeX1, tmpRangeX2); } } rangeX1=max(rangeX1, 0); rangeY1=max(rangeY1, 0); rangeX2=min(rangeX2, MAX_WORLD_X_LOC-1); rangeY2=min(rangeY2, MAX_WORLD_Y_LOC-1); err_when((rangeX2-rangeX1+1) > 30); err_when((rangeY2-rangeY1+1) > 30); mem_del(objLocFlag); mem_del(objCargoRecno); }
//------------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; }
//--------- 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; }