|  | @@ -353,57 +353,68 @@ battle::Units CBattleInfoCallback::battleAliveUnits(ui8 side) const
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  //T is battle::Unit descendant
 | 
	
		
			
				|  |  |  template <typename T>
 | 
	
		
			
				|  |  | -const T * takeOneUnit(std::vector<const T *> & all, const int turn, int8_t & lastMoved)
 | 
	
		
			
				|  |  | +const T * takeOneUnit(std::vector<const T*> & all, const int turn, int8_t & lastMoved, int phase)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	const T * ret = nullptr;
 | 
	
		
			
				|  |  | -	size_t i, //fastest stack
 | 
	
		
			
				|  |  | -			j=0; //fastest stack of the other side
 | 
	
		
			
				|  |  | -	for(i = 0; i < all.size(); i++)
 | 
	
		
			
				|  |  | -		if(all[i])
 | 
	
		
			
				|  |  | -			break;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	//no stacks left
 | 
	
		
			
				|  |  | -	if(i == all.size())
 | 
	
		
			
				|  |  | -		return nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	const T * fastest = all[i], *other = nullptr;
 | 
	
		
			
				|  |  | -	int bestSpeed = fastest->getInitiative(turn);
 | 
	
		
			
				|  |  | +	const T * returnedUnit = nullptr;
 | 
	
		
			
				|  |  | +	size_t currentUnitIndex = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if(fastest->unitSide() == lastMoved)
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -		ret = fastest;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	else
 | 
	
		
			
				|  |  | +	for(size_t i = 0; i < all.size(); i++)
 | 
	
		
			
				|  |  |  	{
 | 
	
		
			
				|  |  | -		for(j = i + 1; j < all.size(); j++)
 | 
	
		
			
				|  |  | +		int32_t currentUnitSpeed = -1;
 | 
	
		
			
				|  |  | +		int32_t returnedUnitSpeed = -1;
 | 
	
		
			
				|  |  | +		if(returnedUnit)
 | 
	
		
			
				|  |  | +			returnedUnitSpeed = returnedUnit->getInitiative(turn);
 | 
	
		
			
				|  |  | +		if(all[i])
 | 
	
		
			
				|  |  |  		{
 | 
	
		
			
				|  |  | -			if(!all[j]) continue;
 | 
	
		
			
				|  |  | -			if(all[j]->unitSide() != lastMoved || all[j]->getInitiative(turn) != bestSpeed)
 | 
	
		
			
				|  |  | +			currentUnitSpeed = all[i]->getInitiative(turn);
 | 
	
		
			
				|  |  | +			switch(phase)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +			case 1: // Faster first, attacker priority, higher slot first
 | 
	
		
			
				|  |  | +				if(returnedUnit == nullptr || currentUnitSpeed > returnedUnitSpeed)
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					returnedUnit = all[i];
 | 
	
		
			
				|  |  | +					currentUnitIndex = i;
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				else if(currentUnitSpeed == returnedUnitSpeed)
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					if(lastMoved == -1 && turn <= 0 && all[i]->unitSide() == BattleSide::ATTACKER
 | 
	
		
			
				|  |  | +						&& !(returnedUnit->unitSide() == all[i]->unitSide() && returnedUnit->unitSlot() < all[i]->unitSlot())) // Turn 0 attacker priority
 | 
	
		
			
				|  |  | +					{
 | 
	
		
			
				|  |  | +						returnedUnit = all[i];
 | 
	
		
			
				|  |  | +						currentUnitIndex = i;
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +					else if(lastMoved != -1 && all[i]->unitSide() != lastMoved
 | 
	
		
			
				|  |  | +						&& !(returnedUnit->unitSide() == all[i]->unitSide() && returnedUnit->unitSlot() < all[i]->unitSlot())) // Alternate equal speeds units
 | 
	
		
			
				|  |  | +					{
 | 
	
		
			
				|  |  | +						returnedUnit = all[i];
 | 
	
		
			
				|  |  | +						currentUnitIndex = i;
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  |  				break;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if(j >= all.size())
 | 
	
		
			
				|  |  | -		{
 | 
	
		
			
				|  |  | -			ret = fastest;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		else
 | 
	
		
			
				|  |  | -		{
 | 
	
		
			
				|  |  | -			other = all[j];
 | 
	
		
			
				|  |  | -			if(other->getInitiative(turn) != bestSpeed)
 | 
	
		
			
				|  |  | -				ret = fastest;
 | 
	
		
			
				|  |  | -			else
 | 
	
		
			
				|  |  | -				ret = other;
 | 
	
		
			
				|  |  | +			case 2: // Slower first, higher slot first
 | 
	
		
			
				|  |  | +			case 3:
 | 
	
		
			
				|  |  | +				if(returnedUnit == nullptr || currentUnitSpeed < returnedUnitSpeed)
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					returnedUnit = all[i];
 | 
	
		
			
				|  |  | +					currentUnitIndex = i;
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				else if(currentUnitSpeed == returnedUnitSpeed && lastMoved != -1 && all[i]->unitSide() != lastMoved
 | 
	
		
			
				|  |  | +					&& !(returnedUnit->unitSide() == all[i]->unitSide() && returnedUnit->unitSlot() < all[i]->unitSlot())) // Alternate equal speeds units
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					returnedUnit = all[i];
 | 
	
		
			
				|  |  | +					currentUnitIndex = i;
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +			default:
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	assert(ret);
 | 
	
		
			
				|  |  | -	if(ret == fastest)
 | 
	
		
			
				|  |  | -		all[i] = nullptr;
 | 
	
		
			
				|  |  | -	else
 | 
	
		
			
				|  |  | -		all[j] = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	lastMoved = ret->unitSide();
 | 
	
		
			
				|  |  | -	return ret;
 | 
	
		
			
				|  |  | +	if(!returnedUnit)
 | 
	
		
			
				|  |  | +		return nullptr;
 | 
	
		
			
				|  |  | +	all[currentUnitIndex] = nullptr;
 | 
	
		
			
				|  |  | +	return returnedUnit;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void CBattleInfoCallback::battleGetTurnOrder(std::vector<battle::Units> & out, const size_t maxUnits, const int maxTurns, const int turn, int8_t lastMoved) const
 | 
	
	
		
			
				|  | @@ -483,28 +494,39 @@ void CBattleInfoCallback::battleGetTurnOrder(std::vector<battle::Units> & out, c
 | 
	
		
			
				|  |  |  		phase[p].push_back(one);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	boost::sort(phase[0], CMP_stack(0, actualTurn));
 | 
	
		
			
				|  |  | +	boost::sort(phase[0], CMP_stack(0, actualTurn, lastMoved));
 | 
	
		
			
				|  |  |  	std::copy(phase[0].begin(), phase[0].end(), std::back_inserter(out.back()));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if(outputFull())
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	for(int i = 1; i < 4; i++)
 | 
	
		
			
				|  |  | -		boost::sort(phase[i], CMP_stack(i, actualTurn));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if(lastMoved < 0)
 | 
	
		
			
				|  |  | -		lastMoved = BattleSide::ATTACKER;
 | 
	
		
			
				|  |  | +		boost::sort(phase[i], CMP_stack(i, actualTurn, lastMoved));	
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	int pi = 1;
 | 
	
		
			
				|  |  |  	while(!outputFull() && pi < 4)
 | 
	
		
			
				|  |  |  	{
 | 
	
		
			
				|  |  | -		auto current = takeOneUnit(phase[pi], actualTurn, lastMoved);
 | 
	
		
			
				|  |  | -		if(!current)
 | 
	
		
			
				|  |  | +		const battle::Unit * current = nullptr;
 | 
	
		
			
				|  |  | +		if(phase[pi].empty())
 | 
	
		
			
				|  |  |  			pi++;
 | 
	
		
			
				|  |  |  		else
 | 
	
		
			
				|  |  | -			out.back().push_back(current);
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			current = takeOneUnit(phase[pi], actualTurn, lastMoved, pi);
 | 
	
		
			
				|  |  | +			if(!current)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				pi++;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			else
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				out.back().push_back(current);
 | 
	
		
			
				|  |  | +				lastMoved = current->unitSide();	
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	if(lastMoved < 0)
 | 
	
		
			
				|  |  | +		lastMoved = BattleSide::ATTACKER;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	if(!outputFull() && (maxTurns == 0 || out.size() < maxTurns))
 | 
	
		
			
				|  |  |  		battleGetTurnOrder(out, maxUnits, maxTurns, actualTurn + 1, lastMoved);
 | 
	
		
			
				|  |  |  }
 |