Ejemplo n.º 1
0
        public IASTNode Parse()
        {
            // Parse the query string into an HQL AST.
            var lex = new HqlLexer(new CaseInsensitiveStringStream(_hql));

            _tokens = new CommonTokenStream(lex);

            var parser = new HqlParser(_tokens)
            {
                TreeAdaptor = new ASTTreeAdaptor(), Filter = _filter
            };

            if (log.IsDebugEnabled)
            {
                log.Debug("parse() - HQL: " + _hql);
            }

            try
            {
                var ast = (IASTNode)parser.statement().Tree;

                var walker = new NodeTraverser(new ConstantConverter(_sfi));
                walker.TraverseDepthFirst(ast);

                return(ast);
            }
            finally
            {
                parser.ParseErrorHandler.ThrowQueryException();
            }
        }
        public void TraversesSequenceNodes()
        {
            var document = @"
                lorem:
                  - name: ipsum
                    dolor: 1
                  - sit: 2
                amet:
                  - adipiscing: 3
            ";

            var result = new NodeTraverser().Traverse(Parser.Parse(document));

            Assert.Equal(new object[] { }, result.ElementAt(0).Path.Segments);
            Assert.IsType <YamlMappingNode>(result.ElementAt(0).Node);

            Assert.Equal(new object[] { "lorem" }, result.ElementAt(1).Path.Segments);
            Assert.IsType <YamlSequenceNode>(result.ElementAt(1).Node);

            Assert.Equal(new object[] { "amet" }, result.ElementAt(2).Path.Segments);
            Assert.IsType <YamlSequenceNode>(result.ElementAt(2).Node);

            Assert.Equal(new object[] { "lorem", 0 }, result.ElementAt(3).Path.Segments);
            Assert.IsType <YamlMappingNode>(result.ElementAt(3).Node);

            Assert.Equal(new object[] { "lorem", 1 }, result.ElementAt(4).Path.Segments);
            Assert.IsType <YamlMappingNode>(result.ElementAt(4).Node);

            Assert.Equal(new object[] { "amet", 0 }, result.ElementAt(5).Path.Segments);
            Assert.IsType <YamlMappingNode>(result.ElementAt(5).Node);
        }
Ejemplo n.º 3
0
 public Node(int index, T value)
 {
     this.Index    = index;
     this.Children = new NodeChildren <T>();
     this.Value    = value;
     this.Traverse = new NodeTraverser <T>(this);
 }
Ejemplo n.º 4
0
 public Node(int index, T value)
 {
     Index    = index;
     Children = new NodeChildren <T>();
     Value    = value;
     Traverse = new NodeTraverser <T>(this);
 }
        private IList <IASTNode> LocateParameters()
        {
            var nodeTraverser = new NodeTraverser(this);

            nodeTraverser.TraverseDepthFirst(_tree);

            return(_nodes);
        }
Ejemplo n.º 6
0
        public IList <IASTNode> LocateQuerySources()
        {
            // Find all the polymorphic query sources
            var nodeTraverser = new NodeTraverser(this);

            nodeTraverser.TraverseDepthFirst(_tree);

            return(_nodes);
        }
        public void TraversesMappingNodes()
        {
            var document = @"
                lorem: ipsum
            ";

            var result = new NodeTraverser().Traverse(Parser.Parse(document));

            Assert.Single(result);
            Assert.Equal(new object[] { }, result.Single().Path.Segments);
            Assert.IsType <YamlMappingNode>(result.Single().Node);
        }
        public void TraversesNestedMappingNodes()
        {
            var document = @"
                lorem:
                    ipsum: dolor
            ";

            var result = new NodeTraverser().Traverse(Parser.Parse(document));

            Assert.Equal(2, result.Count());
            Assert.Equal(new object[] { }, result.First().Path.Segments);
            Assert.IsType <YamlMappingNode>(result.First().Node);
            Assert.Equal(new object[] { "lorem" }, result.Last().Path.Segments);
            Assert.IsType <YamlMappingNode>(result.Last().Node);
        }
Ejemplo n.º 9
0
        public void TestBeatable(string mapId, bool expected)
        {
            //Arrange
            var resourceReader = new System.IO.StreamReader(new System.IO.MemoryStream(Properties.Resources.TestLogic));
            var data           = JsonConvert.DeserializeObject <Common.SaveData.SaveData>(resourceReader.ReadToEnd());

            var randomMap = TestData.Data[mapId];

            var traverser = new NodeTraverser();

            // Act
            var result = traverser.VerifyBeatable(data, randomMap);

            // Assert
            Assert.Equal(expected, result);
        }
Ejemplo n.º 10
0
        private static void GenerateXml(NodeGen nodeGen, string xmlFileName, Options options)
        {
            if (!options.Silent)
            {
                Console.WriteLine("Generating game tree...");
            }

            var      rootNode0 = nodeGen.Generate();
            XElement xElement  = new XElement("Node");

            NodeTraverser.TraverseToXml(xElement, rootNode0);

            XDocument doc = new XDocument(xElement);

            doc.Save(xmlFileName);
        }
