コード例 #1
0
        void Start()
        {
            ani    = GetComponent <Animator>();
            sprite = GetComponent <SpriteRenderer>();


            List <Node> rootChildren      = new List <Node>();
            List <Node> animationChildren = new List <Node>();

            Npeaceful        = new NodeAction(WithoutOpponent);
            Nattack1         = new NodeAction(OneOpponent);
            Nattack2         = new NodeAction(TwoOpponent);
            NattackAndDefend = new NodeAction(OneOpponentPlusOne);
            Nreversal        = new NodeAction(Reversal);
            Ndrawray         = new NodeAction(DrawRay);

            ani.SetInteger("searchStatus", 0);
            animationChildren.Add(Nreversal);
            animationChildren.Add(Npeaceful);
            animationChildren.Add(Nattack1);
            animationChildren.Add(Nattack2);
            animationChildren.Add(NattackAndDefend);

            Nanimation = new NodeSelector(animationChildren);

            rootChildren.Add(Ndrawray);
            rootChildren.Add(Nanimation);

            Nroot = new NodeSequence(rootChildren);
        }
コード例 #2
0
 public ParameterSetResult(NodeSequence arguments, ParameterSet parameterSet, object setInstance, IEnumerable<BindError> errors)
 {
     this.Arguments = arguments;
     this.ParameterSet = parameterSet;
     this.Object = setInstance;
     this.Errors = errors.ToArray();
 }
コード例 #3
0
 public BuildContext(NodeSequence sequence, ParameterSet paramSet, object instance)
 {
     this.Sequence = sequence;
     this.Instance = instance;
     this.ParameterSet = paramSet;
     this.Errors = new List<BindError>();
     this.RemainingParameters = new List<Parameter>(paramSet.OrderBy(p => p.Position.HasValue ? p.Position.Value : int.MinValue));
 }
コード例 #4
0
    private NodeRoot GetNodeRoot(NodeValue nodeValue)
    {
        NodeRoot nodeRoot = null;

        switch (nodeValue.NodeType)
        {
        case NodeType.Select:        // 选择节点
            nodeRoot = new NodeSelect();
            break;

        case NodeType.Sequence:      // 顺序节点
            nodeRoot = new NodeSequence();
            break;

        case NodeType.Decorator:     // 修饰节点
            nodeRoot = new NodeDecorator();
            break;

        case NodeType.Random:        // 随机节点
            nodeRoot = new NodeRandom();
            break;

        case NodeType.Parallel:      // 并行节点
            nodeRoot = new NodeParallel();
            break;

        case NodeType.Condition:     // 条件节点
            nodeRoot = GetLeafNode(nodeValue);
            break;

        case NodeType.Action:        // 行为节点
            nodeRoot = GetLeafNode(nodeValue);
            break;
        }

        return(nodeRoot);
    }
