예제 #1
0
        private Node getNodeToPlay(BasicChessboard chessboard, int totalPlayedTimes)
        {
            Node nodeToPlay = null;

            if (PositionsAvailable.Count > 0)
            {
                nextNodeLock.EnterWriteLock();
                if (PositionsAvailable.Count > 0)
                {
                    nodeToPlay = new Node(PositionsAvailable.Dequeue(), chessboard.NextMoveKind);
                    NextNodes.Add(nodeToPlay);
                }
                nextNodeLock.ExitWriteLock();
            }
            if (nodeToPlay == null)
            {
                nextNodeLock.EnterReadLock();
                nodeToPlay = NextNodes.Aggregate((n1, n2) =>
                {
                    return(n1.GetUCB(totalPlayedTimes) > n2.GetUCB(totalPlayedTimes) ? n1 : n2);
                });
                nextNodeLock.ExitReadLock();
            }

            return(nodeToPlay);
        }
예제 #2
0
 public void Add(IWorkflowNode node)
 {
     if (node != null)
     {
         NextNodes.Add(node);
     }
 }
예제 #3
0
 public void AddNextNode(VariableReferenceNode node)
 {
     if (node == null)
     {
         return;
     }
     NextNodes.Add(node);
     node.PreviousNodes.Add(this);
 }
예제 #4
0
        /// <summary>
        /// 次の指し手ノードを追加します。
        /// </summary>
        public void AddNext(MoveNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.ParentNode != null)
            {
                throw new InvalidOperationException(
                          "すでに親ノードが登録されています。");
            }

            NextNodes.Add(node);
            node.ParentNode = this;
        }
예제 #5
0
 public void AddNextNode(VariableReferenceNode node)
 {
     NextNodes.Add(node);
     node.PreviousNodes.Add(this);
 }
예제 #6
0
        public TalkNode(string path)
        {
            Log.Debug($"Parsing node {path}", Plugin.Instance.Config.VerboseOutput);
            NodeFile = path;
            try
            {
                var input        = new StringReader(File.ReadAllText(path));
                var deserializer = new DeserializerBuilder()
                                   .WithNamingConvention(CamelCaseNamingConvention.Instance)
                                   // Workaround to remove YamlAttributesTypeInspector
                                   .WithTypeInspector(inner => inner, s => s.InsteadOf <YamlAttributesTypeInspector>())
                                   .WithTypeInspector(
                    inner => new YamlAttributesTypeInspector(inner),
                    s => s.Before <NamingConventionTypeInspector>()
                    )
                                   .Build();

                TalkNodeSerializationInfo raw_node = deserializer.Deserialize <TalkNodeSerializationInfo>(input);

                Desc  = raw_node.Description;
                Reply = raw_node.Reply;

                //Parse conditions
                //Format:
                //------------
                //conditions:
                // - token: SomeToken
                //   args:
                //    some_arg: some_value
                //    some_arg1: some_value1
                foreach (NpcNodeWithArgsSerializationInfo info in raw_node.Conditions)
                {
                    NodeCondition cond = NodeCondition.GetFromToken(info.Token);
                    if (cond != null)
                    {
                        Log.Debug($"Recognized token: {cond.Name}", Plugin.Instance.Config.VerboseOutput);
                        Conditions.Add(cond, info.Args);
                    }
                    else
                    {
                        Log.Error($"Failed to parse condition: {info.Token} (invalid token)");
                    }
                }

                //Parse actions
                //Format:
                //------------
                //actions:
                // - token: SomeToken
                //   args:
                //    some_arg: some_value
                //    some_arg1: some_value1
                foreach (NpcNodeWithArgsSerializationInfo info in raw_node.Actions)
                {
                    NodeAction cond = NodeAction.GetFromToken(info.Token);
                    if (cond != null)
                    {
                        Log.Debug($"Recognized token: {cond.Name}", Plugin.Instance.Config.VerboseOutput);
                        Actions.Add(cond, info.Args);
                    }
                    else
                    {
                        Log.Error($"Failed to parse action: {info.Token} (invalid token)");
                    }
                }

                //Parse next nodes
                //Format:
                //------------
                //next_nodes:
                // - /relative/path/to/node
                Log.Debug("Parsing next nodes...", Plugin.Instance.Config.VerboseOutput);
                foreach (string item in raw_node.NextNodes)
                {
                    NextNodes.Add(TalkNode.FromFile(Path.Combine(Config.NPCs_nodes_path, item)));
                }
            }
            catch (Exception e)
            {
                Log.Error($"Failed to parse node {path}! {e}");
                this.Desc  = "<ERROR>";
                this.Reply = "<ERROR>";
            }
        }
예제 #7
0
 /// <summary>
 /// Adds the node to the collection of successor nodes.
 /// </summary>
 /// <param name="nextNode">The next node.</param>
 public virtual void AddNextNode(IRunnableNode nextNode)
 {
     NextNodes.Add(nextNode);
 }
