Esempio n. 1
0
//--------- Begin of function Unit::handle_blocked_attack_wall ---------//
// handle the case that the way of this unit to the target wall is blocked by
// another unit
//
// <Unit*> unitPtr	- the blocking unit
//
void Unit::handle_blocked_attack_wall(Unit *unitPtr)
{
	if(action_x_loc==unitPtr->action_x_loc && action_y_loc==unitPtr->action_y_loc && action_mode==unitPtr->action_mode)
	{
		//------------- both attacks the same wall ------------//
		Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
		if(!locPtr->is_wall())
			stop2(KEEP_DEFENSE_MODE);	// stop since wall is deleted
		else if(space_for_attack(action_x_loc, action_y_loc, UNIT_LAND, 1, 1))
		{
			//------------ found surrounding place to attack the wall -------------//
			if(mobile_type==UNIT_LAND)
				set_move_to_surround(action_x_loc, action_y_loc, 1, 1, BUILDING_TYPE_WALL); // search for a unit only, not for a group
			else
				attack_wall(action_x_loc, action_y_loc);
		}
		else // no surrounding place found, stop now
			stop(KEEP_PRESERVE_ACTION); // no space available, so stop to wait for space to attack the wall
	}
	else
	{
		if(action_x_loc==-1 || action_y_loc==-1)
			stop();
		else
			set_wait();
	}
}
Esempio n. 2
0
//------ Begin of function Unit::handle_blocked_same_target_attack ---------//
// the target of the blocked unit and this unit are same
//
// <Unit*>	unitPtr		-	pointer to blocking uit
// <Unit*>	targetPtr	-	pointer to target unit
//
void Unit::handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr)
{
	//----------------------------------------------------------//
	// this unit is now waiting and the unit pointed by unitPtr
	// is attacking the unit pointed by targetPtr
	//----------------------------------------------------------//
	err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
	err_when(cur_x!=next_x || cur_y!=next_y);
	err_when(cur_x==go_x && cur_y==go_y);

	if(space_for_attack(action_x_loc, action_y_loc, targetPtr->mobile_type, targetPtr->sprite_info->loc_width, targetPtr->sprite_info->loc_height))
	{
		err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
		search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
		//search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
	}
	else if(in_any_defense_mode())
	{
		err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET &&
					action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);

		general_defend_mode_detect_target();
	}
	else if(m.points_distance(next_x_loc(), next_y_loc(), action_x_loc, action_y_loc)<ATTACK_DETECT_DISTANCE)
	{
		//------------------------------------------------------------------------//
		// if the target is within the detect range, stop the unit's action to detect
		// another target if any exist. In case, there is no other target, the unit
		// will still attack the original target since it is the only target in the
		// detect range
		//------------------------------------------------------------------------//
		stop2(KEEP_DEFENSE_MODE);
	}
	else
		set_wait(); // set wait to stop the movement
}
Esempio n. 3
0
/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
  yyParser *yypParser,         /* The parser */
  int yyruleno                 /* Number of the rule by which to reduce */
){
  int yygoto;                     /* The next state */
  int yyact;                      /* The next action */
  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
  yyStackEntry *yymsp;            /* The top of the parser's stack */
  int yysize;                     /* Amount to pop the stack */
  ParseARG_FETCH;
  yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
  if( yyTraceFILE && yyruleno>=0 
        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
      yyRuleName[yyruleno]);
  }