Ejemplo n.º 11
0
        private void HandleWithFragment(FromElement fromElement, IASTNode hqlWithNode)
        {
            try
            {
                ITreeNodeStream old = input;
                input = new CommonTreeNodeStream(adaptor, hqlWithNode);

                IASTNode hqlSqlWithNode = (IASTNode)withClause().Tree;
                input = old;

                if (log.IsDebugEnabled())
                {
                    log.Debug("handleWithFragment() : {0}", _printer.ShowAsString(hqlSqlWithNode, "-- with clause --"));
                }
                WithClauseVisitor visitor   = new WithClauseVisitor(fromElement);
                NodeTraverser     traverser = new NodeTraverser(visitor);
                traverser.TraverseDepthFirst(hqlSqlWithNode);
                FromElement referencedFromElement = visitor.GetReferencedFromElement();
                if (referencedFromElement != fromElement)
                {
                    if (!referencedFromElement.IsEntityJoin() && !fromElement.IsEntityJoin())
                    {
                        throw new InvalidWithClauseException(
                                  "with-clause expressions did not reference from-clause element to which the with-clause was associated");
                    }
                }
                SqlGenerator sql = new SqlGenerator(_sessionFactoryHelper.Factory, new CommonTreeNodeStream(adaptor, hqlSqlWithNode.GetChild(0)));

                sql.whereExpr();

                var withClauseFragment = new SqlString("(", sql.GetSQL(), ")");
                fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), withClauseFragment);
            }
            catch (SemanticException)
            {
                throw;
            }
            catch (InvalidWithClauseException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new SemanticException(e.Message, e);
            }
        }
Ejemplo n.º 12
0
        public void WriteToDb(int hand, Node rootNode, Action <int> nodesWritten = null)
        {
            using (MySqlConnection c = ConnectToDatabase())
            {
                using (MySqlCommand cmd = new MySqlCommand("", c))
                {
                    string initialString =
                        $"SET autocommit=0; INSERT INTO {DbName} (`Player`, `Hand`, `Actions`, `Round`, `NextPlayer`, `Pay`, `PossibleActions`, `Cfr`) VALUES ";
                    StringBuilder sb    = new StringBuilder(initialString);
                    int           i     = 0;
                    int           total = 0;
                    NodeTraverser.TraverseWithAction(rootNode, (node, actions) =>
                    {
                        string nextPlayer      = node.Children.Length > 0 ? node.Children[0].Pos.ToString() : "NULL";
                        string pay             = node.IsTerminal() ? node.PayOff.ToString() : "NULL";
                        float[] avStrategy     = node.GetAverageStrategy(hand);
                        string cfr             = avStrategy.Any() ? $"'{string.Join(";", avStrategy)}'" : "NULL";
                        string possibleActions = node.IsTerminal() ? "NULL" : $"'{string.Join(",", node.Children.Select(x => x.Action.ToShortString()))}'";

                        sb.Append($"({node.Pos}, {hand}, '{actions}', {(int)node.Round}, {nextPlayer}, {pay}, {possibleActions}, {cfr}),");

                        i++;
                        total++;
                        if (i > MaxInsertsPerQuery)
                        {
                            sb[sb.Length - 1] = ';';
                            sb.AppendLine("COMMIT;");
                            cmd.CommandText = sb.ToString();
                            cmd.ExecuteNonQuery();
                            sb.Clear();
                            sb.Append(initialString);
                            i = 0;
                            nodesWritten?.Invoke(total);
                        }
                    });

                    sb[sb.Length - 1] = ';';
                    sb.AppendLine("COMMIT;");
                    cmd.CommandText = sb.ToString();

                    cmd.ExecuteNonQuery();

                    nodesWritten?.Invoke(total);
                }
            }
        }
Ejemplo n.º 13
0
        private void HandleWithFragment(FromElement fromElement, IASTNode hqlWithNode)
        {
            try
            {
                ITreeNodeStream old = input;
                input = new CommonTreeNodeStream(adaptor, hqlWithNode);

                IASTNode hqlSqlWithNode = (IASTNode)withClause().Tree;
                input = old;

                if (log.IsDebugEnabled())
                {
                    log.Debug("handleWithFragment() : {0}", _printer.ShowAsString(hqlSqlWithNode, "-- with clause --"));
                }
                WithClauseVisitor visitor   = new WithClauseVisitor(fromElement);
                NodeTraverser     traverser = new NodeTraverser(visitor);
                traverser.TraverseDepthFirst(hqlSqlWithNode);
                SqlGenerator sql = new SqlGenerator(_sessionFactoryHelper.Factory, new CommonTreeNodeStream(adaptor, hqlSqlWithNode.GetChild(0)));

                sql.whereExpr();

                fromElement.WithClauseFragment = new SqlString("(", sql.GetSQL(), ")");
            }
            catch (SemanticException)
            {
                throw;
            }
            catch (InvalidWithClauseException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new SemanticException(e.Message, e);
            }
        }