예제 #8
0
        /// <summary>
        /// creates the next nodes in the tree
        /// </summary>
        private void SetNextNodesNew()
        {
            //get all outgoing messages
            var outgoing  = this.Current.Connections.Where(t => (t is Message || t is LostMessage) && t.FromObject != null && t.FromObject == this.Current).Where(t => t.Locationy <= IncomingHeight);
            var coregions = this.Current.ParentModel.ObjectList.Where(t => t is CoregionBox && Math.Abs((t as CoregionBox).Locationx - this.Current.Locationx) < 1);
            var messages  = new HashSet <Connection>();

            //check if next messages (or coregions) exist, return if not
            if (outgoing.Any() || coregions.Any())
            {
                //get next outgoing connection
                List <Connection> nextmessagesList = new List <Connection>();
                if (outgoing.Any())
                {
                    //order
                    var outgoingordered = outgoing.OrderByDescending(t => t.Locationy).ToList();

                    //handle lost messages as if they were async
                    //add lostmessages to list until normal message found
                    for (int i = 0; i < outgoingordered.Count; i++)
                    {
                        nextmessagesList.Add(outgoingordered[i]);
                        if (!(outgoingordered[i] is LostMessage))
                        {
                            break;
                        }
                    }
                }

                //check if a coregion exists before. if so, use those connections instead
                if (coregions.Any())
                {
                    var fittingCoregions = coregions.Where(t => t.Locationtopleft.Y < this.IncomingHeight);
                    if (nextmessagesList.Any() && fittingCoregions.Any())
                    {
                        fittingCoregions = fittingCoregions.Where(t => t.Locationtopleft.Y > nextmessagesList.First().Locationy).ToList();
                    }

                    if (fittingCoregions.Any())
                    {
                        //coregion found, replace nextmessages with coregion outgoing messages
                        nextmessagesList.Clear();
                        var coregionmax = fittingCoregions.MaxBy(t => t.Locationy) as Item;
                        var coregionOutgoingMessages = coregionmax.Connections.Where(t => t.FromObject == fittingCoregions.MaxBy(r => r.Locationy));
                        nextmessagesList.AddRange(coregionOutgoingMessages);

                        //special case: lost messages between coregion and incoming message
                        var lostmessagesbetweencoregion = outgoing.Where(t => t is LostMessage && t.Locationy < coregionmax.Locationy);
                        if (lostmessagesbetweencoregion.Any())
                        {
                            nextmessagesList.AddRange(lostmessagesbetweencoregion);
                        }
                    }
                }

                //check if a nextmessage still exists
                if (!nextmessagesList.Any())
                {
                    return;
                }

                foreach (var nextmessage in nextmessagesList)
                {
                    //check if nextmessage enters a new container
                    HashSet <BMSCInlineExpressionAltPar> newcontainers = nextmessage.Containers.Where(t => t is BMSCInlineExpressionAltPar && !EnteredContainers.Contains(t))
                                                                         .Cast <BMSCInlineExpressionAltPar>()
                                                                         .ToHashSet <BMSCInlineExpressionAltPar>();
                    if (newcontainers.Any())
                    {
                        //add containers from split message as well
                        var newsplitcontainers = newcontainers.First().ObjectsBelowLine.Where(t => t is Connection)
                                                 .Cast <Connection>().MaxBy(t => t.Locationy).Containers.Cast <BMSCInlineExpressionAltPar>();
                        foreach (BMSCInlineExpressionAltPar nc in newsplitcontainers)
                        {
                            newcontainers.Add(nc);
                        }

                        //iterate through all new containers. pick each top and bottom message and add to list. no duplicates
                        foreach (BMSCInlineExpressionAltPar newcontainer in newcontainers)
                        {
                            //add to known containers
                            EnteredContainers.Add(newcontainer);

                            //get top top message
                            messages.Add(newcontainer.ObjectsAboveLine.Where(t => t is Connection).Cast <Connection>().MaxBy(t => t.Locationy));

                            //get top bottom mesage
                            messages.Add(newcontainer.ObjectsBelowLine.Where(t => t is Connection).Cast <Connection>().MaxBy(t => t.Locationy));
                        }
                    }
                    //nextmessage does not enter a new container
                    else
                    {
                        //check if swaps, meaning next message in lower container and previous in upper
                        var swappingContainers =
                            nextmessage.Containers.Where(
                                t => ((BMSCInlineExpressionAltPar)t).ObjectsAboveLine.Contains(IncomingMessage) &&
                                ((BMSCInlineExpressionAltPar)t).ObjectsBelowLine.Contains(nextmessage));
                        if (swappingContainers.Any())
                        {
                            //if swap, pick next message NOT in the swapping container
                            if (swappingContainers.Count() > 1)
                            {
                                throw new Exception("unexcepted result. more than one swapping container found.");
                            }

                            //check if another outgoing message exists
                            var nextoutgoing = outgoing.Where(t => !swappingContainers.First().ContainingItems.Contains(t));
                            if (nextoutgoing.Any())
                            {
                                messages.Add(nextoutgoing.MaxBy(t => t.Locationy));
                            }
                        }
                        //no swap, pick next message
                        else
                        {
                            messages.Add(nextmessage);
                        }
                    }
                }

                //create new nodes for each message
                foreach (var newmessage in messages)
                {
                    //case: newmessage is LostMessage: find corresponding found message as next node if exists
                    if (newmessage is LostMessage)
                    {
                        //check for foundmessage
                        var foundmessage = (FoundMessage)this.Current.ParentModel.ObjectList.FirstOrDefault(t => t is FoundMessage && t.Locationy < newmessage.Locationy && ((FoundMessage)t).Text == newmessage.Text);
                        if (foundmessage != null)
                        {
                            NextNodes.Add(new BmscNode((Item)foundmessage.ToObject, (Message)foundmessage, this.CurrentDepth + 1, foundmessage.Locationy, EnteredContainers));
                            NextMessages.Add((Message)newmessage);
                        }
                    }
                    else
                    {
                        NextNodes.Add(new BmscNode((Item)newmessage.ToObject, (Message)newmessage, this.CurrentDepth + 1, newmessage.Locationy, EnteredContainers));
                        NextMessages.Add((Message)newmessage);
                    }
                }
            }
        }