예제 #1
0
    public void MakeTurn()
    {
        if (_playerBalls == null)
        {
            _makeTurnAfterLoading = true;
            return;
        }

        int[] playerIds = Enumerable.Range(0, _gameLogic.NumberOfPlayers).ToArray(); // shuffling players
        for (int i = 0; i < _gameLogic.NumberOfPlayers; i++)
        {
            int tmp = playerIds[i];
            int j   = Random.Range(i, _gameLogic.NumberOfPlayers);
            playerIds[i] = playerIds[j];
            playerIds[j] = tmp;
        }

        HitInfo bestHit = new HitInfo(this, _playerId, 0, 0);

        for (int playerIndex = 0; playerIndex < _gameLogic.NumberOfPlayers; ++playerIndex)
        {
            int playerId       = playerIds[playerIndex];
            var ballPosition   = _gameLogic.PlayerBalls[playerId].transform.position;
            var targetPosition = _gameLogic.PlayerBalls[playerId].GoalHint;

            float goalDirection     = ballPosition.xz().LookAt(targetPosition.xz()) - (playerId == _playerId ? 0 : 180);
            float minDirectionDelta = playerId == _playerId ? MinAngle : 0;
            float maxDirectionDelta = playerId == _playerId ? MaxAngle : 0;
            for (float angle = goalDirection + minDirectionDelta; angle <= goalDirection + maxDirectionDelta; angle += AngleStep)
            {
                HitInfo bestForceHit = new HitInfo(this, playerId, angle, MinForce);
                for (float force = MinForce; force <= MaxForce; force += LinearSearchStep)
                {
                    HitInfo newForceHit = new HitInfo(this, playerId, angle, force);
                    if (newForceHit.CompareTo(bestForceHit) < 0 && Random.value < 0.9)
                    {
                        bestForceHit = newForceHit;
                    }
                }

                float forceL = Math.Max(MinForce, bestForceHit.HitForce - LinearSearchStep);
                float forceR = Math.Min(MaxForce, bestForceHit.HitForce + LinearSearchStep);
                for (int step = 0; step < BinarySearchSteps; ++step)
                {
                    float   forceMl = (forceL * 2 + forceR) / 3;
                    HitInfo hitMl   = new HitInfo(this, playerId, angle, forceMl);

                    float   forceMr = (forceL + 2 * forceR) / 3;
                    HitInfo hitMr   = new HitInfo(this, playerId, angle, forceMr);

                    int comparisonResult = hitMl.CompareTo(hitMr) * (playerId == _playerId ? -1 : 1);
                    if (comparisonResult <= 0)
                    {
                        forceL = forceMl;
                    }
                    if (comparisonResult >= 0)
                    {
                        forceR = forceMr;
                    }
                }

                HitInfo newHit = new HitInfo(this, playerId, angle, (forceL + forceR) / 2);
                if (newHit.CompareTo(bestHit) < 0 && (playerId == _playerId || Random.value < 0.9))
                {
                    bestHit = newHit;
                }
            }
        }

        _gameLogic.HitBall(bestHit.PlayerId, bestHit.HitAngle, bestHit.HitForce);
    }