コード例 #5
0
ファイル: SPL1_80.cs プロジェクト: playgen/it-alert
        // TODO: this should be parameterized further and read from config
        public override SimulationScenario GenerateScenario()
        {
            #region configuration

            #region graph

            var node00      = new NodeConfig(0, 0, AntivirusWorkstation.Archetype, "Antivirus");
            var node10      = new NodeConfig(1, 0, SubsystemNode.Archetype);
            var node20      = new NodeConfig(2, 0, SubsystemNode.Archetype);
            var node01      = new NodeConfig(0, 1, SubsystemNode.Archetype);
            var node11      = new NodeConfig(1, 1, SubsystemNode.Archetype);
            var node21      = new NodeConfig(2, 1, SubsystemNode.Archetype);
            var nodeConfigs = new NodeConfig[]
            {
                node00,
                node10,
                node20,
                node01,
                node11,
                node21,
            };
            ConfigurationHelper.ProcessNodeConfigs(nodeConfigs);

            var connection0010 = new EdgeConfig(node00.Id, EdgeDirection.East, node10.Id, ConnectionNode.Archetype);
            var connection1000 = connection0010.Reciprocate();

            var connection1020 = new EdgeConfig(node10.Id, EdgeDirection.East, node20.Id, ConnectionNode.Archetype);
            var connection2010 = connection1020.Reciprocate();

            var connection0001 = new EdgeConfig(node00.Id, EdgeDirection.South, node01.Id, ConnectionNode.Archetype);
            var connection0100 = connection0001.Reciprocate();

            var connection0111 = new EdgeConfig(node01.Id, EdgeDirection.East, node11.Id, ConnectionNode.Archetype);
            var connection1101 = connection0111.Reciprocate();

            var connection1121 = new EdgeConfig(node11.Id, EdgeDirection.East, node21.Id, ConnectionNode.Archetype);
            var connection2111 = connection1121.Reciprocate();

            var connection2021 = new EdgeConfig(node20.Id, EdgeDirection.South, node21.Id, ConnectionNode.Archetype);
            var connection2120 = connection2021.Reciprocate();

            var edgeConfigs = new EdgeConfig[]
            {
                connection0010,
                connection1000,
                connection1020,
                connection2010,
                connection0001,
                connection0100,
                connection0111,
                connection1101,
                connection1121,
                connection2111,
                connection2021,
                connection2120,
            };

            #endregion

            var archetypes = new List <Archetype>
            {
                SubsystemNode.Archetype,
                ConnectionNode.Archetype,
                Player.Archetype,
                ScannerTool.Archetype,
                AntivirusWorkstation.Archetype,
                AnalyserActivator.Archetype,
                CaptureTool.Archetype,
                AntivirusTool.Archetype,
                RedVirus80,
            };

            var configuration = ConfigurationHelper.GenerateConfiguration(nodeConfigs, edgeConfigs, null, archetypes);
            configuration.RNGSeed = 561122999;

            #endregion

            var scenario = new SimulationScenario(ScenarioInfo)
            {
                Configuration = configuration,

                PlayerConfigFactory = new StartingLocationSequencePlayerConfigFactory(Player.Archetype, new[] { node00.Id, node20.Id, node01.Id, node21.Id }),
                Sequence            = new List <SequenceFrame <Simulation, SimulationConfiguration> >(),

                Scoring = SimulationScenario.ScoringMode.Full,
            };

            var spawnSequence = new NodeSequence(new[]
            {
                // offset by one vs config
                node00,
                node20,
                node10,
                node00,
                node20,
                node01,
                node10,
                node01,
            });

            #region frames

            // 1
            scenario.Sequence.Add(
                new SimulationFrame()
            {
                OnEnterActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new SetTimer <Simulation, SimulationConfiguration>(scenario.TimeLimitSeconds.Value),
                    new CreateItem(ScannerTool.Archetype, node10),
                    new CreateItem(ScannerTool.Archetype, node20),
                    new CreateItem(CaptureTool.Archetype, node10),
                    new CreateItem(CaptureTool.Archetype, node10),
                },
                ExitCondition = new WaitForTicks(1),
                OnExitActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new CreateMalware(RedVirus80, node01)
                },
            }
                );

            // 2
            scenario.Sequence.Add(
                new SimulationFrame()
            {
                OnEnterActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                },
                OnTickActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new ConditionalAction <Simulation, SimulationConfiguration>(new NodeSequenceAction(spawnSequence, ec => new CreateMalware(RedVirus80, ec)),
                                                                                new OnEvent <AntivirusActivationEvent>(aae => aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.SoloExtermination ||
                                                                                                                       aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.CoopExtermination)),
                },
                ExitCondition = new WaitForTimer(),
                OnExitActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new EndGame(EndGameState.Neutral),
                },
            }
                );

            #endregion

            return(scenario);
        }
