public EntityAction(MoveAction?moveAction, BuildAction?buildAction, AttackAction?attackAction, RepairAction?repairAction)
 {
     MoveAction   = moveAction;
     BuildAction  = buildAction;
     AttackAction = attackAction;
     RepairAction = repairAction;
 }
示例#2
0
    /// <summary>
    /// Checks both directions of a diagonal movement
    /// to see if movement or a bump resulting in an interaction is possible. Modifies
    /// the move action to switch to that direction, otherwise leaves it unmodified.
    /// Prioritizes the following when there are multiple options:
    /// 1. Move into empty space if either direction has it
    /// 2. Push an object if either direction has it
    /// 3. Open a door if either direction has it
    ///
    /// When both directions have the same condition (both doors or pushable objects), x will be preferred to y
    /// </summary>
    /// <param name="state">current state to try to slide from</param>
    /// <param name="action">current player action (which should have a diagonal movement). Will be modified if a slide is performed</param>
    /// <returns>bumptype of the final direction of movement if action is modified. Null otherwise</returns>
    private BumpType?TrySlide(PlayerState state, ref PlayerAction action)
    {
        Vector2Int direction = action.Direction();

        if (Math.Abs(direction.x) + Math.Abs(direction.y) < 2)
        {
            //not diagonal, do nothing
            return(null);
        }

        Vector2Int xDirection = new Vector2Int(direction.x, 0);
        Vector2Int yDirection = new Vector2Int(0, direction.y);
        BumpType   xBump      = MatrixManager.GetBumpTypeAt(state.WorldPosition.RoundToInt(), xDirection, gameObject);
        BumpType   yBump      = MatrixManager.GetBumpTypeAt(state.WorldPosition.RoundToInt(), yDirection, gameObject);

        MoveAction?newAction = null;
        BumpType?  newBump   = null;

        if (xBump == BumpType.None)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.None)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }
        else if (xBump == BumpType.Push)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.Push)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }
        else if (xBump == BumpType.ClosedDoor)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.ClosedDoor)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }

        if (newAction.HasValue)
        {
            action.moveActions = new int[] { (int)newAction };
            return(newBump);
        }
        else
        {
            return(null);
        }
    }
示例#3
0
        public IEnumerable <Status> FindPath()
        {
            Vector3 target = Entity.Position;

            if (Creature.AI.PositionConstraint.Contains(target) == ContainmentType.Disjoint)
            {
                target = MathFunctions.RandVector3Box(Creature.AI.PositionConstraint);
            }

            List <MoveAction> path = new List <MoveAction>();
            VoxelHandle       curr = Creature.Physics.CurrentVoxel;
            var storage            = new MoveActionTempStorage();

            for (int i = 0; i < PathLength; i++)
            {
                var actions = Creature.AI.Movement.GetMoveActions(new MoveState()
                {
                    Voxel = curr
                }, new List <GameComponent>(), storage);

                MoveAction?bestAction = null;
                float      bestDist   = float.MinValue;
                foreach (MoveAction action in actions)
                {
                    float dist = (action.DestinationVoxel.WorldPosition - target).LengthSquared();

                    if (dist > bestDist)
                    {
                        bestDist   = dist;
                        bestAction = action;
                    }
                }

                if (bestAction.HasValue &&
                    !path.Any(p => p.DestinationVoxel.Equals(bestAction.Value.DestinationVoxel) && p.MoveType == bestAction.Value.MoveType &&
                              Creature.AI.PositionConstraint.Contains(bestAction.Value.DestinationVoxel.WorldPosition + Vector3.One * 0.5f) == ContainmentType.Contains))
                {
                    MoveAction action = bestAction.Value;
                    action.DestinationVoxel = curr;
                    path.Add(action);
                    curr = bestAction.Value.DestinationVoxel;
                }
                else
                {
                    break;
                }
            }
            if (path.Count > 0)
            {
                Creature.AI.Blackboard.SetData("FleePath", path);
                yield return(Status.Success);
            }
            else
            {
                yield return(Status.Fail);
            }
        }