Ejemplo n.º 14
0
        public Dictionary <string, Guid> FillLocations(SaveData someData, FillOptions options, ItemPool pool, Inventory startingInventory, Random random, Dictionary <string, Guid> originalItemMap)
        {
            Log = new LogLayer("Item Placement");

            var inventory = new Inventory(startingInventory);

            var nodeCollection = new NodeCollection();

            nodeCollection.InitializeNodes(someData);

            keyNodes = nodeCollection.myNodes.Where(node => node is KeyNode).ToList();
            var eventNodes = keyNodes.Where(node => node is EventKeyNode).Select(node => node as EventKeyNode);

            startNode   = eventNodes.FirstOrDefault(node => node.myKeyId == StaticKeys.GameStart);
            endNode     = eventNodes.FirstOrDefault(node => node.myKeyId == StaticKeys.GameFinish);
            charlieNode = eventNodes.FirstOrDefault(node => node.myKeyId == StaticKeys.CharlieDefeated);

            // Generate Item map
            var itemMap = new Dictionary <string, Guid>(originalItemMap);

            if (options.majorSwap == FillOptions.ItemSwap.Unchanged || options.minorSwap == FillOptions.ItemSwap.Unchanged)
            {
                var allRandomKeyNodes  = keyNodes.Where(node => node is RandomKeyNode randomNode).Select(node => node as RandomKeyNode).OrderBy(node => node.id);
                var openRandomKeyNodes = allRandomKeyNodes.Where(node => !itemMap.ContainsKey(node.myRandomKeyIdentifier));

                foreach (var keyNode in openRandomKeyNodes)
                {
                    var item = keyNode.GetOriginalKey();
                    if (item == null)
                    {
                        continue;
                    }

                    if ((StaticKeys.IsMajorItem(item.Id) && options.majorSwap == FillOptions.ItemSwap.Unchanged) ||
                        (StaticKeys.IsMinorItem(item.Id) && options.minorSwap == FillOptions.ItemSwap.Unchanged))
                    {
                        var pulled = pool.Pull(item.Id);
                        if (pulled)
                        {
                            itemMap.Add(keyNode.myRandomKeyIdentifier, item.Id);
                        }
                    }
                }
            }

            KeyManager.SetRandomKeyMap(itemMap);

            // Set up location rules
            itemRequiredLocationRules = ItemRuleUtility.GetRequiredLocationRules(options.itemRules);
            itemBlockedLocationRules  = ItemRuleUtility.GetBlockedLocationRules(options.itemRules);

            restrictedLocations = new HashSet <string>();

            if (itemRequiredLocationRules.Any())
            {
                Log.AddChild("RequiredLocationRules", itemRequiredLocationRules.Select(group => new LogLayer(KeyManager.GetKeyName(group.Key), group.Value)));
            }

            if (itemBlockedLocationRules.Any())
            {
                Log.AddChild("BlockedLocationRules", itemBlockedLocationRules.Select(group => new LogLayer(KeyManager.GetKeyName(group.Key), group.Value)));
            }

            UpdateLocationRestrictions(inventory, itemMap, pool, random, Log);

            // Initialize search terms
            searcher = new FillSearcher();

            var reachableKeys   = new List <NodeBase>();
            var retracableKeys  = new List <NodeBase>();
            var restrictedItems = new List <Guid>();

            var searchDepth = 0;
            var stepCount   = 1;

            if (options.gameCompletion == FillOptions.GameCompletion.NoLogic)
            {
                Log.AddChild("Game Completion has No Logic - Skipping standard steps");
            }
            else
            {
                var logSteps = Log.AddChild("Standard Steps");
                while (true)
                {
                    var logCurrentStep = logSteps.AddChild($"Step {stepCount++}, depth {searchDepth}");
                    logCurrentStep.AddChild(inventory.GetKeyLog());

                    // Beatable conditional
                    if (options.gameCompletion == FillOptions.GameCompletion.Beatable && inventory.myNodes.Contains(endNode))
                    {
                        logCurrentStep.AddChild($"EndNode reached");
                        break;
                    }

                    // Do not place any power bombs until obtaining powered suit
                    restrictedItems.Clear();
                    if (options.noEarlyPbs && !inventory.ContainsKey(StaticKeys.CharlieDefeated))
                    {
                        restrictedItems.Add(StaticKeys.PowerBombs);
                    }

                    var itemDepthRestrictions = options.itemRules.Where(rest => rest is ItemRuleRestrictedBeforeDepth depthRest && depthRest.SearchDepth > searchDepth);
                    if (itemDepthRestrictions.Any())
                    {
                        restrictedItems.AddRange(itemDepthRestrictions.Select(rest => rest.ItemId));
                    }

                    if (restrictedItems.Any())
                    {
                        logCurrentStep.AddChild("Restricted Items", restrictedItems.Select(key => KeyManager.GetKeyName(key)));
                    }

                    // Find all nodes that can be reached with current inventory
                    reachableKeys.RemoveAll(node => inventory.myNodes.Contains(node));
                    reachableKeys.AddRange(searcher.ContinueSearch(startNode, inventory, node => (node is KeyNode) && !inventory.myNodes.Contains(node)));

                    logCurrentStep.AddChild("Reachable keys", reachableKeys.Select(node => node.Name()));

                    // Find all reachable keys that are also possible to get back from
                    // (End node is always considered retracable, since being able to reach it at all is just akin to "being in go mode")
                    retracableKeys.RemoveAll(node => inventory.myNodes.Contains(node));
                    var notRetracable = reachableKeys.Except(retracableKeys);
                    retracableKeys.AddRange(notRetracable.AsParallel().Where(node => node == endNode || NodeTraverser.PathExists(node, startNode, node is EventKeyNode ? inventory.Expand(node) : inventory)).ToList());

                    logCurrentStep.AddChild("Retracable keys", retracableKeys.Select(node => node.Name()));

                    if (!retracableKeys.Any())
                    {
                        break;
                    }

                    // If any events can be reached, add to inventory and update search before continuing
                    var retracableEvents = retracableKeys.Where(node => node is EventKeyNode).ToList();
                    if (retracableEvents.Any())
                    {
                        logCurrentStep.AddChild("Retracable events", retracableEvents.Select(node => node.Name()));
                        inventory.myNodes.AddRange(retracableEvents);
                        continue;
                    }

                    var randomizedLocations = retracableKeys.Where(key => key is RandomKeyNode randomNode).Select(key => key as RandomKeyNode).OrderBy(x => x.id).ToList();

                    // Pick up any items already filled in on the map and update search before placing any items
                    var preFilledLocations = randomizedLocations.Where(loc => itemMap.ContainsKey(loc.myRandomKeyIdentifier));

                    if (preFilledLocations.Any())
                    {
                        logCurrentStep.AddChild("Prefilled locations", preFilledLocations.Select(node => $"{node.Name()} - {node.GetKeyName()}"));
                        inventory.myNodes.AddRange(preFilledLocations);
                        continue;
                    }

                    // Get items that are prioritized according to item rules
                    var prioritizedItems = options.itemRules.Where(rest => rest is ItemRulePrioritizedAfterDepth depthRest && depthRest.SearchDepth <= searchDepth)
                                           .Select(rest => rest.ItemId)
                                           .Where(item => !restrictedItems.Contains(item) && !inventory.ContainsKey(item))
                                           .ToList();

                    logCurrentStep.AddChild("Prioritized Items", prioritizedItems.Select(key => KeyManager.GetKeyName(key)));

                    var selectedRelevantKey = FindRelevantKey(inventory, searcher, options, randomizedLocations, reachableKeys.Except(retracableKeys), restrictedItems, prioritizedItems, pool, itemMap, random, logCurrentStep);

                    // Special case to handle how chozodia area is built
                    // Specifically can't get out of it without power bombs, which creates awkward dynamics regarding the placements of said power bombs)
                    // Special case triggers on reaching charlie when no early pbs is enabled
                    if (reachableKeys.Any(key => key is EventKeyNode eventKey && eventKey.myKeyId == StaticKeys.CharlieDefeated) && options.noEarlyPbs &&
                        (NodeTraverser.PathExists(charlieNode, endNode, inventory.Expand(charlieNode)) || selectedRelevantKey == Guid.Empty))
                    {
                        FillRandomly(restrictedItems, inventory, options, itemMap, pool, random, logCurrentStep.AddChild("Charlie random fill"));

                        if (!inventory.ContainsKey(StaticKeys.CharlieDefeated))
                        {
                            // Unless Charlie was for some reason reached during fill, start new search with Charlie as new start node
                            startNode = charlieNode;
                            inventory.myNodes.Add(startNode);
                            searcher = new FillSearcher();
                        }

                        continue;
                    }

                    if (selectedRelevantKey == Guid.Empty)
                    {
                        break;
                    }

                    // Filter out available locations where selected key cannot be placed
                    var filteredLocations = randomizedLocations.Where(location => KeyAllowedInLocation(selectedRelevantKey, options, itemMap, pool, location)).OrderBy(x => x.id).ToList();

                    logCurrentStep.AddChild("Filtered Locations", filteredLocations.Select(node => node.Name()));

                    if (!filteredLocations.Any())
                    {
                        break;
                    }

                    pool.Pull(selectedRelevantKey);

                    // Pick out one random accessible location, place the selected key there and add that item to inventory
                    var selectedLocation = filteredLocations.ElementAt(random.Next(filteredLocations.Count));
                    randomizedLocations.Remove(selectedLocation);
                    itemMap.Add(selectedLocation.myRandomKeyIdentifier, selectedRelevantKey);
                    inventory.myNodes.Add(selectedLocation);

                    logCurrentStep.AddChild($"Selected Location: {selectedLocation.Name()}");

                    prioritizedItems.Remove(selectedRelevantKey);

                    // Only increase searchDepth if an actual item is placed (debatable if this is the correct approach)
                    searchDepth++;

                    UpdateLocationRestrictions(inventory, itemMap, pool, random, logCurrentStep);

                    // Fill remaining accessible locations with random items
                    if (options.majorSwap != FillOptions.ItemSwap.LocalPool && options.minorSwap != FillOptions.ItemSwap.LocalPool)
                    {
                        var randomizedLocationLog = logCurrentStep.AddChild("Randomized Locations");
                        foreach (var node in randomizedLocations)
                        {
                            var locationLog = randomizedLocationLog.AddChild(node.Name());

                            // This is possible through Required Location Rules
                            if (itemMap.ContainsKey(node.myRandomKeyIdentifier))
                            {
                                locationLog.AddChild($"Already filled with: {node.GetKeyName()}");
                                inventory.myNodes.Add(node);
                                continue;
                            }

                            var filteredPrioritizedItems = prioritizedItems.Where(key => KeyAllowedInLocation(key, options, itemMap, pool, node));

                            if (filteredPrioritizedItems.Any())
                            {
                                locationLog.AddChild("Filtered Prioritized Items", filteredPrioritizedItems.Select(key => KeyManager.GetKeyName(key)));

                                var randomKey = pool.PullAmong(filteredPrioritizedItems, random);
                                prioritizedItems.Remove(randomKey);
                                itemMap.Add(node.myRandomKeyIdentifier, randomKey);
                                inventory.myNodes.Add(node);

                                locationLog.Message += $" : {KeyManager.GetKeyName(randomKey)}";
                                locationLog.AddChild($"Prioritized Key placed: {KeyManager.GetKeyName(randomKey)}");
                            }
                            else
                            {
                                // Add all items that cannot be in this location to restrictedItems
                                var locationRestrictedItems = restrictedItems.Union(pool.AvailableItems().Where(key => !KeyAllowedInLocation(key, options, itemMap, pool, node)));

                                locationLog.AddChild("Location Restricted Items", locationRestrictedItems.Select(key => KeyManager.GetKeyName(key)));

                                var selectedKey = pool.PullExcept(locationRestrictedItems, random);

                                if (selectedKey != Guid.Empty)
                                {
                                    itemMap.Add(node.myRandomKeyIdentifier, selectedKey);
                                    inventory.myNodes.Add(node);

                                    locationLog.Message += $" : {KeyManager.GetKeyName(selectedKey)}";
                                    locationLog.AddChild($"Selected Key placed: {KeyManager.GetKeyName(selectedKey)}");
                                }
                            }

                            UpdateLocationRestrictions(inventory, itemMap, pool, random, locationLog);
                        }
                    }

                    // Go back to start of loop to continue search with updated inventory
                }
            }

            var postFillLog = Log.AddChild("Post fill");

            // POST-FILL:
            // Reachable if seed is beatable or if it ran out of possible relevant keys
            // Fill in remaining locations as well as possible without breaking any restrictions

            // Do not place any power bombs until obtaining powered suit
            restrictedItems.Clear();
            if (options.noEarlyPbs && !inventory.ContainsKey(StaticKeys.CharlieDefeated))
            {
                restrictedItems.Add(StaticKeys.PowerBombs);
            }

            postFillLog.AddChild("Restricted Items", restrictedItems.Select(key => KeyManager.GetKeyName(key)));

            if (options.gameCompletion == FillOptions.GameCompletion.AllItems)
            {
                var nonEmptyLog = postFillLog.AddChild("Add non-empty items");

                // Prioritize filling in non-empty items
                var restrictedAndEmpty = new List <Guid>(restrictedItems);
                restrictedAndEmpty.Add(StaticKeys.Nothing);

                FillRandomly(restrictedAndEmpty, inventory, options, itemMap, pool, random, nonEmptyLog);
            }

            var reachableLog = postFillLog.AddChild("Fill remaining reachable locations");

            // Fill remaining reachable nodes randomly
            FillRandomly(restrictedItems, inventory, options, itemMap, pool, random, reachableLog);

            restrictedItems.Clear();

            // Fill all remaining (unreachable) locations with any remaining items
            var remainingNodes = keyNodes.Where(node => node is RandomKeyNode randomNode && !itemMap.ContainsKey(randomNode.myRandomKeyIdentifier)).Select(key => key as RandomKeyNode).OrderBy(x => x.id);

            if (remainingNodes.Any())
            {
                var respectableLog = postFillLog.AddChild("Fill unreachable locations");

                FillRandomly(remainingNodes, restrictedItems, inventory, options, itemMap, pool, random, respectableLog);
            }

            // Fill final locations with blanks
            var finalEmptyLocations = keyNodes.Where(node => node is RandomKeyNode randomNode && !itemMap.ContainsKey(randomNode.myRandomKeyIdentifier)).Select(key => key as RandomKeyNode).OrderBy(x => x.id);

            if (finalEmptyLocations.Any())
            {
                var finalFill = postFillLog.AddChild("Final fill");
                foreach (var node in finalEmptyLocations)
                {
                    if (itemMap.ContainsKey(node.myRandomKeyIdentifier))
                    {
                        continue;
                    }

                    var locationLog = finalFill.AddChild(node.myRandomKeyIdentifier);

                    var item = StaticKeys.Nothing;

                    locationLog.Message += $" : {KeyManager.GetKeyName(item)}";
                    locationLog.AddChild($"Selected item: {KeyManager.GetKeyName(item)}");

                    itemMap.Add(node.myRandomKeyIdentifier, item);

                    UpdateLocationRestrictions(inventory, itemMap, pool, random, locationLog);
                }
            }

            return(itemMap);
        }
