void Player_Random::getMoves(GameState & state, const MoveArray & moves, std::vector<Move> & moveVec)
{
	for (size_t u(0); u<moves.numUnits(); u++)
	{
		moveVec.push_back(moves.getMove(u, rand() % moves.numMoves(u)));
	}
}
Exemple #2
0
void GameState::generateMoves(MoveArray & moves, const IDType & playerIndex) const
{
	moves.clear();

	// which is the enemy player
	IDType enemyPlayer  = getEnemy(playerIndex);

	// we are interested in all simultaneous moves
	// so return all units which can move at the same time as the first
	TimeType firstUnitMoveTime = getUnit(playerIndex, 0).firstTimeFree();
		
	for (IDType unitIndex(0); unitIndex < _numUnits[playerIndex]; ++unitIndex)
	{
		// unit reference
		const Unit & unit(getUnit(playerIndex,unitIndex));
			
		// if this unit can't move at the same time as the first
		if (unit.firstTimeFree() != firstUnitMoveTime)
		{
			// stop checking
			break;
		}

		if (unit.previousMoveTime() == _currentTime && _currentTime != 0)
		{
			// CHANGED
            // printf("ERROR: Previous Move: %s\n", unit.previousMove().moveString().c_str());
			int a = 6;
		}

		moves.addUnit();

		// generate attack moves
		if (unit.canAttackNow())
		{
			for (IDType u(0); u<_numUnits[enemyPlayer]; ++u)
			{
				const Unit & enemyUnit(getUnit(enemyPlayer, u));
				if (unit.canAttackTarget(enemyUnit, _currentTime) && enemyUnit.isAlive())
				{
					moves.add(Move(unitIndex, playerIndex, MoveTypes::ATTACK, u));
				}
			}
		}
		else if (unit.canHealNow())
		{
			for (IDType u(0); u<_numUnits[playerIndex]; ++u)
			{
				// units cannot heal themselves in broodwar
				if (u == unitIndex)
				{
					continue;
				}

				const Unit & ourUnit(getUnit(playerIndex, u));
				if (unit.canHealTarget(ourUnit, _currentTime) && ourUnit.isAlive())
				{
					moves.add(Move(unitIndex, playerIndex, MoveTypes::HEAL, u));
				}
			}
		}
		// generate the wait move if it can't attack yet
		else
		{
			if (!unit.canHeal())
			{
				moves.add(Move(unitIndex, playerIndex, MoveTypes::RELOAD, 0));
			}
		}
		
		// generate movement moves
		if (unit.isMobile())
		{
			for (IDType d(0); d<Search::Constants::Num_Directions; ++d)
			{
				Move move(unitIndex, playerIndex, MoveTypes::MOVE, d);
			
				Position dest;
				Position dir(Search::Constants::Move_Dir[move._moveIndex][0], 
							 Search::Constants::Move_Dir[move._moveIndex][1]);
			
				// if the unit can attack the destination will be set by default move distance
				if (unit.canAttackNow() || unit.canHeal())
				{
					dest = Position(Search::Constants::Move_Distance*dir.x(), Search::Constants::Move_Distance*dir.y()) + unit.pos();
				}
				// otherwise it will be a move until attack move
				else
				{
					dest = unit.getMoveUntilAttackDest(dir, _currentTime);
				}

				if (isWalkable(dest))
				{
					moves.add(Move(unitIndex, playerIndex, MoveTypes::MOVE, d));
				}
			}
		}

		// if no moves were generated for this unit, it must be issued a 'PASS' move
		if (moves.numMoves(unitIndex) == 0)
		{
			moves.add(Move(unitIndex, playerIndex, MoveTypes::PASS, 0));
		}
	}

	if (!moves.validateMoves())
	{
		fprintf(stderr, "Moves invalid, something is wrong\n");
	}
}
void GameState::generateMoves(MoveArray & moves, const IDType & playerIndex) const
{
	moves.clear();

    // which is the enemy player
	IDType enemyPlayer  = getEnemy(playerIndex);

    // make sure this player can move right now
    const IDType canMove(whoCanMove());
    if (canMove == enemyPlayer)
    {
        System::FatalError("GameState Error - Called generateMoves() for a player that cannot currently move");
    }

	// we are interested in all simultaneous moves
	// so return all units which can move at the same time as the first
	TimeType firstUnitMoveTime = getUnit(playerIndex, 0).firstTimeFree();
		
	for (IDType unitIndex(0); unitIndex < _numUnits[playerIndex]; ++unitIndex)
	{
		// unit reference
		const Unit & unit(getUnit(playerIndex,unitIndex));
			
		// if this unit can't move at the same time as the first
		if (unit.firstTimeFree() != firstUnitMoveTime)
		{
			// stop checking
			break;
		}

		if (unit.previousActionTime() == _currentTime && _currentTime != 0)
		{
            System::FatalError("Previous Move Took 0 Time: " + unit.previousAction().moveString());
		}

		moves.addUnit();

		// generate attack moves
		if (unit.canAttackNow())
		{
			for (IDType u(0); u<_numUnits[enemyPlayer]; ++u)
			{
				const Unit & enemyUnit(getUnit(enemyPlayer, u));
				bool invisible = false;
				if (enemyUnit.type().hasPermanentCloak())
				{
					invisible = true;
					for (IDType detectorIndex(0); detectorIndex < _numUnits[playerIndex]; ++detectorIndex)
					{
						// unit reference
						const Unit & detector(getUnit(playerIndex, detectorIndex));
						if (detector.type().isDetector() && detector.canSeeTarget(enemyUnit, _currentTime))
						{
							invisible = false;
							break;
						}
					}
				}
				if (!invisible && unit.canAttackTarget(enemyUnit, _currentTime) && enemyUnit.isAlive())
				{
					moves.add(Action(unitIndex, playerIndex, ActionTypes::ATTACK, u));
                    //moves.add(Action(unitIndex, playerIndex, ActionTypes::ATTACK, unit.ID()));
				}
			}
		}
		else if (unit.canHealNow())
		{
			for (IDType u(0); u<_numUnits[playerIndex]; ++u)
			{
				// units cannot heal themselves in broodwar
				if (u == unitIndex)
				{
					continue;
				}

				const Unit & ourUnit(getUnit(playerIndex, u));
				if (unit.canHealTarget(ourUnit, _currentTime) && ourUnit.isAlive())
				{
					moves.add(Action(unitIndex, playerIndex, ActionTypes::HEAL, u));
                    //moves.add(Action(unitIndex, playerIndex, ActionTypes::HEAL, unit.ID()));
				}
			}
		}
		// generate the wait move if it can't attack yet
		else
		{
			if (!unit.canHeal())
			{
				moves.add(Action(unitIndex, playerIndex, ActionTypes::RELOAD, 0));
			}
		}
		
		// generate movement moves
		if (unit.isMobile())
		{
            // In order to not move when we could be shooting, we want to move for the minimum of:
            // 1) default move distance move time
            // 2) time until unit can attack, or if it can attack, the next cooldown
            double timeUntilAttack          = unit.nextAttackActionTime() - getTime();
            timeUntilAttack                 = timeUntilAttack == 0 ? unit.attackCooldown() : timeUntilAttack;

            // the default move duration
            double defaultMoveDuration      = (double)Constants::Move_Distance / unit.speed();

            // if we can currently attack
			double chosenTime = timeUntilAttack != 0 ? std::min(timeUntilAttack, defaultMoveDuration) : defaultMoveDuration;

            // the chosen movement distance
            PositionType moveDistance       = (PositionType)(chosenTime * unit.speed());

            // DEBUG: If chosen move distance is ever 0, something is wrong
            if (moveDistance == 0)
            {
                System::FatalError("Move Action with distance 0 generated. timeUntilAttack:"+
					std::to_string(timeUntilAttack)+", speed:"+std::to_string(unit.speed()));
            }

            // we are only generating moves in the cardinal direction specified in common.h
			for (IDType d(0); d<Constants::Num_Directions; ++d)
			{			
                // the direction of this movement
              	Position dir(Constants::Move_Dir[d][0], Constants::Move_Dir[d][1]);
            
                if (moveDistance == 0)
                {
                    printf("%lf %lf %lf\n", timeUntilAttack, defaultMoveDuration, chosenTime);
                }

                // the final destination position of the unit
                Position dest = unit.pos() + Position(moveDistance*dir.x(), moveDistance*dir.y());

                // if that poisition on the map is walkable
                if (isWalkable(dest) || (unit.type().isFlyer() && isFlyable(dest)))
				{
                    // add the move to the MoveArray
					moves.add(Action(unitIndex, playerIndex, ActionTypes::MOVE, d, dest));
				}
			}
		}

		// if no moves were generated for this unit, it must be issued a 'PASS' move
		if (moves.numMoves(unitIndex) == 0)
		{
			moves.add(Action(unitIndex, playerIndex, ActionTypes::PASS, 0));
		}
	}
}
void Player_NOKDPS::getMoves(GameState & state, const MoveArray & moves, std::vector<UnitAction> & moveVec)
{
    moveVec.clear();
	IDType enemy(state.getEnemy(_playerID));

	Array<int, Constants::Max_Units> hpRemaining;

	for (IDType u(0); u<state.numUnits(enemy); ++u)
	{
		hpRemaining[u] = state.getUnit(enemy,u).currentHP();
	}

	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundUnitAction						(false);
		size_t actionMoveIndex					(0);
		double actionHighestDPS					(0);
		size_t closestMoveIndex					(0);
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());
		
		const Unit & ourUnit				(state.getUnit(_playerID, u));
		const Unit & closestUnit(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : ourUnit.type().isDetector() ? state.getClosestEnemyUnit(_playerID, u, false):state.getClosestEnemyUnit(_playerID, u, true));
		
		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const UnitAction move						(moves.getMove(u, m));
				
			if ((move.type() == UnitActionTypes::ATTACK) && (hpRemaining[move._moveIndex] > 0))
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				double dpsHPValue =				(target.dpf() / hpRemaining[move._moveIndex]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundUnitAction = true;
				}

                if (move._moveIndex >= state.numUnits(enemy))
                {
                    int e = enemy;
                    int pl = _playerID;
                    printf("wtf\n");
                }
			}
			else if (move.type() == UnitActionTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move._moveIndex));
				double dpsHPValue =				(target.dpf() / hpRemaining[move._moveIndex]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundUnitAction = true;
				}
			}
			else if (move.type() == UnitActionTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == UnitActionTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Constants::Move_Dir[move._moveIndex][0], 
												 ourUnit.y() + Constants::Move_Dir[move._moveIndex][1]);
				size_t dist						(closestUnit.getDistanceSqToPosition(ourDest, state.getTime()));

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(foundUnitAction ? actionMoveIndex : closestMoveIndex);

		UnitAction theMove(moves.getMove(u, actionMoveIndex));
		if (theMove.type() == UnitActionTypes::ATTACK)
		{
			hpRemaining[theMove.index()] -= state.getUnit(_playerID, theMove.unit()).damage();
		}
			
		moveVec.push_back(moves.getMove(u, bestMoveIndex));
	}
}
const MoveTuple Player_AttackClosest::getMoveTuple(GameState & state, const MoveArray & moves)
{
	MoveTuple tuple(0);

	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction					(false);
		size_t actionMoveIndex				(0);
		size_t closestMoveIndex				(0);
		unsigned long long actionDistance	(std::numeric_limits<unsigned long long>::max());
		unsigned long long closestMoveDist	(std::numeric_limits<unsigned long long>::max());

		const Unit & ourUnit				(state.getUnit(_playerID, u));
		const Unit & closestUnit			(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const Move move					(moves.getMove(u, m));
				
			if (move.type() == MoveTypes::ATTACK)
			{
				const Unit & target			(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				size_t dist					(ourUnit.distSq(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			if (move.type() == MoveTypes::HEAL)
			{
				const Unit & target			(state.getUnit(move.player(), move._moveIndex));
				size_t dist					(ourUnit.distSq(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == MoveTypes::MOVE)
			{
				Position ourDest			(ourUnit.x() + Search::Constants::Move_Dir[move._moveIndex][0], 
											 ourUnit.y() + Search::Constants::Move_Dir[move._moveIndex][1]);
				size_t dist					(closestUnit.distSq(ourDest, state.getTime()));

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(foundAction ? actionMoveIndex : closestMoveIndex);

		tuple += bestMoveIndex * moves.getProduct(u);
	}

	return tuple;
}
void Player_KiterDPS::getMoves(GameState & state, const MoveArray & moves, std::vector<Move> & moveVec)
{
	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction						(false);
		IDType actionMoveIndex					(0);
		IDType furthestMoveIndex				(0);
		size_t furthestMoveDist					(0);
		IDType closestMoveIndex					(0);
		double actionHighestDPS					(0);
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());

		const Unit & ourUnit					(state.getUnit(_playerID, u));
		const Unit & closestUnit				(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (IDType m(0); m<moves.numMoves(u); ++m)
		{
			const Move move						(moves.getMove(u, m));
				
			if (move.type() == MoveTypes::ATTACK)
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				double dpsHPValue 				(target.dpf() / target.currentHP());

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move._moveIndex));
				double dpsHPValue 				(target.dpf() / target.currentHP());

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Search::Constants::Move_Dir[move._moveIndex][0], 
												 ourUnit.y() + Search::Constants::Move_Dir[move._moveIndex][1]);
				size_t dist						(closestUnit.distSq(ourDest, state.getTime()));

				if (dist > furthestMoveDist)
				{
					furthestMoveDist = dist;
					furthestMoveIndex = m;
				}

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		// the move we will be returning
		size_t bestMoveIndex(0);

		// if we have an attack move we will use that one
		if (foundAction)
		{
			bestMoveIndex = actionMoveIndex;
		}
		// otherwise use the closest move to the opponent
		else
		{
			// if we are in attack range of the unit, back up
			if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
			{
				bestMoveIndex = furthestMoveIndex;
			}
			// otherwise get back into the fight
			else
			{
				bestMoveIndex = closestMoveIndex;
			}
		}
		
		moveVec.push_back(moves.getMove(u, bestMoveIndex));
	}
}
// TODO: UNTESTED
const MoveTuple Player_Kiter::getMoveTuple(GameState & state, const MoveArray & moves)
{
	// the tuple, we will generate this on the fly
	MoveTuple tuple(0);
	
	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction						(false);
		IDType actionMoveIndex					(0);
		IDType furthestMoveIndex				(0);
		size_t furthestMoveDist					(0);
		IDType closestMoveIndex					(0);
		int actionDistance						(std::numeric_limits<int>::max());
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());

		const Unit & ourUnit					(state.getUnit(_playerID, u));
		const Unit & closestUnit				(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (IDType m(0); m<moves.numMoves(u); ++m)
		{
			const Move move						(moves.getMove(u, m));
				
			if (move.type() == MoveTypes::ATTACK)
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				PositionType dist				(ourUnit.distSq(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move._moveIndex));
				PositionType dist				(ourUnit.distSq(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Search::Constants::Move_Dir[move._moveIndex][0], 
												 ourUnit.y() + Search::Constants::Move_Dir[move._moveIndex][1]);
				size_t dist						(closestUnit.distSq(ourDest, state.getTime()));

				if (dist > furthestMoveDist)
				{
					furthestMoveDist = dist;
					furthestMoveIndex = m;
				}

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		// the move we will be returning
		size_t bestMoveIndex(0);

		// if we have an attack move we will use that one
		if (foundAction)
		{
			bestMoveIndex = actionMoveIndex;
		}
		// otherwise use the closest move to the opponent
		else
		{
			// if we are in attack range of the unit, back up
			if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
			{
				bestMoveIndex = furthestMoveIndex;
			}
			// otherwise get back into the fight
			else
			{
				bestMoveIndex = closestMoveIndex;
			}
		}
			
		// update the tuple calculation
		tuple += bestMoveIndex * moves.getProduct(u);
	}

	return tuple;
}
const MoveTuple Player_NOK_AttackDPS::getMoveTuple(GameState & state, const MoveArray & moves)
{
	MoveTuple tuple(0);

	IDType player(moves.getMove(0,0).player());
	IDType enemy(state.getEnemy(player));

	Array<int, Search::Constants::Max_Units> hpRemaining;
	if (state.numUnits(enemy) > Search::Constants::Max_Units) 
	{
		hpRemaining.resize(state.numUnits(enemy));
	}

	for (IDType u(0); u<state.numUnits(enemy); ++u)
	{
		hpRemaining[u] = state.getUnit(enemy,u).currentHP();
	}

	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction						(false);
		size_t actionMoveIndex					(0);
		double actionHighestDPS					(0);
		size_t closestMoveIndex					(0);
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());
		
		const Unit & ourUnit				(state.getUnit(_playerID, u));
		const Unit & closestUnit			(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const Move move						(moves.getMove(u, m));
				
			if ((move.type() == MoveTypes::ATTACK) && (hpRemaining[move._moveIndex] > 0))
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				double dpsHPValue =				(target.dpf() / hpRemaining[move._moveIndex]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move._moveIndex));
				double dpsHPValue =				(target.dpf() / hpRemaining[move._moveIndex]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == MoveTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Search::Constants::Move_Dir[move._moveIndex][0], 
												 ourUnit.y() + Search::Constants::Move_Dir[move._moveIndex][1]);
				size_t dist						(closestUnit.distSq(ourDest, state.getTime()));

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(foundAction ? actionMoveIndex : closestMoveIndex);

		Move theMove(moves.getMove(u, actionMoveIndex));
		if (theMove.type() == MoveTypes::ATTACK)
		{
			hpRemaining[theMove.index()] -= state.getUnit(player, theMove.unit()).damage();
		}
			
		tuple += bestMoveIndex * moves.getProduct(u);
	}

	return tuple;
}
void Player_AttackDPS::getMoves(GameState & state, const MoveArray & moves, std::vector<Move> & moveVec)
{
	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction						(false);
		size_t actionMoveIndex					(0);
		size_t closestMoveIndex					(0);
		double actionHighestDPS					(0);
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());
		
		const Unit & ourUnit					(state.getUnit(_playerID, u));
		const Unit & closestUnit				(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const Move move						(moves.getMove(u, m));
				
			if (move.type() == MoveTypes::ATTACK)
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				double dpsHPValue =				(target.dpf() / target.currentHP());

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			if (move.type() == MoveTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move._moveIndex));
				double dpsHPValue =				(target.dpf() / target.currentHP());

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == MoveTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == MoveTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Search::Constants::Move_Dir[move._moveIndex][0], 
												 ourUnit.y() + Search::Constants::Move_Dir[move._moveIndex][1]);
				size_t dist						(closestUnit.distSq(ourDest, state.getTime()));

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(foundAction ? actionMoveIndex : closestMoveIndex);
			
		moveVec.push_back(moves.getMove(u, bestMoveIndex));
	}
}
void Player_AttackClosest::getMoves(const GameState & state, const MoveArray & moves, std::vector<UnitAction> & moveVec)
{
    moveVec.clear();
	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundUnitAction				(false);
		size_t actionMoveIndex				(0);
		size_t closestMoveIndex				(0);
		unsigned long long actionDistance	(std::numeric_limits<unsigned long long>::max());
		unsigned long long closestMoveDist	(std::numeric_limits<unsigned long long>::max());

		const Unit & ourUnit				(state.getUnit(_playerID, u));
		const Unit & closestUnit			(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const UnitAction move					(moves.getMove(u, m));
				
			if (move.type() == UnitActionTypes::ATTACK)
			{
				const Unit & target			(state.getUnit(state.getEnemy(move.player()), move._moveIndex));
				size_t dist					(ourUnit.getDistanceSqToUnit(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundUnitAction = true;
				}
			}
			if (move.type() == UnitActionTypes::HEAL)
			{
				const Unit & target			(state.getUnit(move.player(), move._moveIndex));
				size_t dist					(ourUnit.getDistanceSqToUnit(target, state.getTime()));

				if (dist < actionDistance)
				{
					actionDistance = dist;
					actionMoveIndex = m;
					foundUnitAction = true;
				}
			}
			else if (move.type() == UnitActionTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == UnitActionTypes::MOVE)
			{
				Position ourDest			(ourUnit.x() + Constants::Move_Dir[move._moveIndex][0], 
											 ourUnit.y() + Constants::Move_Dir[move._moveIndex][1]);
				size_t dist					(closestUnit.getDistanceSqToPosition(ourDest, state.getTime()));

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(foundUnitAction ? actionMoveIndex : closestMoveIndex);

		moveVec.push_back(moves.getMove(u, bestMoveIndex));
	}
}
void Player_Kiter_NOKDPS::getMoves(GameState & state, const MoveArray & moves, std::vector<Action> & moveVec)
{
    moveVec.clear();
	IDType enemy(state.getEnemy(_playerID));

	Array<int, Constants::Max_Units> hpRemaining;

	for (IDType u(0); u<state.numUnits(enemy); ++u)
	{
		hpRemaining[u] = state.getUnit(enemy,u).currentHP();
	}

	for (IDType u(0); u<moves.numUnits(); ++u)
	{
		bool foundAction					(false);
		size_t actionMoveIndex					(0);
        IDType furthestMoveIndex				(0);
		size_t furthestMoveDist					(0);
		double actionHighestDPS					(0);
		size_t closestMoveIndex					(0);
		unsigned long long closestMoveDist		(std::numeric_limits<unsigned long long>::max());
		
		const Unit & ourUnit				(state.getUnit(_playerID, u));
		const Unit & closestUnit			(ourUnit.canHeal() ? state.getClosestOurUnit(_playerID, u) : state.getClosestEnemyUnit(_playerID, u));

		for (size_t m(0); m<moves.numMoves(u); ++m)
		{
			const Action move						(moves.getMove(u, m));
				
			if ((move.type() == ActionTypes::ATTACK) && (hpRemaining[move.index()] > 0))
			{
				const Unit & target				(state.getUnit(state.getEnemy(move.player()), move.index()));
				double dpsHPValue =				(target.dpf() / hpRemaining[move.index()]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}

                if (move.index() >= state.numUnits(enemy))
                {
                    int e = enemy;
                    int pl = _playerID;
                    printf("wtf\n");
                }
			}
			else if (move.type() == ActionTypes::HEAL)
			{
				const Unit & target				(state.getUnit(move.player(), move.index()));
				double dpsHPValue =				(target.dpf() / hpRemaining[move.index()]);

				if (dpsHPValue > actionHighestDPS)
				{
					actionHighestDPS = dpsHPValue;
					actionMoveIndex = m;
					foundAction = true;
				}
			}
			else if (move.type() == ActionTypes::RELOAD)
			{
				if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
				{
					closestMoveIndex = m;
					break;
				}
			}
			else if (move.type() == ActionTypes::MOVE)
			{
				Position ourDest				(ourUnit.x() + Constants::Move_Dir[move.index()][0], 
												 ourUnit.y() + Constants::Move_Dir[move.index()][1]);
				size_t dist						(closestUnit.getDistanceSqToPosition(ourDest, state.getTime()));

                if (dist > furthestMoveDist)
				{
					furthestMoveDist = dist;
					furthestMoveIndex = m;
				}

				if (dist < closestMoveDist)
				{
					closestMoveDist = dist;
					closestMoveIndex = m;
				}
			}
		}

		size_t bestMoveIndex(0);
        // if we have an attack move we will use that one
		if (foundAction)
		{
			bestMoveIndex = actionMoveIndex;
		}
		// otherwise use the closest move to the opponent
		else
		{
			// if we are in attack range of the unit, back up
			if (ourUnit.canAttackTarget(closestUnit, state.getTime()))
			{
				bestMoveIndex = furthestMoveIndex;
			}
			// otherwise get back into the fight
			else
			{
				bestMoveIndex = closestMoveIndex;
			}
		}

		Action theMove(moves.getMove(u, actionMoveIndex));
		if (theMove.type() == ActionTypes::ATTACK)
		{
			hpRemaining[theMove.index()] -= state.getUnit(_playerID, theMove.unit()).damage();
		}
			
		moveVec.push_back(moves.getMove(u, bestMoveIndex));
	}
}