示例#4
0
        private static EntityAction GetEntityAction(PlayerView playerView, Entity entity)
        {
            int myId = playerView.MyId;
            EntityProperties properties  = playerView.EntityProperties[entity.EntityType];
            MoveAction?      moveAction  = null;
            BuildAction?     buildAction = null;

            if (properties.CanMove)
            {
                moveAction = new MoveAction(
                    new Vec2Int(playerView.MapSize - 1, playerView.MapSize - 1),
                    true,
                    true);
            }
            else if (properties.Build != null)
            {
                EntityType entityType   = properties.Build.Value.Options[0];
                int        currentUnits = 0;
                foreach (var otherEntity in playerView.Entities)
                {
                    if (otherEntity.PlayerId != null && otherEntity.PlayerId == myId &&
                        otherEntity.EntityType == entityType)
                    {
                        currentUnits++;
                    }
                }

                if ((currentUnits + 1) * playerView.EntityProperties[entityType].PopulationUse <= properties.PopulationProvide)
                {
                    buildAction = new BuildAction(
                        entityType,
                        new Vec2Int(entity.Position.X + properties.Size, entity.Position.Y + properties.Size - 1));
                }
            }

            EntityType[] validAutoAttackTargets;
            if (entity.EntityType == EntityType.BuilderUnit)
            {
                validAutoAttackTargets = new EntityType[] { EntityType.Resource };
            }
            else
            {
                validAutoAttackTargets = new EntityType[0];
            }

            EntityAction entityAction = new EntityAction(
                moveAction,
                buildAction,
                new AttackAction(
                    null,
                    new AutoAttack(properties.SightRange, validAutoAttackTargets)),
                null);

            return(entityAction);
        }
示例#5
0
        public IEnumerable <Status> FindRandomPath()
        {
            Vector3 target = MathFunctions.RandVector3Cube() * Radius + Creature.AI.Position;

            if (Creature.AI.PositionConstraint.Contains(target) == ContainmentType.Disjoint)
            {
                target = MathFunctions.RandVector3Box(Creature.AI.PositionConstraint);
            }
            if (Is2D)
            {
                target.Y = Creature.AI.Position.Y;
            }
            List <MoveAction> path = new List <MoveAction>();
            VoxelHandle       curr = Creature.Physics.CurrentVoxel;

            for (int i = 0; i < PathLength; i++)
            {
                var actions = Creature.AI.Movement.GetMoveActions(new MoveState()
                {
                    Voxel = curr
                }, Creature.World.OctTree);

                MoveAction?bestAction = null;
                float      bestDist   = float.MaxValue;
                foreach (MoveAction action in actions)
                {
                    if (Is2D && (action.MoveType == MoveType.Climb || action.MoveType == MoveType.ClimbWalls))
                    {
                        continue;
                    }
                    float dist = (action.DestinationVoxel.WorldPosition - target).LengthSquared();

                    if (dist < bestDist)
                    {
                        bestDist   = dist;
                        bestAction = action;
                    }
                }

                if (bestAction.HasValue &&
                    !path.Any(p => p.DestinationVoxel.Equals(bestAction.Value.DestinationVoxel) && p.MoveType == bestAction.Value.MoveType &&
                              Creature.AI.PositionConstraint.Contains(bestAction.Value.DestinationVoxel.WorldPosition + Vector3.One * 0.5f) == ContainmentType.Contains))
                {
                    MoveAction action = bestAction.Value;
                    action.DestinationVoxel = curr;
                    path.Add(action);
                    curr = bestAction.Value.DestinationVoxel;
                }
                else
                {
                    break;
                }
            }
            if (path.Count > 0)
            {
                Creature.AI.Blackboard.SetData("RandomPath", path);
                yield return(Status.Success);
            }
            else
            {
                yield return(Status.Fail);
            }
        }
