Пример #1
0
        private bool ProcessChickenUnitMoves(IList <ChickenUnit> aliveChickens)
        {
            //// TODO: [vmcl] Use bisection to get conflicting units closer to each other
            //// TODO: [vmcl] Optimize number of collision checks!
            //// TODO: [vmcl] Divide move: eg. unit couldn't move but could turn beak or vice versa

            _moveInfoStates.Clear();
            for (var unitIndex = 0; unitIndex < aliveChickens.Count; unitIndex++)
            {
                if (IsStopping())
                {
                    return(false);
                }

                var unit = aliveChickens[unitIndex];
                _moveInfoStates[unit] = MoveInfoStates.Handled;

                var moveInfo = _moveInfos.GetValueOrDefault(unit);
                if (moveInfo == null)
                {
                    continue;
                }

                DebugHelper.WriteLine(
                    "{0} is processing move {{{1}}} of chicken {{{2}}}.",
                    GetType().Name,
                    moveInfo,
                    unit);

                var movementAndNewPosition = GameHelper.GetMovementAndNewPosition(
                    unit.Position,
                    unit.BeakAngle,
                    moveInfo.MoveDirection,
                    GameConstants.ChickenUnit.DefaultRectilinearSpeed);

                var beakMovementAndNewAngle = GameHelper.GetBeakMovementAndNewAngle(unit.BeakAngle, moveInfo.BeakTurn);

                var newPositionElement = new ChickenElement(
                    movementAndNewPosition.Position,
                    beakMovementAndNewAngle.Position);
                if (HasOutOfBoardCollision(newPositionElement))
                {
                    _moveInfoStates[unit] = MoveInfoStates.RejectedBoardCollision;
                    DebugHelper.WriteLine(
                        "Blocked collision of chicken {{{0}}} with game board border.",
                        unit);
                    continue;
                }

                ChickenUnit conflictingChicken = null;

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var conflictingIndex = 0; conflictingIndex < aliveChickens.Count; conflictingIndex++)
                {
                    var aliveChicken = aliveChickens[conflictingIndex];
                    if (aliveChicken == unit)
                    {
                        continue;
                    }

                    if (CollisionDetector.CheckCollision(newPositionElement, aliveChicken.GetElement()))
                    {
                        conflictingChicken = aliveChicken;
                        break;
                    }
                }

                if (conflictingChicken != null)
                {
                    _moveInfoStates[unit] = MoveInfoStates.RejectedOtherUnitCollision;
                    DebugHelper.WriteLine(
                        "Blocked collision of chicken {{{0}}} with {{{1}}}.",
                        unit,
                        conflictingChicken);
                    continue;
                }

                unit.SetMovement(movementAndNewPosition.Movement, beakMovementAndNewAngle.Movement);

                DebugHelper.WriteLine("Chicken {{{0}}} has moved.", unit);
            }

            return(true);
        }
Пример #2
0
        private void ProcessEngineStep()
        {
            var aliveChickens = this.AliveChickens
                                .Where(item => !item.IsDead && item.LogicExecutor.Error == null)
                                .ToList();

            _moveInfos.Clear();
            _previousMoves.Clear();
            for (var logicIndex = 0; logicIndex < _logicExecutors.Count; logicIndex++)
            {
                var logic = _logicExecutors[logicIndex];

                lock (logic.UnitsMovesLock)
                {
                    foreach (var pair in logic.UnitsMoves)
                    {
                        _moveInfos.Add(pair.Key, pair.Value);
                        _previousMoves.Add(pair.Key, pair.Value);
                    }
                }
            }

            if (!ProcessChickenUnitMoves(aliveChickens))
            {
                return;
            }

            // Processing new shot units
            var shootingMoves = _moveInfos.Where(item => !item.Key.IsDead && item.Value.FireMode != FireMode.None);

            ProcessNewShots(shootingMoves);

            #region Processing Shot Collisions

            foreach (var shotUnit in _shotUnitsDirect)
            {
                var movement = GameHelper.GetMovement(
                    shotUnit.Angle,
                    MoveDirection.MoveForward,
                    GameConstants.ShotUnit.DefaultRectilinearSpeed);

                shotUnit.SetMovement(movement);
                DebugHelper.WriteLine("Shot {{{0}}} has moved.", shotUnit);

                var hasOutOfBoardCollision = HasOutOfBoardCollision(shotUnit.GetElement());
                if (hasOutOfBoardCollision)
                {
                    shotUnit.Exploded = true;
                    DebugHelper.WriteLine("Shot {{{0}}} has exploded outside of game board.", shotUnit);
                }
            }

            var injuredChickens = new List <ChickenUnit>(aliveChickens.Count);
            for (var index = 0; index < _shotUnitsDirect.Count; index++)
            {
                var shotUnit = _shotUnitsDirect[index];

                for (var otherIndex = index + 1; otherIndex < _shotUnitsDirect.Count; otherIndex++)
                {
                    var otherShotUnit = _shotUnitsDirect[otherIndex];

                    var isCollision = CollisionDetector.CheckCollision(
                        shotUnit.GetElement(),
                        otherShotUnit.GetElement());
                    if (!isCollision)
                    {
                        continue;
                    }

                    shotUnit.Exploded      = true;
                    otherShotUnit.Exploded = true;

                    DebugHelper.WriteLine(
                        "Mutual annihilation of shots {{{0}}} and {{{1}}}.",
                        shotUnit,
                        otherShotUnit);
                }

                var shotElement = shotUnit.GetElement();

                injuredChickens.Clear();

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var chickenIndex = 0; chickenIndex < aliveChickens.Count; chickenIndex++)
                {
                    var aliveChicken = aliveChickens[chickenIndex];
                    if (!aliveChicken.IsDead &&
                        CollisionDetector.CheckCollision(shotElement, aliveChicken.GetElement()))
                    {
                        injuredChickens.Add(aliveChicken);
                    }
                }

                foreach (var injuredChicken in injuredChickens)
                {
                    shotUnit.Exploded = true; //// TODO [vmcl] Move out of loop

                    injuredChicken.IsDead   = true;
                    injuredChicken.KilledBy = shotUnit.Owner;
                    var suicide = shotUnit.Owner == injuredChicken;
                    if (!suicide)
                    {
                        shotUnit.Owner.KillCount++;
                    }

                    DebugHelper.WriteLine(
                        "Shot {{{0}}} has exploded and killed {{{1}}}{2}.",
                        shotUnit,
                        injuredChicken,
                        suicide ? " [suicide]" : string.Empty);
                }
            }

            #endregion

            UpdateLastGamePresentation();

            _aliveChickensDirect.RemoveAll(item => item.IsDead);
            _aliveChickensDirect.DoForEach(item => item.ApplyMovement());

            _shotUnitsDirect.RemoveAll(item => item.Exploded);
            _shotUnitsDirect.DoForEach(item => item.ApplyMovement());

            var aliveTeams = _aliveChickensDirect.Select(item => item.Team).Distinct().ToList();
            if (aliveTeams.Count > 1)
            {
                return;
            }

            _finalizingStage = true;
            if (_shotUnitsDirect.Any())
            {
                return;
            }

            var winningTeam = aliveTeams.SingleOrDefault();

            ChickenUnitLogic winningLogic;
            switch (winningTeam)
            {
            case GameTeam.Light:
                winningLogic = _lightTeamLogicExecutor.Logic;
                break;

            case GameTeam.Dark:
                winningLogic = _darkTeamLogicExecutor.Logic;
                break;

            default:
                winningLogic = null;
                break;
            }

            RaiseGameEnded(winningTeam, winningLogic);
        }