コード例 #6
0
ファイル: Student.cs プロジェクト: Hengle/BehaviorTree
    /// <summary>
    /// 初始化添加行为树节点
    /// </summary>
    private void Init()
    {
        // 顺序节点 1
        NodeSequence nodeSequence_1 = new NodeSequence();

        // 顺序节点 1 添加到根节点
        rootNode.AddNode(nodeSequence_1);

        #region 是否饿了
        // 条件节点 1.1
        NodeConditionHungry nodeConditionHungry_1_1 = new NodeConditionHungry();
        nodeConditionHungry_1_1.SetStudent(this);
        // 条件节点 1.1 添加到 顺序节点1
        nodeSequence_1.AddNode(nodeConditionHungry_1_1);
        #endregion

        #region  择节点 1.2
        {
            // 选择节点1.2
            NodeSelect nodeSelect_1_2 = new NodeSelect();
            nodeSequence_1.AddNode(nodeSelect_1_2);

            // 节点 1.2.1 是否有饭
            NodeConditionHasFood nodeConditionHasFood_1_2_1 = new NodeConditionHasFood();
            nodeConditionHasFood_1_2_1.SetStudent(this);
            nodeSelect_1_2.AddNode(nodeConditionHasFood_1_2_1);

            // 顺序节点 1.2.2
            NodeSequence nodeSequence_1_2_2 = new NodeSequence();
            nodeSelect_1_2.AddNode(nodeSequence_1_2_2);

            // 行为节点 1.2.2.1 走到厨房
            NodeActionMove nodeActionMove_1_2_2_1 = new NodeActionMove();
            nodeActionMove_1_2_2_1.SetStudent(this);
            nodeActionMove_1_2_2_1.SetTarget("Cooking");
            nodeActionMove_1_2_2_1.SetTr(transform);
            nodeSequence_1_2_2.AddNode(nodeActionMove_1_2_2_1);

            // 行为节点 1.2.2.2 做饭
            NodeActionCooking nodeActionCooking_1_2_2_2 = new NodeActionCooking();
            nodeActionCooking_1_2_2_2.SetStudent(this);
            nodeSequence_1_2_2.AddNode(nodeActionCooking_1_2_2_2);
        }
        #endregion

        #region 走到餐桌
        {
            // 行为节点 1.3 走到餐桌
            NodeActionMove nodeActionMove_1_3 = new NodeActionMove();
            nodeActionMove_1_3.SetStudent(this);
            nodeActionMove_1_3.SetTarget("Food");
            nodeActionMove_1_3.SetTr(transform);
            nodeSequence_1.AddNode(nodeActionMove_1_3);
        }
        #endregion

        #region 吃饭
        {
            // 行为节点 1.4 吃饭
            NodeActionEat nodeActionEat_1_4 = new NodeActionEat();
            nodeActionEat_1_4.SetStudent(this);
            nodeSequence_1.AddNode(nodeActionEat_1_4);
        }
        #endregion
    }
コード例 #7
0
    private void Init()
    {
        CreateTarget(true);

        //patrol
        _patrol = new PatrolActionNode(transform, _target, this);

        //destination sequence
        _reachTarget       = new ReachTargetActionNode(transform, _target);
        _setNewDestination = new SetTargetPositionActionNode(_target, new Bounds(Vector3.zero, Vector3.one * 100));
        List <BehaviourNode> destinationNodes = new List <BehaviourNode>();

        destinationNodes.Add(_reachTarget);
        destinationNodes.Add(_setNewDestination);
        _destinationSequence = new NodeSequence(destinationNodes);

        //free from orbit sequence
        _stuck = new StuckActionNode(transform, _target);
        _free  = new FreeFromOrbitActionNode(transform, _target);
        List <BehaviourNode> orbitNodes = new List <BehaviourNode>();

        orbitNodes.Add(_stuck);
        orbitNodes.Add(_free);
        _inOrbitSequence = new NodeSequence(orbitNodes);

        //movement selector
        List <BehaviourNode> movementNodes = new List <BehaviourNode>();

        movementNodes.Add(_destinationSequence);
        movementNodes.Add(_inOrbitSequence);
        _movementSelector = new NodeSelector(movementNodes);

        //enemy sequence
        //encounter
        _encounter = new EncounterActionNode(transform, this, FindObjectsOfType <Enemy>());

        //small enemy
        _checkEnemySmall = new SmallEnemyActionNode(this);
        _aim             = new AimActionNode(transform, _layerMask, this);
        _shoot           = new ShootActionNode(transform, this);
        List <BehaviourNode> smallEnemyNodes = new List <BehaviourNode>();

        smallEnemyNodes.Add(_checkEnemySmall);
        smallEnemyNodes.Add(_aim);
        smallEnemyNodes.Add(_shoot);
        _smallEnemy = new NodeSequence(smallEnemyNodes);

        //teleport - not small enemy
        _teleport = new TeleportActionNode(transform, this);

        //handle enemy selector
        List <BehaviourNode> handleEnemyNodes = new List <BehaviourNode>();

        handleEnemyNodes.Add(_smallEnemy);
        handleEnemyNodes.Add(_teleport);
        _handleEnemySelector = new NodeSelector(handleEnemyNodes);

        //enemy sequence
        List <BehaviourNode> enemyNodes = new List <BehaviourNode>();

        enemyNodes.Add(_encounter);
        enemyNodes.Add(_handleEnemySelector);
        _enemySequence = new NodeSequence(enemyNodes);

        //events selector
        List <BehaviourNode> eventNodes = new List <BehaviourNode>();

        eventNodes.Add(_movementSelector);
        eventNodes.Add(_enemySequence);
        _eventSelector = new NodeSelector(eventNodes);


        //initializing main sequence
        List <BehaviourNode> mainLoopNodes = new List <BehaviourNode>();

        mainLoopNodes.Add(_patrol);
        mainLoopNodes.Add(_eventSelector);
        _mainLoop = new NodeSequence(mainLoopNodes);
    }
