Example #1
0
 private Move(TurnPlan owner, RelativeDirection direction, TileVector destination, int energyCost)
 {
     Owner       = owner;
     Direction   = direction;
     Destination = destination;
     EnergyCost  = energyCost;
 }
Example #2
0
 /// <summary>
 /// Construct a Move which represents a unit staying completely stationary.
 /// </summary>
 /// <param name="owner">the TurnPlan which created this move</param>
 /// <returns></returns>
 public static Move Halt(TurnPlan owner)
 {
     return(new Move(owner, RelativeDirection.Forward, owner.Unit.Position, 0));
 }
Example #3
0
        /// <summary>
        /// Construct a Move which represents a unit turning in place.
        /// </summary>
        /// <param name="owner">the TurnPlan which created this move</param>
        /// <param name="direction">the RelativeDirection for it to turn to</param>
        /// <returns></returns>
        public static Move Turn(TurnPlan owner, RelativeDirection direction)
        {
            var cost = direction == RelativeDirection.Forward ? 0 : 1;

            return(new Move(owner, direction, owner.Unit.Position, cost));
        }
Example #4
0
        /// <summary>
        /// Constructe a Move which represents a turn followed by a single tile step.
        /// </summary>
        /// <param name="owner">the TurnPlan which created this move</param>
        /// <param name="direction">the RelativeDirection for it to turn and move in</param>
        /// <returns></returns>
        public static Move Step(TurnPlan owner, RelativeDirection direction)
        {
            var destination = owner.Unit.Position + owner.Unit.Turn(direction);

            return(new Move(owner, direction, destination, 2));
        }
        /// <summary>
        /// Simulate the game for a single turn.
        /// </summary>
        public void DoTurn()
        {
            var activeUnits = new Dictionary <Unit, TurnPlan>();

            foreach (var unit in _units)
            {
                unit.Reset();
                activeUnits.Add(unit, unit.GetMovementPlan(_world));
            }

                        #if DEBUG
            DebugLogFrame();
                        #endif

            while (activeUnits.Count > 0)             // main loop: iterate through each simulation frame
            {
                // STEP 1: COMBAT DETERMINATION
                var pendingCombat = new HashSet <Combat>();                // stops duplication of the same combat
                var unitsInCombat = new HashSet <Unit>();

                foreach (var unit in activeUnits.Keys)
                {
                    foreach (var adj in unit.Position.Adjacent().Select(pos => _world[pos]))                     // for each adjacent Hex
                    {
                        if (adj == null)
                        {
                            continue;
                        }

                        var neighbour = adj.Occupant;
                        if (neighbour != null && neighbour.Owner != unit.Owner)
                        {
                            pendingCombat.Add(new Combat(unit, neighbour));
                            unitsInCombat.Add(unit);
                            unitsInCombat.Add(neighbour);
                        }
                    }
                }

                // STEP 2: COMBAT RESOLUTION
                var pendingCombatSorted = new List <Combat>(pendingCombat);
                pendingCombatSorted.Sort(Combat.PriorityComparer);                      // sort by priortiy

                foreach (var combat in pendingCombatSorted)
                {
                    var unit1 = combat.Unit1;
                    var unit2 = combat.Unit2;

                    if (!unit1.IsDead() && !unit2.IsDead())
                    {
                        combat.Apply();

                        FinaliseCombat(unit1, unit2, activeUnits);                              // lambda/local-function would be
                        FinaliseCombat(unit2, unit1, activeUnits);                              // ideal here! outdated version of C#
                    }
                }

                // STEP 3: MOVE PRE-PROCESSING
                var moveDestinations = new Dictionary <TileVector, List <MoveResolver> >(); // where units want to move to
                var moveOrigins      = new Dictionary <TileVector, MoveResolver>();         // where units are moving from

                foreach (var unit in _units)                                                // collect all units' moves into the Dictionaries, using plans
                {
                    TurnPlan plan = null;
                    if (activeUnits.ContainsKey(unit))                          // only active units can make moves - bind a plan
                    {
                        plan = activeUnits[unit];
                        if (!plan.IsActive())                                           // unit can no longer make moves, so remove from active units
                        {
                            activeUnits.Remove(unit);
                            plan = null;                                                        // unbind plan for this frame
                        }
                    }

                    var canMove   = plan != null && !unitsInCombat.Contains(plan.Unit);
                    var move      = canMove? plan.GetNextMove() : null;
                    var mayVacate = canMove && move.IsStep();

                    // if move is a step, moves here are conditional upon it. otherwise, deny outright
                    var resolver = mayVacate ? MoveResolver.Of(move) : MoveResolver.Deny();
                    moveOrigins.Add(unit.Position, resolver);

                    if (mayVacate)                     // add resolver to the move's intended destination for processing later
                    {
                        var hex = _world[move.Destination];
                        if (hex != null && !hex.Impassable)                         // if target is valid
                        {
                            List <MoveResolver> movesToDestination;
                            if (moveDestinations.ContainsKey(move.Destination))
                            {
                                movesToDestination = moveDestinations[move.Destination];
                            }
                            else                             // initialise the list if it doesn't exist yet
                            {
                                movesToDestination = new List <MoveResolver>(6);
                                moveDestinations.Add(move.Destination, movesToDestination);
                            }
                            movesToDestination.Add(resolver);
                        }
                        else
                        {
                            resolver.Resolve(false);                            // reject if move is illegal
                        }
                    }
                }

                // STEP 4: MOVE CONFLICT RESOLUTION
                foreach (var entry in moveDestinations)                 // check all future mech positions, finalise moves
                {
                    var destination = entry.Key;
                    var moves       = entry.Value;

                    var best = 0;
                    for (var i = 1; i < moves.Count; i++)                       // reject all moves here except the best one
                    {
                        if (Move.PriorityComparer.Compare(moves[i].Move, moves[best].Move) > 0)
                        {
                            moves[best].Resolve(false);
                            best = i;
                        }
                        else                            // not the best move: reject
                        {
                            moves[i].Resolve(false);
                        }
                    }
                    var dependency = moveOrigins.ContainsKey(destination) ? moveOrigins[destination] : null;

                    if (dependency != null)
                    {
                        moves[best].SetParent(dependency);
                    }
                    else
                    {
                        moves[best].Resolve(true);
                    }
                }

                                #if DEBUG
                DebugLogFrame();
                                #endif
            }
            RoundNumber++;
        }
Example #6
0
 public TurnPlan GetMovementPlan(World world)
 {
     LastMove     = _currentMove;
     _currentMove = _moveMethod(this, world);
     return(_currentMove);
 }