示例#6
0
        public IEnumerable <Status> FindGreedyPath()
        {
            Vector3 target = Target.Position;

            if (Is2D)
            {
                target.Y = Creature.AI.Position.Y;
            }
            List <MoveAction> path = new List <MoveAction>();
            var curr    = Creature.Physics.CurrentVoxel;
            var bodies  = Agent.World.PlayerFaction.OwnedObjects.Where(o => o.Tags.Contains("Teleporter")).ToList();
            var storage = new MoveActionTempStorage();

            for (int i = 0; i < PathLength; i++)
            {
                IEnumerable <MoveAction> actions =
                    Creature.AI.Movement.GetMoveActions(new MoveState()
                {
                    Voxel = curr
                }, bodies, storage);

                MoveAction?bestAction = null;
                float      bestDist   = float.MaxValue;

                foreach (MoveAction action in actions)
                {
                    // Prevents a stack overflow due to "DestroyObject" task creating a FollowPathAct!
                    if (action.MoveType == MoveType.DestroyObject)
                    {
                        continue;
                    }
                    float dist = (action.DestinationVoxel.WorldPosition - target).LengthSquared();

                    if (dist < bestDist)
                    {
                        bestDist   = dist;
                        bestAction = action;
                    }
                }

                Vector3 half = Vector3.One * 0.5f;
                if (bestAction.HasValue &&
                    !path.Any(p => p.DestinationVoxel.Equals(bestAction.Value.DestinationVoxel) && p.MoveType == bestAction.Value.MoveType))
                {
                    path.Add(bestAction.Value);
                    MoveAction action = bestAction.Value;
                    action.DestinationVoxel = curr;
                    curr       = bestAction.Value.DestinationVoxel;
                    bestAction = action;

                    if (((bestAction.Value.DestinationVoxel.WorldPosition + half) - target).Length() < Threshold)
                    {
                        break;
                    }
                }
            }

            if (path.Count > 0)
            {
                Creature.AI.Blackboard.SetData("RandomPath", path);
                yield return(Status.Success);
            }
            else
            {
                yield return(Status.Fail);
            }
        }
示例#7
0
        public IEnumerable <Status> FindGreedyPath()
        {
            Vector3 target = Target.Position;

            if (Is2D)
            {
                target.Y = Creature.AI.Position.Y;
            }
            List <MoveAction> path = new List <MoveAction>();
            var curr = Creature.Physics.CurrentVoxel;

            for (int i = 0; i < PathLength; i++)
            {
                IEnumerable <MoveAction> actions =
                    Creature.AI.Movement.GetMoveActions(curr);

                MoveAction?bestAction = null;
                float      bestDist   = float.MaxValue;

                foreach (MoveAction action in actions)
                {
                    float dist = (action.DestinationVoxel.WorldPosition - target).LengthSquared();

                    if (dist < bestDist)
                    {
                        bestDist   = dist;
                        bestAction = action;
                    }
                }

                Vector3 half = Vector3.One * 0.5f;
                if (bestAction.HasValue &&
                    !path.Any(p => p.DestinationVoxel.Equals(bestAction.Value.DestinationVoxel) && p.MoveType == bestAction.Value.MoveType))
                {
                    path.Add(bestAction.Value);
                    MoveAction action = bestAction.Value;
                    action.DestinationVoxel = curr;
                    curr       = bestAction.Value.DestinationVoxel;
                    bestAction = action;

                    if (((bestAction.Value.DestinationVoxel.WorldPosition + half) - target).Length() < Threshold)
                    {
                        break;
                    }
                }
            }

            if (path.Count > 0)
            {
                path.Insert(0,
                            new MoveAction()
                {
                    Diff             = Vector3.Zero,
                    DestinationVoxel = path[0].SourceVoxel,
                    SourceVoxel      = Creature.Physics.CurrentVoxel,
                    MoveType         = MoveType.Walk
                });
                Creature.AI.Blackboard.SetData("RandomPath", path);
                yield return(Status.Success);
            }
            else
            {
                yield return(Status.Fail);
            }
        }