コード例 #8
0
    void Init()
    {
        NodeSequence nodeSequence_1 = new NodeSequence();

        rootNode.AddNode(nodeSequence_1);

        #region 条件 1.1 是否饿了
        {
            NodeConditionHungry cond_1_1 = new NodeConditionHungry();
            cond_1_1.SetActor(this);
            nodeSequence_1.AddNode(cond_1_1);
        }
        #endregion

        #region  择条件 1.2 是否有饭
        {
            NodeSelect sel_1_2 = new NodeSelect();
            nodeSequence_1.AddNode(sel_1_2);

            // 1.2.1 是否有饭
            NodeConditionHasFood hasFood_1_2_1 = new NodeConditionHasFood();
            hasFood_1_2_1.SetActor(this);
            sel_1_2.AddNode(hasFood_1_2_1);

            // 没有饭的话, 走去厨房 => 做饭
            // 1.2.2 顺序节点
            NodeSequence sequence_1_2_2 = new NodeSequence();
            sel_1_2.AddNode(sequence_1_2_2);
            // 1.2.2.1 走厨房
            NodeActionMove move_1_2_2_1 = new NodeActionMove();
            move_1_2_2_1.SetActor(this);
            move_1_2_2_1.myTransform     = this.transform;
            move_1_2_2_1.targetTransform = doCookingTransform;
            sequence_1_2_2.AddNode(move_1_2_2_1);
            // 1.2.2.2 做饭
            NodeActionCooking cooking_1_2_2_2 = new NodeActionCooking();
            cooking_1_2_2_2.SetActor(this);
            sequence_1_2_2.AddNode(cooking_1_2_2_2);
        }
        #endregion
        #region 1.3 去餐桌
        {
            NodeActionMove move_1_3 = new NodeActionMove();
            move_1_3.SetActor(this);
            move_1_3.myTransform     = this.transform;
            move_1_3.targetTransform = eatFoodTransform;

            nodeSequence_1.AddNode(move_1_3);
        }
        #endregion

        #region 1.4 吃饭
        {
            NodeActionEat eat_1_4 = new NodeActionEat();
            eat_1_4.SetActor(this);
            nodeSequence_1.AddNode(eat_1_4);
        }
        #endregion

        #region 2
        // 并行节点
        NodeParallel p_2 = new NodeParallel();
        rootNode.AddNode(p_2);

        // 2.1 是否有钱
        NodeConditionHasMoney hasMoney_2_1 = new NodeConditionHasMoney();
        p_2.AddNode(hasMoney_2_1);

        // 2.2 走去酒馆
        NodeSequence seq_saloon = new NodeSequence();
        p_2.AddNode(seq_saloon);

        NodeActionMove move_2_2 = new NodeActionMove();
        move_2_2.myTransform     = this.transform;
        move_2_2.targetTransform = saloonTransform;
        seq_saloon.AddNode(move_2_2);
        // 2.3 随机点一份酒水
        NodeRandom r_2_3 = new NodeRandom();
        seq_saloon.AddNode(r_2_3);
        // 2.3.1 喝红酒
        r_2_3.AddNode(new NodeActionDrinkRedWine());
        // 2.3.2 喝白开水
        r_2_3.AddNode(new NodeActionDrinkWater());
        #endregion
    }
