コード例 #1
0
        private static int GetTurnsUntilAffordable(TurnCalculatorNode node, Currency cost)
        {
            if (node.PlayerData.CurrencyData.CanAfford(cost))
            {
                return(0);
            }
            if (!node.PlayerData.CurrencyData.HasUtilisableCurrencies(cost))
            {
                return(-1);
            }

            var suppliers       = Cells.GetSuppliers(node.Buildings.Select(b => b as HexCell).ToList());
            var suppliesPerTurn = suppliers.Sum(c => c.CalculateSupplies(node.PlayerData));

            if (suppliesPerTurn <= 0)
            {
                return(-1);
            }

            var requiredSupplies = cost.supplies - node.PlayerData.CurrencyData.Supplies;
            var numTurns         = Mathf.CeilToInt((float)requiredSupplies / suppliesPerTurn);

            const float maxTurnCount = 10;

            if (numTurns > maxTurnCount)
            {
                return(-1);
            }

            return(numTurns);
        }
コード例 #2
0
        private TurnCalculatorNode TryCreateNewNode(TurnCalculatorNode origin, ActionDefinition action)
        {
            if (action is BuildAction buildAction)
            {
                if (origin.Buildings.Contains(buildAction.prefab))
                {
                    return(null);
                }
                if (origin.PlayerData.TechnologyData.HasTechnology(buildAction.prefab.Technology))
                {
                    return(null);
                }
                if (!origin.PlayerData.TechnologyData.HasTechnologies(buildAction.techRequirements))
                {
                    return(null);
                }

                var turnCount = GetTurnsUntilAffordable(origin, buildAction.prefab.Cost);
                if (turnCount < 0)
                {
                    return(null);
                }

                var costForHeuristic = targetCell == null ? targetUpgrade.cost : targetCell.Cost;
                return(new TurnCalculatorNode(origin, buildAction.prefab, turnCount, costForHeuristic));
            }
            else if (action is UpgradeAction upgradeAction)
            {
                UpgradeAction.UpgradeDetails nextUpgrade;
                try
                {
                    nextUpgrade = upgradeAction.upgradeDetails.First(u => !origin.PlayerData.TechnologyData.HasTechnology(u.tech));
                }
                catch
                {
                    return(null);
                }

                if (origin.PlayerData.TechnologyData.HasTechnology(nextUpgrade.tech))
                {
                    return(null);
                }
                if (!origin.PlayerData.TechnologyData.HasTechnologies(nextUpgrade.requiredTech))
                {
                    return(null);
                }

                var turnCount = GetTurnsUntilAffordable(origin, nextUpgrade.cost);
                if (turnCount < 0)
                {
                    return(null);
                }

                var costForHeuristic = targetCell == null ? targetUpgrade.cost : targetCell.Cost;
                return(new TurnCalculatorNode(origin, nextUpgrade, turnCount, costForHeuristic));
            }

            return(null);
        }
コード例 #3
0
        public TurnCalculatorNode(TurnCalculatorNode originalNode, UpgradeAction.UpgradeDetails upgrade, int numTurnsToAfford, Currency targetCost)
        {
            PlayerData = originalNode.PlayerData.Clone();
            Buildings  = originalNode.Buildings;

            ApplyCurrencyModifications(numTurnsToAfford, upgrade.cost);
            PlayerData.TechnologyData.AddTechnology(upgrade.tech);

            PreviousNode = originalNode;
            Action       = "Upgrade " + upgrade.title;

            CalculateNodeCosts(targetCost);
        }
コード例 #4
0
        private void AddToOpenSet(TurnCalculatorNode node)
        {
            if (node.PlayerData.TurnNumber > 50)
            {
                return;
            }

            if (openSet.Any(openNode => openNode.IsEqual(node) && openNode.F < node.F))
            {
                return;
            }
            if (closedSet.Any(closedNode => closedNode.IsEqual(node) && closedNode.F < node.F))
            {
                return;
            }
            openSet.Add(node);
        }
コード例 #5
0
        private List <TurnCalculatorNode> GetNeighbouringNodes(TurnCalculatorNode node)
        {
            var neighbours = new List <TurnCalculatorNode>();

            foreach (var building in node.Buildings)
            {
                foreach (var action in building.Actions)
                {
                    var newNode = TryCreateNewNode(node, action);
                    if (newNode != null)
                    {
                        neighbours.Add(newNode);
                    }
                }
            }

            return(neighbours);
        }
コード例 #6
0
        private Queue <TurnCalculatorNode> ConstructGamePlan(TurnCalculatorNode node)
        {
            var queue = new Stack <TurnCalculatorNode>();

            while (node != null)
            {
                queue.Push(node);
                node = node.PreviousNode;
            }

            var gamePlan = new Queue <TurnCalculatorNode>();

            while (queue.Any())
            {
                gamePlan.Enqueue(queue.Pop());
            }

            return(gamePlan);
        }
コード例 #7
0
ファイル: GamePlan.cs プロジェクト: Aspekt1024/HexCraft
        private void ShowNextTurnSteps(TurnCalculatorNode node, int turnNumber, VisualElement container)
        {
            var numTurnsSinceLastAction = node.PlayerData.TurnNumber - turnNumber;

            for (int i = 0; i < numTurnsSinceLastAction; i++)
            {
                var details = new StepRowDetails
                {
                    TurnNumber           = turnNumber + i + 1,
                    Label                = "Next turn",
                    StyleClass           = "plan-step-nextturn",
                    InitialSupplies      = node.InitialSupplies + node.SuppliesPerTurn * i,
                    InitialProduction    = node.InitialProduction,
                    SupplyDifference     = node.SuppliesPerTurn,
                    ProductionDifference = 0,
                    PopulationDifference = 0,
                };
                var step = CreateStepRow(details);

                container.Add(step);
            }
        }
コード例 #8
0
        public TurnCalculatorNode(TurnCalculatorNode originalNode, HexCell newCell, int numTurnsToAfford, Currency targetCost)
        {
            PlayerData = originalNode.PlayerData.Clone();
            Buildings  = originalNode.Buildings.ToList();

            ApplyCurrencyModifications(numTurnsToAfford, newCell.Cost);

            PlayerData.TechnologyData.AddTechnology(newCell.Technology);

            if (newCell is BuildingCell building)
            {
                Buildings.Add(building);
                var currencyBonus = building.GetCurrencyBonus();
                PlayerData.CurrencyData.Production.maximum += currencyBonus.production;
                PlayerData.CurrencyData.Population.maximum += currencyBonus.population;
            }

            PreviousNode = originalNode;
            Action       = "Purchase " + newCell.DisplayName;

            CalculateNodeCosts(targetCost);
        }
コード例 #9
0
 private bool NodeAchievesGamePlan(TurnCalculatorNode node)
 {
     return(node.PlayerData.TechnologyData.HasTechnology(targetCell != null ? targetCell.Technology : targetUpgrade.tech));
 }
コード例 #10
0
 public bool IsEqual(TurnCalculatorNode other)
 {
     return(other.PlayerData.HasSameData(PlayerData) &&
            other.Buildings.Count == Buildings.Count &&
            other.Buildings.All(b => Buildings.Contains(b)));
 }