#endif /* NDEBUG */

  /* Silence complaints from purify about yygotominor being uninitialized
  ** in some cases when it is copied into the stack after the following
  ** switch.  yygotominor is uninitialized when a rule reduces that does
  ** not set the value of its left-hand side nonterminal.  Leaving the
  ** value of the nonterminal uninitialized is utterly harmless as long
  ** as the value is never used.  So really the only thing this code
  ** accomplishes is to quieten purify.  
  **
  ** 2007-01-16:  The wireshark project (www.wireshark.org) reports that
  ** without this code, their parser segfaults.  I'm not sure what there
  ** parser is doing to make this happen.  This is the second bug report
  ** from wireshark this week.  Clearly they are stressing Lemon in ways
  ** that it has not been previously stressed...  (SQLite ticket #2172)
  */
  /*memset(&yygotominor, 0, sizeof(yygotominor));*/
  yygotominor = yyzerominor;


  switch( yyruleno ){
  /* Beginning here are the reduction cases.  A typical example
  ** follows:
  **   case 0:
  **  #line <lineno> <grammarfile>
  **     { ... }           // User supplied code
  **  #line <lineno> <thisfile>
  **     break;
  */
      case 4: /* decl ::= REPORT TO STR */
#line 22 "cfg.y"
{set_report(ps,yymsp[0].minor.yy0);}
#line 739 "cfg.c"
        break;
      case 5: /* decl ::= LISTEN ON STR */
#line 23 "cfg.y"
{set_listen(ps,yymsp[0].minor.yy0);}
#line 744 "cfg.c"
        break;
      case 6: /* job ::= JOB LCURLY sbody RCURLY */
#line 24 "cfg.y"
{push_job(ps);}
#line 749 "cfg.c"
        break;
      case 9: /* kv ::= NAME STR */
#line 27 "cfg.y"
{set_name(ps,yymsp[0].minor.yy0);}
#line 754 "cfg.c"
        break;
      case 11: /* kv ::= DIR path */
#line 29 "cfg.y"
{set_dir(ps,yymsp[0].minor.yy0);}
#line 759 "cfg.c"
        break;
      case 12: /* kv ::= OUT path */
#line 30 "cfg.y"
{set_out(ps,yymsp[0].minor.yy0);}
#line 764 "cfg.c"
        break;
      case 13: /* kv ::= IN path */
#line 31 "cfg.y"
{set_in(ps,yymsp[0].minor.yy0);}
#line 769 "cfg.c"
        break;
      case 14: /* kv ::= ERR path */
#line 32 "cfg.y"
{set_err(ps,yymsp[0].minor.yy0);}
#line 774 "cfg.c"
        break;
      case 15: /* kv ::= USER STR */
#line 33 "cfg.y"
{set_user(ps,yymsp[0].minor.yy0);}
#line 779 "cfg.c"
        break;
      case 16: /* kv ::= ORDER STR */
#line 34 "cfg.y"
{set_ord(ps,yymsp[0].minor.yy0);}
#line 784 "cfg.c"
        break;
      case 17: /* kv ::= ENV STR */
#line 35 "cfg.y"
{set_env(ps,yymsp[0].minor.yy0);}
#line 789 "cfg.c"
        break;
      case 18: /* kv ::= ULIMIT STR STR */
      case 34: /* pairs ::= pairs STR STR */ yytestcase(yyruleno==34);
#line 36 "cfg.y"
{set_ulimit(ps,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
#line 795 "cfg.c"
        break;
      case 20: /* kv ::= DISABLED */
#line 38 "cfg.y"
{set_dis(ps);  }
#line 800 "cfg.c"
        break;
      case 21: /* kv ::= WAIT */
#line 39 "cfg.y"
{set_wait(ps); }
#line 805 "cfg.c"
        break;
      case 22: /* kv ::= ONCE */
#line 40 "cfg.y"
{set_once(ps); }
#line 810 "cfg.c"
        break;
      case 23: /* kv ::= BOUNCE EVERY STR */
#line 41 "cfg.y"
{set_bounce(ps,yymsp[0].minor.yy0);}
#line 815 "cfg.c"
        break;
      case 25: /* cmd ::= path */
#line 43 "cfg.y"
{set_cmd(ps,yymsp[0].minor.yy0);}
#line 820 "cfg.c"
        break;
      case 26: /* cmd ::= path args */
#line 44 "cfg.y"
{set_cmd(ps,yymsp[-1].minor.yy0);}
#line 825 "cfg.c"
        break;
      case 27: /* path ::= STR */
      case 30: /* arg ::= STR */ yytestcase(yyruleno==30);
#line 45 "cfg.y"
{yygotominor.yy0=yymsp[0].minor.yy0;}
#line 831 "cfg.c"
        break;
      case 28: /* args ::= args arg */
      case 29: /* args ::= arg */ yytestcase(yyruleno==29);
#line 46 "cfg.y"
{utarray_push_back(&ps->job->cmdv,&yymsp[0].minor.yy0);}
#line 837 "cfg.c"
        break;
      case 31: /* arg ::= QUOTEDSTR */
#line 49 "cfg.y"
{yygotominor.yy0=unquote(yymsp[0].minor.yy0);}
#line 842 "cfg.c"
        break;
      case 32: /* paths ::= paths path */
      case 33: /* paths ::= path */ yytestcase(yyruleno==33);
#line 50 "cfg.y"
{utarray_push_back(&ps->job->depv,&yymsp[0].minor.yy0);}
#line 848 "cfg.c"
        break;
      default:
      /* (0) file ::= decls */ yytestcase(yyruleno==0);
      /* (1) decls ::= decls job */ yytestcase(yyruleno==1);
      /* (2) decls ::= decls decl */ yytestcase(yyruleno==2);
      /* (3) decls ::= */ yytestcase(yyruleno==3);
      /* (7) sbody ::= sbody kv */ yytestcase(yyruleno==7);
      /* (8) sbody ::= kv */ yytestcase(yyruleno==8);
      /* (10) kv ::= CMD cmd */ yytestcase(yyruleno==10);
      /* (19) kv ::= ULIMIT LCURLY pairs RCURLY */ yytestcase(yyruleno==19);
      /* (24) kv ::= DEPENDS LCURLY paths RCURLY */ yytestcase(yyruleno==24);
      /* (35) pairs ::= */ yytestcase(yyruleno==35);
        break;
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
  if( yyact < YYNSTATE ){
#ifdef NDEBUG
    /* If we are not debugging and the reduce action popped at least
    ** one element off the stack, then we can push the new element back
    ** onto the stack here, and skip the stack overflow test in yy_shift().
    ** That gives a significant speed improvement. */
    if( yysize ){
      yypParser->yyidx++;
      yymsp -= yysize-1;
      yymsp->stateno = (YYACTIONTYPE)yyact;
      yymsp->major = (YYCODETYPE)yygoto;
      yymsp->minor = yygotominor;
    }else
#endif
    {
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
    }
  }else{
    assert( yyact == YYNSTATE + YYNRULE + 1 );
    yy_accept(yypParser);
  }
}
Esempio n. 4
0
//------ Begin of function Unit::search_or_wait ---------//
// call searching or wait
//
void Unit::search_or_wait()
{
	#define	SQUARE1	9
	#define	SQUARE2	25
	#define	SQUARE3	49
	#define	DIMENSION 7

	int curXLoc = next_x_loc(), curYLoc = next_y_loc();
	short surrArray[SQUARE3];
	int xShift, yShift, checkXLoc, checkYLoc, hasFree, i, shouldWait;
	short unitRecno;
	Unit *unitPtr;
	Location *locPtr;

	//----------------------------------------------------------------------------//
	// wait if the unit is totally blocked.  Otherwise, call searching
	//----------------------------------------------------------------------------//
	memset(surrArray, 0, sizeof(short)*SQUARE3);
	for(shouldWait=0, hasFree=0, i=2; i<=SQUARE3; i++)
	{
		if(i==SQUARE1 || i==SQUARE2 || i==SQUARE3)
		{
			if(!hasFree)
			{	
				shouldWait++;
				break;
			}
			else
				hasFree = 0;
		}

		m.cal_move_around_a_point(i, DIMENSION, DIMENSION, 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->has_unit(mobile_type))
		{
			hasFree++;
			continue;
		}

		unitRecno = locPtr->unit_recno(mobile_type);
		err_when(!unitRecno);
		if(unit_array.is_deleted(unitRecno))
			continue;

		unitPtr = unit_array[unitRecno];
		if(unitPtr->nation_recno==nation_recno && unitPtr->unit_group_id==unit_group_id &&
			((unitPtr->cur_action==SPRITE_WAIT && unitPtr->waiting_term>1) || unitPtr->cur_action==SPRITE_TURN ||
			  unitPtr->cur_action==SPRITE_MOVE))
		{
			surrArray[i-2] = unitRecno;
			unitPtr->unit_group_id++;
		}
	}

	//------------------- call searching if should not wait --------------------//
	if(!shouldWait)
		search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_IN_A_GROUP);
		//search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_IN_A_GROUP);

	for(i=0; i<SQUARE3; i++)
	{
		if(surrArray[i])
		{
			err_when(unit_array.is_deleted(surrArray[i]));
			unitPtr = unit_array[surrArray[i]];
			unitPtr->unit_group_id--;
		}
	}

	if(shouldWait)
		set_wait();
}
Esempio n. 5
0
//------ 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));
}
Esempio n. 6
0
//--------- 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 #########//
	}
}
Esempio n. 7
0
//--------- 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;
}