コード例 #9
0
        public virtual ParameterSetResult Build(ITypeActivator typeActivator,
                                                ITypeConverter typeConverter,
                                                CultureInfo cultureInfo,
                                                NodeSequence sequence,
                                                ParameterSet paramSet)
        {
            BuildContext ctx = new BuildContext(sequence,
                                                paramSet,
                                                typeActivator.CreateInstance(paramSet.UnderlyingType));

            var requiredParameters = new HashSet<Parameter>(paramSet.Where(p => p.GetAttribute<RequiredAttribute>() != null));

            SetDefaultValues(typeConverter, cultureInfo, ctx);

            bool first = true;

            using (IEnumerator<AstNode> enumerator = sequence.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    if (first && !string.IsNullOrEmpty(ctx.ParameterSet.Command))
                    {
                        LiteralValue literal = enumerator.Current as LiteralValue;
                        if (literal == null || !StringComparer.InvariantCultureIgnoreCase.Equals(literal.Value, ctx.ParameterSet.Command))
                        {
                            // report error: missing/incorrect command
                            ctx.Errors.Add(new BindError(ErrorType.MissingCommand,
                                                         Enumerable.Empty<Parameter>(),
                                                         new AstNode[] { literal },
                                                         string.Format(ErrorMessages.MissingCommand, ctx.ParameterSet.Command)));
                        }
                        if (!enumerator.MoveNext())
                            break;
                    }
                    first = false;

                    if (enumerator.Current.Type == NodeType.Parameter || enumerator.Current.Type == NodeType.Switch)
                    {
                        ParameterName parameterName = (ParameterName)enumerator.Current;
                        Parameter[] parameters;
                        if (ctx.ParameterSet.TryGetParameter(parameterName.Name, out parameters) && parameters.Length == 1)
                        {
                            // remove from "remaining parameters" collection
                            if (!ctx.RemainingParameters.Remove(parameters[0]))
                            {
                                // report error, multiple bindings
                                string message = string.Format(ErrorMessages.MultipleBindings,
                                                               parameterName.Name);

                                ctx.Errors.Add(new BindError(ErrorType.MultipleBindings,
                                                             parameters,
                                                             new AstNode[] { parameterName },
                                                             message));

                                // if the parameter was not of type Switch, skip next node
                                if (parameters[0].Property.PropertyType != typeof(Switch))
                                    enumerator.MoveNext();

                                // handled, continue and skip
                                continue;
                            }

                            // if it's a Switch we can simply set it to "Present"
                            if (parameters[0].Property.PropertyType == typeof(Switch))
                            {
                                if (enumerator.Current.Type == NodeType.Switch)
                                {
                                    SwitchParameter switchParameter = (SwitchParameter)enumerator.Current;
                                    SetPropertyValue(ctx, parameters[0], switchParameter.Value);
                                }
                                else
                                    parameters[0].Property.SetValue(ctx.Instance, Switch.Present, null);

                                requiredParameters.Remove(parameters[0]);
                                // handled, continue and skip
                                continue;
                            }

                            // advance to value 
                            if (!enumerator.MoveNext())
                            {
                                string message = string.Format(ErrorMessages.MissingValue, parameters[0].Name);

                                ctx.Errors.Add(new BindError(ErrorType.MissingValue,
                                                             new[] { parameters[0] },
                                                             new[] { parameterName },
                                                             message));
                                break;
                            }

                            SetPropertyValue(ctx, parameters[0], enumerator.Current);
                            requiredParameters.Remove(parameters[0]);
                        }
                        else if (parameters != null && parameters.Length > 1)
                        {
                            // report error, ambigious name
                            string message = string.Format(ErrorMessages.AmbigiousName,
                                                           parameterName.Name,
                                                           string.Join(", ", parameters.Select(p => p.Name)));

                            ctx.Errors.Add(new BindError(ErrorType.AmbigiousName,
                                                         parameters,
                                                         new AstNode[] { parameterName },
                                                         message));
                        }
                        else
                        {
                            // report error, parameter not found
                            string message = string.Format(ErrorMessages.ArgumentNameMismatch, parameterName.Name);

                            ctx.Errors.Add(new BindError(ErrorType.ArgumentNameMismatch,
                                                         Enumerable.Empty<Parameter>(),
                                                         new AstNode[] { parameterName },
                                                         message));
                        }
                    }
                    else
                    {
                        // positional param
                        var positionalParam = ctx.RemainingParameters.FirstOrDefault(p => p.Position.HasValue);

                        if (positionalParam == null)
                        {
                            // report error, there are no positional parameters
                            string message = string.Format(ErrorMessages.ArgumentPositionMismatch,
                                                           ctx.Sequence.GetInputString(enumerator.Current.SourceInfo));

                            ctx.Errors.Add(new BindError(ErrorType.ArgumentPositionMismatch,
                                                         Enumerable.Empty<Parameter>(),
                                                         new[] { enumerator.Current },
                                                         message));
                        }
                        else
                        {
                            SetPropertyValue(ctx, positionalParam, enumerator.Current);
                            requiredParameters.Remove(positionalParam);
                        }
                    }
                }
            }

            foreach (Parameter missingParameter in requiredParameters)
            {
                string message = string.Format(ErrorMessages.MissingRequiredParameter, missingParameter.Name);

                ctx.Errors.Add(new BindError(ErrorType.MissingRequiredParameter,
                                             new[] { missingParameter },
                                             null,
                                             message));
            }

            return new ParameterSetResult(sequence, ctx.ParameterSet, ctx.Instance, ctx.Errors);
        }