Ejemplo n.º 15
0
        private void FillRandomly(List <Guid> restrictedItems,
                                  Inventory inventory, FillOptions options, Dictionary <string, Guid> itemMap, ItemPool pool,
                                  Random random, LogLayer log)
        {
            var fillLog = log.AddChild("Random Fill");

            fillLog.AddChild("Restricted Items", restrictedItems.Select(key => KeyManager.GetKeyName(key)));

            var reachableNodes = new List <NodeBase>();
            var localSearcher  = new FillSearcher();

            // Fill all still reachable random nodes
            int stepCount = 1;

            while (true)
            {
                var stepLog = new LogLayer($"Step {stepCount++}");
                stepLog.AddChild(inventory.GetKeyLog());

                reachableNodes.RemoveAll(node => inventory.myNodes.Contains(node));
                reachableNodes.AddRange(localSearcher.ContinueSearch(startNode, inventory, node => (node is KeyNode) && !inventory.myNodes.Contains(node)));

                stepLog.AddChild(new LogLayer("Reachable Nodes", reachableNodes.Select(node => node.Name())));

                var retracableKeys = reachableNodes.AsParallel().Where(node => node == endNode || NodeTraverser.PathExists(node, startNode, node is EventKeyNode ? inventory.Expand(node) : inventory)).ToList();

                // Find all reachable events that are also possible to get back from
                var retracableEvents = retracableKeys.Where(node => node is EventKeyNode);

                // If any events can be reached, add to inventory and update search before continuing
                if (retracableEvents.Any())
                {
                    stepLog.AddChild("Retracable events", retracableEvents.Select(node => node.Name()));
                    fillLog.AddChild(stepLog);
                    inventory.myNodes.AddRange(retracableEvents);
                    continue;
                }

                var fillNodes = retracableKeys.Any() ? retracableKeys : reachableNodes;

                var fillRandomKeyNodes = fillNodes.Where(node => node is RandomKeyNode).Select(node => node as RandomKeyNode).OrderBy(x => x.id);

                var addedNodes = FillRandomly(fillRandomKeyNodes, restrictedItems, inventory, options, itemMap, pool, random, stepLog);

                if (!addedNodes)
                {
                    break;
                }

                fillLog.AddChild(stepLog);
            }
        }
