Пример #1
0
        /// <summary>
        /// Returns a list of possible Recipes that a given character is able to craft.
        /// </summary>
        /// <param name="carrier">Probably the player character.</param>
        /// <returns>A list of possible recipes. Keep it, and invoke Apply on the player's choice.</returns>
        public static List <Recipe> GetPossibilities(Character carrier)
        {
            Carrier         = carrier;
            ItemsToWorkWith = Carrier.GetToken("items");
            var results = new List <Recipe>();
            var tml     = Mix.GetTokenTree("crafting.tml");

            foreach (var recipe in tml)
            {
                var considered = new List <Token>();
                var resultName = "?";
                if (recipe.HasToken("produce"))
                {
                    resultName = recipe.GetToken("produce").Text;
                }
                var resultingSourceItem = default(InventoryItem);

                var steps     = recipe.Tokens;
                var stepRefs  = new Token[steps.Count()];
                var i         = 0;
                var newRecipe = new Recipe();
                foreach (var step in steps)
                {
                    if (step.Name == "consume" || step.Name == "require")
                    {
                        var amount = 1;
                        if (step.HasToken("amount"))
                        {
                            amount = (int)step.GetToken("amount").Value;
                        }

                        var numFound = 0;
                        if (step.Text == "<anything>")
                        {
                            foreach (var carriedItem in ItemsToWorkWith.Tokens)
                            {
                                var knownItem = NoxicoGame.KnownItems.Find(ki => ki.ID == carriedItem.Name);
                                if (knownItem == null)
                                {
                                    Program.WriteLine("Crafting: don't know what a {0} is.", carriedItem.Name);
                                    continue;
                                }

                                var withs    = step.GetAll("with");
                                var withouts = step.GetAll("withouts");
                                var okay     = 0;
                                foreach (var with in withs)
                                {
                                    if (knownItem.HasToken(with.Text))
                                    {
                                        okay++;
                                    }
                                }
                                foreach (var without in withouts)
                                {
                                    if (knownItem.HasToken(without.Text))
                                    {
                                        okay = 0;
                                    }
                                }
                                if (okay < withs.Count())
                                {
                                    continue;
                                }

                                if (carriedItem.HasToken("charge"))
                                {
                                    numFound += (int)carriedItem.GetToken("charge").Value;
                                }
                                else
                                {
                                    numFound++;
                                }
                                stepRefs[i] = carriedItem;

                                if (i == 0)
                                {
                                    resultingSourceItem = knownItem;
                                }
                            }
                        }
                        else if (step.Text == "book")
                        {
                            //TODO: see if a book with the given ID is marked as read.
                        }
                        else
                        {
                            foreach (var carriedItem in ItemsToWorkWith.Tokens.Where(t => t.Name == step.Text))
                            {
                                var knownItem = NoxicoGame.KnownItems.Find(ki => ki.ID == carriedItem.Name);
                                if (knownItem == null)
                                {
                                    Program.WriteLine("Crafting: don't know what a {0} is.", carriedItem.Name);
                                    continue;
                                }

                                if (carriedItem.HasToken("charge"))
                                {
                                    numFound += (int)carriedItem.GetToken("charge").Value;
                                }
                                else
                                {
                                    numFound++;
                                }
                                stepRefs[i] = carriedItem;

                                if (i == 0)
                                {
                                    resultingSourceItem = knownItem;
                                }
                            }
                        }

                        if (numFound < amount)
                        {
                            Program.WriteLine("Crafting: not enough {0} to craft {1}.", step.Text, resultName);
                            break;
                        }
                        if (step.Name == "consume")
                        {
                            newRecipe.Actions.Add(new CraftConsumeItemAction()
                            {
                                Target = stepRefs[i]
                            });
                        }
                    }
                    else if (step.Name == "produce")
                    {
                        var itemMade = new Token(step.Text);
                        itemMade.Tokens.AddRange(step.Tokens);
                        newRecipe.Actions.Add(new CraftProduceItemAction()
                        {
                            Target = itemMade
                        });
                        var resultingKnownItem = NoxicoGame.KnownItems.Find(ki => ki.ID == itemMade.Name);
                        newRecipe.Display = i18n.Format("craft_produce_x_from_y", resultingKnownItem.ToString(itemMade), resultingSourceItem.ToString(stepRefs[0]));
                    }
                    else if (step.Name == "train")
                    {
                        newRecipe.Actions.Add(new CraftTrainAction()
                        {
                            Trainee = carrier, Target = step
                        });
                    }
                }
                if (newRecipe.Display.IsBlank())
                {
                    continue;
                }
                if (results.Exists(x => x.Display == newRecipe.Display))
                {
                    continue;
                }
                results.Add(newRecipe);
            }

            //Find dyes
            foreach (var maybeDye in ItemsToWorkWith.Tokens)
            {
                var knownItem = NoxicoGame.KnownItems.Find(ki => ki.ID == maybeDye.Name);
                if (knownItem == null)
                {
                    Program.WriteLine("Crafting: don't know what a {0} is.", maybeDye.Name);
                    continue;
                }

                if (knownItem.HasToken("dye"))
                {
                    var dyeItem = maybeDye;
                    var color   = dyeItem.GetToken("color").Text;
                    foreach (var carriedItem in ItemsToWorkWith.Tokens)
                    {
                        knownItem = NoxicoGame.KnownItems.Find(ki => ki.ID == carriedItem.Name);
                        if (knownItem == null)
                        {
                            Program.WriteLine("Crafting: don't know what a {0} is.", carriedItem.Name);
                            continue;
                        }

                        if (knownItem.HasToken("colored") && !knownItem.HasToken("dye"))
                        {
                            var newRecipe = new Recipe();
                            newRecipe.Display = i18n.Format("craft_dye_x_y", knownItem.ToString(carriedItem), color);
                            if (!carriedItem.HasToken("color"))
                            {
                                newRecipe.Actions.Add(new CraftAddTokenAction()
                                {
                                    Target = carriedItem, Add = new Token("color", 0, color)
                                });
                            }
                            else if (carriedItem.GetToken("color").Text == color)
                            {
                                continue;
                            }
                            else
                            {
                                newRecipe.Actions.Add(new CraftChangeTokenAction()
                                {
                                    Target = carriedItem.GetToken("color"), NewText = color, NewValue = 0
                                });
                            }
                            results.Add(newRecipe);
                        }
                    }
                }
            }
            return(results);
        }