示例#8
0
        public IEnumerable <Status> FindRandomPath()
        {
            var target = MathFunctions.RandVector3Cube() * Radius + Creature.AI.Position;

            if (Creature.AI.PositionConstraint.Contains(target) == ContainmentType.Disjoint)
            {
                target = MathFunctions.RandVector3Box(Creature.AI.PositionConstraint);
            }
            if (Is2D)
            {
                target.Y = Creature.AI.Position.Y;
            }

            var path              = new List <MoveAction>();
            var curr              = Creature.Physics.CurrentVoxel;
            var bodies            = Agent.World.PlayerFaction.OwnedObjects.Where(o => o.Tags.Contains("Teleporter")).ToList();
            var storage           = new MoveActionTempStorage();
            var previousMoveState = new MoveState {
                Voxel = curr
            };

            for (int i = 0; i < PathLength; i++)
            {
                var actions = Creature.AI.Movement.GetMoveActions(previousMoveState, bodies, storage);

                MoveAction?bestAction = null;
                var        bestDist   = float.MaxValue;

                foreach (MoveAction action in actions)
                {
                    if (Is2D && (action.MoveType == MoveType.Climb || action.MoveType == MoveType.ClimbWalls || action.MoveType == MoveType.Fall))
                    {
                        continue;
                    }

                    float dist = (action.DestinationVoxel.WorldPosition - target).LengthSquared() * Creature.AI.Movement.Cost(action.MoveType);

                    if (dist < bestDist && !path.Any(a => a.DestinationVoxel == action.DestinationVoxel))
                    {
                        bestDist   = dist;
                        bestAction = action;
                    }
                }

                if (bestAction.HasValue &&
                    !path.Any(p => p.DestinationVoxel.Equals(bestAction.Value.DestinationVoxel) && p.MoveType == bestAction.Value.MoveType &&
                              Creature.AI.PositionConstraint.Contains(bestAction.Value.DestinationVoxel.WorldPosition + Vector3.One * 0.5f) == ContainmentType.Contains))
                {
                    MoveAction action = bestAction.Value;
                    path.Add(action);
                    previousMoveState = action.DestinationState;
                }
                else
                {
                    break;
                }
            }

            if (path.Count > 0)
            {
                Creature.AI.Blackboard.SetData("RandomPath", path);
                yield return(Status.Success);
            }
            else
            {
                yield return(Status.Fail);
            }
        }
示例#9
0
        public Action GetAction(PlayerView playerView, DebugInterface debugInterface)
        {
            Action result = new Action(new System.Collections.Generic.Dictionary <int, Model.EntityAction>());
            int    myId   = playerView.MyId;

            foreach (var entity in playerView.Entities)
            {
                if (entity.PlayerId != myId)
                {
                    continue;
                }
                EntityProperties properties  = playerView.EntityProperties[entity.EntityType];
                MoveAction?      moveAction  = null;
                BuildAction?     buildAction = null;
                if (properties.CanMove)
                {
                    moveAction = new MoveAction(
                        new Vec2Int(playerView.MapSize - 1, playerView.MapSize - 1),
                        true,
                        true
                        );
                }
                else if (properties.Build != null)
                {
                    EntityType entityType   = properties.Build.Value.Options[0];
                    int        currentUnits = 0;
                    foreach (var otherEntity in playerView.Entities)
                    {
                        if (otherEntity.PlayerId != null && otherEntity.PlayerId == myId &&
                            otherEntity.EntityType == entityType)
                        {
                            currentUnits++;
                        }
                    }
                    if ((currentUnits + 1) * playerView.EntityProperties[entityType].PopulationUse <= properties.PopulationProvide)
                    {
                        buildAction = new BuildAction(
                            entityType,
                            new Vec2Int(entity.Position.X + properties.Size, entity.Position.Y + properties.Size - 1)
                            );
                    }
                }
                EntityType[] validAutoAttackTargets;
                if (entity.EntityType == EntityType.BuilderUnit)
                {
                    validAutoAttackTargets = new EntityType[] { EntityType.Resource };
                }
                else
                {
                    validAutoAttackTargets = new EntityType[0];
                }
                result.EntityActions[entity.Id] = new EntityAction(
                    moveAction,
                    buildAction,
                    new AttackAction(
                        null,
                        new AutoAttack(properties.SightRange, validAutoAttackTargets)
                        ),
                    null
                    );
            }
            return(result);
        }