コード例 #10
0
ファイル: SPL3.cs プロジェクト: playgen/it-alert
        // TODO: this should be parameterized further and read from config
        public override SimulationScenario GenerateScenario()
        {
            #region configuration

            var text = new Dictionary <string, Dictionary <string, string> >();

            #region graph

            var node00 = new NodeConfig(0, 0, SubsystemNode.Archetype);
            var node10 = new NodeConfig(1, 0, SubsystemNode.Archetype);
            var node20 = new NodeConfig(2, 0, SubsystemNode.Archetype);
            var node30 = new NodeConfig(3, 0, SubsystemNode.Archetype);

            var node01 = new NodeConfig(0, 1, TransferWorkstation.Archetype);
            var node11 = new NodeConfig(1, 1, AntivirusWorkstation.Archetype);
            var node21 = new NodeConfig(2, 1, SubsystemNode.Archetype);
            var node31 = new NodeConfig(3, 1, TransferWorkstation.Archetype);

            var node02 = new NodeConfig(0, 2, SubsystemNode.Archetype);
            var node12 = new NodeConfig(1, 2, SubsystemNode.Archetype);
            var node22 = new NodeConfig(2, 2, SubsystemNode.Archetype);
            var node32 = new NodeConfig(3, 2, SubsystemNode.Archetype);

            var nodeConfigs = new NodeConfig[]
            {
                node00,
                node10,
                node20,
                node30,

                node01,
                node11,
                node21,
                node31,

                node02,
                node12,
                node22,
                node32,
            };
            ConfigurationHelper.ProcessNodeConfigs(nodeConfigs);

            // top row

            // horizontal
            var connection0010 = new EdgeConfig(node00, EdgeDirection.East, node10, ConnectionNode.Archetype);
            var connection1000 = connection0010.Reciprocate();

            var connection1020 = new EdgeConfig(node10, EdgeDirection.East, node20, ConnectionNode.Archetype);
            var connection2010 = connection1020.Reciprocate();

            var connection2030 = new EdgeConfig(node20, EdgeDirection.East, node30, ConnectionNode.Archetype);
            var connection3020 = connection2030.Reciprocate();

            //vertical
            var connection0001 = new EdgeConfig(node00, EdgeDirection.South, node01, ConnectionNode.Archetype);
            var connection0100 = connection0001.Reciprocate();

            var connection1011 = new EdgeConfig(node10, EdgeDirection.South, node11, ConnectionNode.Archetype);
            var connection1110 = connection1011.Reciprocate();

            var connection3031 = new EdgeConfig(node30, EdgeDirection.South, node31, ConnectionNode.Archetype);
            var connection3130 = connection3031.Reciprocate();

            // middle row

            //horizontal
            var connection0111 = new EdgeConfig(node01, EdgeDirection.East, node11, ConnectionNode.Archetype);
            var connection1101 = connection0111.Reciprocate();

            var connection2131 = new EdgeConfig(node21, EdgeDirection.East, node31, ConnectionNode.Archetype);
            var connection3121 = connection2131.Reciprocate();

            // vertical
            var connection0102 = new EdgeConfig(node01, EdgeDirection.South, node02, ConnectionNode.Archetype);
            var connection0201 = connection0102.Reciprocate();

            var connection2122 = new EdgeConfig(node21, EdgeDirection.South, node22, ConnectionNode.Archetype);
            var connection2221 = connection2122.Reciprocate();

            var connection3132 = new EdgeConfig(node31, EdgeDirection.South, node32, ConnectionNode.Archetype);
            var connection3231 = connection3132.Reciprocate();

            // bottom row

            //horizontal
            var connection0212 = new EdgeConfig(node02, EdgeDirection.East, node12, ConnectionNode.Archetype);
            var connection1202 = connection0212.Reciprocate();

            var connection1222 = new EdgeConfig(node12, EdgeDirection.East, node22, ConnectionNode.Archetype);
            var connection2212 = connection1222.Reciprocate();

            var connection2232 = new EdgeConfig(node22, EdgeDirection.East, node32, ConnectionNode.Archetype);
            var connection3222 = connection2232.Reciprocate();

            var edgeConfigs = new List <EdgeConfig>()
            {
                connection0010,
                connection1000,
                connection1020,
                connection2010,
                connection2030,
                connection3020,
                connection0001,
                connection0100,
                connection1011,
                connection1110,
                connection3031,
                connection3130,
                connection0111,
                connection1101,
                connection2131,
                connection3121,
                connection0102,
                connection0201,
                connection2122,
                connection2221,
                connection3132,
                connection3231,
                connection0212,
                connection1202,
                connection1222,
                connection2212,
                connection2232,
                connection3222,
            };

            #endregion

            var archetypes = new List <Archetype>
            {
                SubsystemNode.Archetype,
                ConnectionNode.Archetype,
                Player.Archetype,

                AntivirusWorkstation.Archetype,
                AnalyserActivator.Archetype,
                CaptureTool.Archetype,
                AntivirusTool.Archetype,

                TransferWorkstation.Archetype,
                TransferActivator.Archetype,

                ScannerTool.Archetype,
                RedVirus.Archetype,
                GreenVirus.Archetype
            };

            var configuration = ConfigurationHelper.GenerateConfiguration(nodeConfigs, edgeConfigs, null, archetypes);
            configuration.RNGSeed = 889753438;

            #endregion

            var scenario = new SimulationScenario(ScenarioInfo)
            {
                Configuration = configuration,

                PlayerConfigFactory = new StartingLocationSequencePlayerConfigFactory(Player.Archetype, new[] { node00.Id, node30.Id, node02.Id, node32.Id }),
                Sequence            = new List <SequenceFrame <Simulation, SimulationConfiguration> >(),

                Scoring = SimulationScenario.ScoringMode.Full,
            };

            var redSpawnSequence = new NodeSequence(new[]
            {
                // offset by one vs config
                node10,
                node22,
                node02,
                node30,
                node21,
                node01,
                node31,
                node11,
                node12,
                node00,
                node32,
                node10,
            });

            var greenSpawnSequence = new NodeSequence(new[]
            {
                // offset by one vs config
                node12,
                node00,
                node32,
                node20,
                node31,
                node22,
                node02,
                node30,
                node21,
                node01,
                node10,
                node11,
                node12,
            });

            #region frames

            // 1
            scenario.Sequence.Add(
                new SimulationFrame()
            {
                OnEnterActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new SetTimer <Simulation, SimulationConfiguration>(scenario.TimeLimitSeconds.Value),
                    new CreateItem(ScannerTool.Archetype, node00),
                    new CreateItem(ScannerTool.Archetype, node32),
                    new CreateItem(CaptureTool.Archetype, node10),
                    new CreateItem(CaptureTool.Archetype, node22),
                },
                ExitCondition = new WaitForTicks(1),
                OnExitActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new CreateMalware(RedVirus.Archetype, node10),
                    new CreateMalware(GreenVirus.Archetype, node21),
                },
            }
                );

            // 2
            scenario.Sequence.Add(
                new SimulationFrame()
            {
                OnEnterActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                },
                OnTickActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new ConditionalAction <Simulation, SimulationConfiguration>(new NodeSequenceAction(redSpawnSequence, ec => new CreateMalware(RedVirus.Archetype, ec)),
                                                                                new OnEvent <AntivirusActivationEvent>(aae => (aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.SoloExtermination ||
                                                                                                                               aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.CoopExtermination) &&
                                                                                                                       aae.MalwareCount[SimulationConstants.MalwareGeneRed] == 0)),
                    new ConditionalAction <Simulation, SimulationConfiguration>(new NodeSequenceAction(greenSpawnSequence, ec => new CreateMalware(GreenVirus.Archetype, ec)),
                                                                                new OnEvent <AntivirusActivationEvent>(aae => (aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.SoloExtermination ||
                                                                                                                               aae.ActivationResult == AntivirusActivationEvent.AntivirusActivationResult.CoopExtermination) &&
                                                                                                                       aae.MalwareCount[SimulationConstants.MalwareGeneGreen] == 0)),
                },
                ExitCondition = new WaitForTimer(),
                OnExitActions = new List <ECSAction <Simulation, SimulationConfiguration> >()
                {
                    new EndGame(EndGameState.Neutral),
                },
            }
                );
            #endregion

            return(scenario);
        }