Ejemplo n.º 16
0
        public static void DoTest()
        {
            var fileNames = new List <string>(Directory.GetFiles(Environment.CurrentDirectory));

            var logicFile = ChooseLogic(fileNames.Where(x => Path.GetExtension(x) == ".lgc").ToList());

            if (logicFile == null)
            {
                // Log issue
                _logMessage += $"No logic file chosen{Environment.NewLine}";
                return;
            }

            var itemFile = ChooseItems(fileNames.Where(x => Path.GetExtension(x) == ".txt" || Path.GetExtension(x) == ".log").ToList());

            if (itemFile == null)
            {
                // Log issue
                _logMessage += $"No item file chosen{Environment.NewLine}";
                return;
            }

            var data = JsonConvert.DeserializeObject <SaveData>(File.ReadAllText(logicFile));

            KeyManager.Initialize(data);

            var inventoryKeys = ParseInventory(itemFile);

            if (inventoryKeys == null)
            {
                // Error logged in parser
                return;
            }

            var randomMap = ParseItemMap(data, itemFile);

            if (randomMap == null)
            {
                // Error logged in parser
                return;
            }

            Console.WriteLine();

            var traverser = new NodeTraverser();

            var inventory = new Inventory();

            inventory.myKeys = inventoryKeys;

            _Timer.Start();
            //for (int count = 0; count < 100; count++)
            {
                _logMessage += Environment.NewLine;
                var fullCompleteResult = traverser.VerifyFullCompletable(data, randomMap, new Inventory(inventory));
                _logMessage += $"100%: {fullCompleteResult}{Environment.NewLine}{traverser.GetWaveLog()}{Environment.NewLine}{Environment.NewLine}";

                var unreachablenodes = traverser.GetUnreachable();
                if (unreachablenodes.Any())
                {
                    _logMessage += $"Unreachable: {traverser.GetUnreachable().Select(node => Utility.GetNodeName(node) + (node is RandomKeyNode keyNode? $"({(keyNode.GetKey() is BaseKey key ? key.Name : "empty")})" : string.Empty)).Aggregate((i, j) => i + ", " + j)}{Environment.NewLine}{Environment.NewLine}";
                }

                var beatableResult = traverser.VerifyBeatable(data, randomMap, new Inventory(inventory));
                _logMessage += $"Beatable: {beatableResult}{Environment.NewLine}{traverser.GetWaveLog()}";
            }

            _Timer.Stop();
        }
