示例#1
0
文件: ounitb.cpp 项目: mecirt/7k2
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;
	}
}
示例#2
0
文件: osprite2.cpp 项目: mecirt/7k2
//--------- Begin of function Sprite::sprite_move --------//
//
// <int> desX, desY   - the destination coordination
//
void Sprite::sprite_move(int desX, int desY)
{
	if( cur_action != SPRITE_MOVE )
	{
		cur_action = SPRITE_MOVE;
		cur_frame  = 1;
	}

	err_when(desX<0 || desY<0 || desX>=MAX_WORLD_X_LOC*LOCATE_WIDTH || desY>=MAX_WORLD_Y_LOC*LOCATE_HEIGHT);

#ifdef DEBUG	
	short vectorX=desX-next_x;
	short vectorY=desY-next_y;
	
	if(vectorX && vectorY)	// both are non-zero
	{
		err_if(abs(vectorX) != abs(vectorY))
			err_here();
	}
#endif

	go_x = desX;
	go_y = desY;

	//----------- determine the movement direction ---------//

	set_dir(cur_x, cur_y, go_x, go_y);

	//------ set the next tile to move towards -------//
/*
	next_x = cur_x;
	next_y = cur_y;
*/
	int stepMagn = move_step_magn();
	set_next(cur_x+stepMagn*move_x_pixel_array[final_dir], cur_y+stepMagn*move_y_pixel_array[final_dir], -stepMagn);

	err_when(cur_action==SPRITE_MOVE && (cur_x!=next_x || cur_y!=next_y) &&
				final_dir!=(check_dir1=get_dir(cur_x, cur_y, next_x, next_y)));
}
示例#3
0
文件: OUNITS.cpp 项目: Stummi/7kaa
//--------- 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;
}
示例#4
0
文件: OUNITHB.cpp 项目: brianV/7kaa
//------ Begin of function Unit::handle_blocked_move_s11 -------//
// both blocked and blocking are size 1
//
void Unit::handle_blocked_move_s11(Unit *unitPtr)
{
	err_when( world.get_unit_recno(next_x_loc(), next_y_loc(), mobile_type) != sprite_recno );
	err_when( world.get_unit_recno(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->mobile_type) != unitPtr->sprite_recno );
	err_when(cur_x!=next_x || cur_y!=next_y);

	int waitTerm;
	int moveStep = move_step_magn();

	switch(unitPtr->cur_action)
	{
		//------------------------------------------------------------------------------------//
		// handle blocked for units belonging to the same nation.  For those belonging to other
		// nations, wait for it moving to other locations or search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_WAIT: // the blocking unit is waiting
				err_when(unitPtr->go_x==unitPtr->cur_x && unitPtr->go_y==unitPtr->cur_y);
		
		case SPRITE_TURN:
				if(unitPtr->nation_recno==nation_recno)
					handle_blocked_wait(unitPtr); // check for cycle wait for our nation
				else if(waiting_term>=MAX_WAITING_TERM_DIFF)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall searching
					waiting_term = 0;
				}
				else // wait
					set_wait();
				return;

		//------------------------------------------------------------------------------------//
		// We know from the cur_action of the blocking unit it is moving to another locations,
		// the blocked unit wait for a number of terms or search again.
		//------------------------------------------------------------------------------------//
		case SPRITE_MOVE:
		case SPRITE_READY_TO_MOVE:
		case SPRITE_SHIP_EXTRA_MOVE:
				if(unit_id!=UNIT_CARAVAN && unitPtr->unit_id==UNIT_CARAVAN) // don't wait for caravans, and caravans don't wait for other units
				{
					search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
				}
				else
				{
					waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
					if(waiting_term>=waitTerm)
					{
						search_or_wait();
						waiting_term = 0;
					}
					else
						set_wait();
				}
				return;

		//------------------------------------------------------------------------------------//
		// handling blocked for idle unit
		//------------------------------------------------------------------------------------//
		case SPRITE_IDLE:
				err_when(unitPtr->result_node_array!=NULL);
				if(unitPtr->action_mode==ACTION_SHIP_TO_BEACH)
				{
					//----------------------------------------------------------------------//
					// the blocking unit is trying to move to beach, so wait a number of terms,
					// or call searching again
					//----------------------------------------------------------------------//
					if(abs(unitPtr->next_x_loc()-unitPtr->action_x_loc2)<=moveStep &&
						abs(unitPtr->next_y_loc()-unitPtr->action_y_loc2)<=moveStep &&
						terrain_res[world.get_loc(unitPtr->action_x_loc2, unitPtr->action_y_loc2)->terrain_id]->average_type
						!=TERRAIN_OCEAN)
					{
						if(action_mode2==ACTION_SHIP_TO_BEACH && action_x_loc2==unitPtr->action_x_loc2 &&
							action_y_loc2==unitPtr->action_y_loc2)
						{
							int tempX, tempY;
							ship_to_beach(action_x_loc2, action_y_loc2, tempX, tempY);
						}
						else
						{
							waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
							if(waiting_term>=waitTerm)
								stop2();
							else
								set_wait();
						}
						return;
					}
				}

				if(unitPtr->nation_recno==nation_recno) //-------- same nation
				{
					//------------------------------------------------------------------------------------//
					// units from our nation
					//------------------------------------------------------------------------------------//
					if(unitPtr->unit_group_id==unit_group_id)
					{
						//--------------- from the same group -----------------//
						if(way_point_count && !unitPtr->way_point_count)
						{
							//------------ reset way point --------------//
							stop2();
							reset_way_point_array();
						}
						else if((unitPtr->next_x_loc() != move_to_x_loc || unitPtr->next_y_loc() != move_to_y_loc) &&
							(unitPtr->cur_action==SPRITE_IDLE && unitPtr->action_mode2==ACTION_STOP))
							move_to_my_loc(unitPtr); // push the blocking unit and exchange their destination
						else if(unitPtr->action_mode == ACTION_SETTLE)
							set_wait(); // wait for the settler
						else if(waiting_term>MAX_WAITING_TERM_SAME)
						{
							//---------- stop if wait too long ----------//
							terminate_move();
							waiting_term = 0;
						}
						else
							set_wait();
					}
					else if(unitPtr->action_mode2==ACTION_STOP)
						handle_blocked_by_idle_unit(unitPtr);
					else if(way_point_count && !unitPtr->way_point_count)
					{
						stop2();
						reset_way_point_array();
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				else // different nation
				{
					//------------------------------------------------------------------------------------//
					// units from other nations
					//------------------------------------------------------------------------------------//
					if(unitPtr->next_x_loc() == move_to_x_loc && unitPtr->next_y_loc() == move_to_y_loc)
					{  
						terminate_move(); // destination occupied by other unit

						if(action_mode==ACTION_ATTACK_UNIT && unitPtr->nation_recno!=nation_recno && unitPtr->sprite_recno==action_para)
						{
							err_when(action_x_loc!=unitPtr->next_x_loc() || action_y_loc!=unitPtr->next_y_loc());
							err_when(action_mode2!=ACTION_ATTACK_UNIT && action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET &&
										action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);
							err_when(action_para2!=action_para);
							err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
							
							set_dir(next_x, next_y, unitPtr->next_x, unitPtr->next_y);
							if(is_dir_correct())
								attack_unit(action_para);
							else
								set_turn();
							cur_frame  = 1;
						}
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				return;

		//------------------------------------------------------------------------------------//
		// don't wait for attackers from other nations, search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_ATTACK:
				//----------------------------------------------------------------//
				// don't wait for other nation unit, call searching again
				//----------------------------------------------------------------//
				if(nation_recno!=unitPtr->nation_recno)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1);
					return;
				}

				//------------------------------------------------------------------------------------//
				// for attackers owned by our commander, handled blocked case by case as follows.
				//------------------------------------------------------------------------------------//
				switch(unitPtr->action_mode)
				{
					case ACTION_ATTACK_UNIT:
							if(action_para && !unit_array.is_deleted(action_para))
							{
								Unit *targetPtr = unit_array[action_para];
								handle_blocked_attack_unit(unitPtr, targetPtr);
							}
							else
								search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
							break;

					case ACTION_ATTACK_FIRM:
							if(!unitPtr->action_para || firm_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_firm(unitPtr);
							break;

					case ACTION_ATTACK_TOWN:
							if(!unitPtr->action_para || town_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_town(unitPtr);
							break;

					case ACTION_ATTACK_WALL:
							if(unitPtr->action_para)
								set_wait();
							else
								handle_blocked_attack_wall(unitPtr);
							break;

					case ACTION_GO_CAST_POWER:
							set_wait();
							break;

					default: err_here();
								break;
				}
				return;

		//------------------------------------------------------------------------------------//
		// the blocked unit can pass after the blocking unit disappears in air.
		//------------------------------------------------------------------------------------//
		case SPRITE_DIE:
				set_wait();	// assume this unit will not wait too long
				return;

		default:
				err_here();
				break;
	}
	
	err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
}
示例#5
0
文件: osprite2.cpp 项目: mecirt/7k2
void Sprite::process_move()
{
	#ifdef DEBUG
	int debugStepMagn1 = move_step_magn();
	err_when(abs(cur_x-next_x)>LOCATE_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>LOCATE_HEIGHT*debugStepMagn1);
	#endif

	//---- for some sprite (e.g. elephant), move one step per a few frames ----//

	if( --remain_frames_per_step > 0 )
		return;
	else
		remain_frames_per_step = sprite_info->frames_per_step;

	err_when(cur_x < 0 || cur_y < 0 || cur_x >= MAX_WORLD_X_LOC * LOCATE_WIDTH || cur_y >= MAX_WORLD_Y_LOC * LOCATE_HEIGHT);
	err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));

	//----- if the sprite has reach the destintion ----//

	if( cur_x==go_x && cur_y==go_y)
	{
		cur_action = SPRITE_IDLE;
		
		int rc = set_next(cur_x, cur_y);			//********* BUGHERE

		err_when( !rc );

#ifdef DEBUG
		char h, w, blocked=0;
		short x, y;

		for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
		{
			for(w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
				blocked = world.get_loc(x, y)->unit_recno(mobile_type) != sprite_recno;
		}
		err_if(blocked)
			err_here();
#endif
		cur_frame  = 1;
		return;
	}

	err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));

	//---- set the next tile the sprite will be moving towards ---//

	static short vector_x_array[] = {  0,  1, 1, 1, 0, -1, -1, -1 };	// default vectors, temporary only
	static short vector_y_array[] = { -1, -1, 0, 1, 1,  1,  0, -1 };

//	short stepX = sprite_info->speed;
//	short stepY = sprite_info->speed;
	short stepX, stepY;
	stepX = stepY = sprite_speed();

	if( final_dir & 1 )		// diagonal direction slower
	{
		if( stepX >=8  )
		{
			stepY = (stepX -= (unsigned)stepX /4 );			// slightly fast for unsigned division
		}
		else if( stepX >= 3 )
		{
			--stepX;
			--stepY;
		}
	}

	//------------------------------------------//

	if( next_x != go_x || next_y != go_y )		// if next_x==go_x & next_y==go_y, reach destination already, don't move further.
	{
		if( abs(cur_x-next_x) <= stepX && abs(cur_y-next_y) <= stepY )
		{
			int stepMagn = move_step_magn();

			if( !set_next(next_x+stepMagn*move_x_pixel_array[final_dir], next_y+stepMagn*move_y_pixel_array[final_dir], -stepMagn) )
				return;
		}
	}

	err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
	
	//---- if the is blocked, cur_action is changed to SPRITE_WAIT, return now ----//

	if( cur_action != SPRITE_MOVE )
		return;

	//-------------- update position -----------------//
	//
	// If it gets very close to the destination, fit it
	// to the destination ingoring the normal vector.
	//
	//------------------------------------------------//

	short vectorX = vector_x_array[final_dir] * stepX;	// cur_dir may be changed in the above set_next() call
	short vectorY = vector_y_array[final_dir] * stepY;

	if( abs(cur_x-go_x) <= stepX )
		cur_x = go_x;
	else
		cur_x += vectorX;

	if( abs(cur_y-go_y) <= stepY )
		cur_y = go_y;
	else
		cur_y += vectorY;

	err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));	// is a better checking if speed in all direction is equal
	#ifdef DEBUG
	int debugStepMagn2 = move_step_magn();
	err_when(abs(cur_x-next_x)>LOCATE_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>LOCATE_HEIGHT*debugStepMagn1);
	#endif

	//-------- check boundary ---------//

	err_when(cur_x < 0 || cur_y < 0 || cur_x >= MAX_WORLD_X_LOC * LOCATE_WIDTH || cur_y >= MAX_WORLD_Y_LOC * LOCATE_HEIGHT);

	//------- update frame id. --------//

	if( ++cur_frame > cur_sprite_move()->frame_count )
		cur_frame = 1;
}