Ejemplo n.º 17
0
        public static void Randomize()
        {
            var fileNames = new List <string>(Directory.GetFiles(Environment.CurrentDirectory));

            var logicFile = ChooseLogic(fileNames.Where(x => Path.GetExtension(x) == ".lgc").ToList());

            if (logicFile == null)
            {
                // Log issue
                _logMessage += $"No logic file chosen{Environment.NewLine}";
            }

            var data = JsonConvert.DeserializeObject <SaveData>(File.ReadAllText(logicFile));

            KeyManager.Initialize(data);

            var traverser = new NodeTraverser();

            var settingsFile = ChooseSettings(fileNames.Where(x => Path.GetExtension(x) == ".txt" || Path.GetExtension(x) == ".log").ToList());

            if (settingsFile == null)
            {
                // Log issue
                _logMessage += $"No settings chosen{Environment.NewLine}";
            }

            if (!TryParseSettingsFile(startingInventory, settingsFile))
            {
                // Log issue
                _logMessage += "Failed to parse settings";
            }

            var randomizationType = ChooseRandomization();
            var gameCompletion    = ChooseGameCompletion();

            var random = new Random();
            var seed   = random.Next();
            // var seed = 1083686163;

            var count = 0;

            _Timer.Start();
            while (true)
            {
                if (randomizationType == 1)
                {
                    var placer  = new ItemPlacer();
                    var options = new FillOptions();
                    options.gameCompletion = gameCompletion;
                    options.majorSwap      = FillOptions.ItemSwap.GlobalPool;
                    options.minorSwap      = FillOptions.ItemSwap.LocalPool;
                    // options.noEarlyPbs = true;

                    var result = false;

                    var itemMap = new Dictionary <string, Guid>();

                    ItemPool pool = new ItemPool();
                    pool.CreatePool();
                    foreach (var item in itemMap.Values)
                    {
                        pool.Pull(item);
                    }

                    while (true)
                    {
                        random = new Random(seed);

                        //pool.RemoveRandomItemsExcept(90, random, new List<Guid>() { StaticKeys.Morph, StaticKeys.Missile, StaticKeys.Bombs, StaticKeys.IceBeam, StaticKeys.PlasmaBeam });

                        var testInventory = new Inventory(startingInventory);

                        testInventory.myKeys.AddRange(pool.AvailableItems().Where(key => key != StaticKeys.Nothing && (!options.noEarlyPbs || key != StaticKeys.PowerBombs)).Select(id => KeyManager.GetKey(id)));

                        if (traverser.VerifyBeatable(data, itemMap, testInventory))
                        {
                            break;
                        }

                        seed = random.Next();

                        pool.CreatePool();
                        foreach (var item in itemMap.Values)
                        {
                            pool.Pull(item);
                        }
                    }

                    random = new Random(seed);

                    var randomMap = placer.FillLocations(data, options, pool, startingInventory, random, itemMap);

                    if (gameCompletion == FillOptions.GameCompletion.Beatable)
                    {
                        result = traverser.VerifyBeatable(data, randomMap, new Inventory(startingInventory));
                    }
                    else if (gameCompletion == FillOptions.GameCompletion.AllItems)
                    {
                        result = traverser.VerifyFullCompletable(data, randomMap, new Inventory(startingInventory));
                    }

                    if (result)
                    {
                        Console.WriteLine($"{Environment.NewLine}Randomization complete after {count} attempts - Successful seed: {seed}");

                        Console.WriteLine(traverser.GetWaveLog());

                        _Timer.Stop();

                        resultItemMap = randomMap;
                        return;
                    }

                    seed = random.Next();

                    Console.WriteLine($"Attempts {count}");
                }
                else if (randomizationType == 2)
                {
                    var pool = new ItemPool();
                    pool.CreatePool();

                    random = new Random(seed);

                    var randomMap = StaticData.Locations.ToDictionary(location => location, location => pool.Pull(random));

                    var morphItem = randomMap.FirstOrDefault(x => x.Value.Equals(StaticKeys.Morph));

                    if (string.IsNullOrWhiteSpace(morphItem.Key))
                    {
                        seed = random.Next();
                        continue;
                    }

                    var morphLocation = randomMap.FirstOrDefault(x => x.Key.Equals("BrinstarMorph"));

                    randomMap[morphItem.Key]     = morphLocation.Value;
                    randomMap[morphLocation.Key] = StaticKeys.Morph;

                    var result = false;
                    if (gameCompletion == FillOptions.GameCompletion.Beatable)
                    {
                        result = traverser.VerifyBeatable(data, randomMap, new Inventory(startingInventory));
                    }
                    else if (gameCompletion == FillOptions.GameCompletion.AllItems)
                    {
                        result = traverser.VerifyFullCompletable(data, randomMap, new Inventory(startingInventory));
                    }

                    if (result)
                    {
                        Console.WriteLine($"Randomization complete after {count} attempts - Successful seed: {seed}");

                        _Timer.Stop();

                        resultItemMap = randomMap;
                        return;
                    }

                    if (count % 50 == 0)
                    {
                        Console.WriteLine($"Attempts {count}");
                    }
                }

                count++;

                seed = random.Next();
            }
        }
Ejemplo n.º 18
0
        private Guid FindRelevantKey(Inventory inventory, FillSearcher aSearcher, FillOptions options,
                                     IEnumerable <RandomKeyNode> availableLocations, IEnumerable <NodeBase> unRetracableKeys,
                                     IEnumerable <Guid> restrictedItems, IEnumerable <Guid> prioritizedItems,
                                     ItemPool pool, Dictionary <string, Guid> itemMap,
                                     Random random, LogLayer log)
        {
            var relevantKeyLog = log.AddChild("Relevant Key");

            var relevantKeys = new Dictionary <Guid, List <NodeBase> >();

            foreach (var item in pool.AvailableItems().Distinct().Where(key => !restrictedItems.Contains(key)))
            {
                var testInventory = inventory.Expand(KeyManager.GetKey(item));

                var tempSearcher = new FillSearcher(aSearcher);

                var currentKeyLog = relevantKeyLog.AddChild(KeyManager.GetKeyName(item));

                var  reachableKeys = new List <NodeBase>();
                bool searchAgain;
                do
                {
                    // Find all nodes that can be reached with current inventory
                    reachableKeys.RemoveAll(node => testInventory.myNodes.Contains(node));
                    reachableKeys.AddRange(tempSearcher.ContinueSearch(testInventory, node => (node is KeyNode) && !testInventory.myNodes.Contains(node)));

                    var combinedReachableKeys = unRetracableKeys.Where(key => !testInventory.myNodes.Contains(key)).Union(reachableKeys);

                    searchAgain = false;

                    var retracableKeys = combinedReachableKeys.AsParallel().Where(node => node == endNode || NodeTraverser.PathExists(node, startNode, node is EventKeyNode ? testInventory.Expand(node) : testInventory)).ToList();

                    if (retracableKeys.Any())
                    {
                        // If any events can be reached, add to inventory and update search before continuing
                        var retracableEvents = retracableKeys.Where(node => node is EventKeyNode).ToList();
                        if (retracableEvents.Any())
                        {
                            currentKeyLog.AddChild("Retracable events", retracableEvents.Select(node => node.Name()));
                            testInventory.myNodes.AddRange(retracableEvents);

                            // Prioritize item that will let you beat the game
                            if (retracableEvents.Any(node => node == endNode))
                            {
                                relevantKeyLog.Message += $" : {KeyManager.GetKeyName(item)}";

                                return(item);
                            }

                            searchAgain = true;

                            continue;
                        }

                        var randomizedLocations = retracableKeys.Where(key => key is RandomKeyNode randomNode).Select(key => key as RandomKeyNode).OrderBy(x => x.id).ToList();

                        // Pick up any items already filled in on the map and update search before placing any items
                        var preFilledLocations = randomizedLocations.Where(loc => itemMap.ContainsKey(loc.myRandomKeyIdentifier));

                        if (preFilledLocations.Any())
                        {
                            currentKeyLog.AddChild("Prefilled locations", preFilledLocations.Select(node => $"{node.Name()} - {node.GetKeyName()}"));
                            testInventory.myNodes.AddRange(preFilledLocations);

                            searchAgain = true;

                            continue;
                        }

                        currentKeyLog.AddChild($"Locations", retracableKeys.Select(key => key.Name()));

                        relevantKeys.Add(item, retracableKeys);
                    }
                } while (searchAgain);
            }

            // Filter out any keys that by rules cannot be placed in any available location
            var filteredKeys = relevantKeys.Where(key => availableLocations.Any(location => KeyAllowedInLocation(key.Key, options, itemMap, pool, location))).ToDictionary(key => key.Key, key => key.Value);

            relevantKeyLog.AddChild("Filtered Keys", filteredKeys.Select(key => $"{KeyManager.GetKeyName(key.Key)}"));

            if (!filteredKeys.Any())
            {
                return(Guid.Empty);
            }

            // Correlate prioritized and relevant keys
            var prioritizedRelevantKeys = filteredKeys.Where(key => prioritizedItems.Contains(key.Key));

            if (prioritizedRelevantKeys.Any())
            {
                filteredKeys = prioritizedRelevantKeys.ToDictionary(key => key.Key, key => key.Value);
            }

            relevantKeyLog.AddChild("Prioritized Relevant Keys", filteredKeys.Select(key => $"{KeyManager.GetKeyName(key.Key)}"));

            // Prioritize items that open up major location for local swaps
            if (options.majorSwap == FillOptions.ItemSwap.LocalPool || options.minorSwap == FillOptions.ItemSwap.LocalPool)
            {
                var keysWithMajorLocation = filteredKeys.Where(key => key.Value.Any(location => StaticKeys.IsMajorLocation(location)));
                if (keysWithMajorLocation.Any())
                {
                    filteredKeys = keysWithMajorLocation.ToDictionary(key => key.Key, key => key.Value);
                }
            }

            // Avoid sprawl calculation bias if value is not set or there is only one item to choose from
            if (options.SprawlFactor == 0 || filteredKeys.Count < 2)
            {
                var item = pool.PeekAmong(filteredKeys.Keys, random);

                relevantKeyLog.Message += $" : {KeyManager.GetKeyName(item)}";
                relevantKeyLog.AddChild($"Item pulled from pool: {KeyManager.GetKeyName(item)}");

                return(item);
            }

            relevantKeyLog.AddChild($"Sprawl factor: {options.SprawlFactor}");

            // Translate sprawl factor to a decimal
            var sprawl = ((double)options.SprawlFactor) / 10;

            // Weight is numberOfLocationsUnlocked ^ sprawl
            var keysGroupedByWeight = filteredKeys.ToLookup(key => key.Value.Count, key => key.Key).Select(group => new KeyValuePair <double, List <Guid> >(Math.Pow(group.Key, sprawl), group.ToList())).OrderBy(pair => pair.Key);

            relevantKeyLog.AddChild("Keys with weights", keysGroupedByWeight.SelectMany(group => group.Value.Select(key => $"{KeyManager.GetKeyName(key)} - {group.Key}")));

            // Sum of all weights
            var weightSum = keysGroupedByWeight.Select(pair => pair.Key).Sum();

            relevantKeyLog.AddChild($"Sum of Weights: {weightSum}");

            // Pick random number between 0 and weightSum
            var weightRandom = random.NextDouble() * weightSum;

            relevantKeyLog.AddChild($"Weight Random: {weightRandom}");

            // Remove weight from random value until it goes below zero then pick that key
            foreach (var key in keysGroupedByWeight)
            {
                weightRandom -= key.Key;
                if (weightRandom < 0)
                {
                    relevantKeyLog.AddChild($"Chosen weight: {key.Key}");

                    var item = pool.PeekAmong(key.Value, random);

                    relevantKeyLog.Message += $" : {KeyManager.GetKeyName(item)}";
                    relevantKeyLog.AddChild($"Selected Key: {KeyManager.GetKeyName(item)}");

                    return(item);
                }
            }

            relevantKeyLog.AddChild($"No Key Selected");
            return(Guid.Empty);
        }