Beispiel #1
0
 public ReactionCardType Initialized(ResourceCost cost, ResourceCost gain, CardReactionSequence action)
 {
     this.cost       = cost;
     this.onPlayGain = gain;
     actionSequence  = action;
     return(this);
 }
Beispiel #2
0
    /// <summary>
    /// Handles left clicking when placing a building
    /// </summary>
    /// <param name="location">The location the action occured from</param>
    private void BuildingMouseLeft(LocationStruct location)
    {
        Building building = currentObject.GetComponent <Building>();

        if (building == null)
        {
            return;
        }
        ResourceCost resCost = currentObject.GetComponent <ResourceCost>();

        if (resCost == null)
        {
            Debug.Log(string.Format("Buildable object {0} does not have a resource cost script", currentObject.name));
        }
        if (!resCost.CheckCost())
        {
            return;
        }
        resCost.DecreaseResources();
        selectedPrefab = null;
        GameObject  tile         = Board.board[location.row, location.column];
        TileControl tc           = tile.GetComponent <TileControl>();
        GameObject  actualObject = (GameObject)PhotonNetwork.Instantiate(Utils.RemoveClone(currentObject.name), currentObject.transform.position, currentObject.transform.rotation, 0);

        Destroy(HUD.currentObject);
        currentObject = null;

        tc.SetOccupyingObject(actualObject);
        actualObject.GetComponent <BoardLocation>().SetLocation(location.row, location.column);

        currState = ActionState.NO_ACTION;
    }
        private ResourceCost ReserveCost(ResourceCost cost)
        {
            var result = new ResourceCost();

            result.Resource = cost.Resource;
            result.Amount   = -cost.Amount;
            return(result);
        }
Beispiel #4
0
 static bool Prefix(ResourceSystem __instance, byte faction, ref ResourceCost buildCost)
 {
     if (faction == __instance.Battle.LocalPlayerFactionId)
     {
         Traverse.Create(buildCost).Property("PopulationCost").SetValue(0);
     }
     return(true);
 }
        public override void ApplyReward()
        {
            ResearchOption research = UnityEngine.Object.Instantiate(Research);

            ResourceCost[] combined = new ResourceCost[] { research.ResourceCost, AddedCost };
            research.ResourceCost = combined.Sum().ToResourceCost();
            ResearchController.Instance.AddResearchOption(Research);
        }
 public void DeductFromResources(ResourceCost resourceCost)
 {
     fruitAmount = fruitAmount - resourceCost.fruitAmount;
     meatAmount  = meatAmount - resourceCost.meatAmount;
     woodAmount  = woodAmount - resourceCost.woodAmount;
     stoneAmount = stoneAmount - resourceCost.stoneAmount;
     metalAmount = metalAmount - resourceCost.metalAmount;
     UpdateDisplays();
 }
Beispiel #7
0
    public static bool CanAfford(this Member m, ResourceCost c)
    {
        if (!c.IsXCost && c.Amount == 0)
        {
            return(true);
        }
        var costAmount = c.ResourcesSpent(m);
        var remaining  = m.State.ResourceAmount(costAmount.ResourceType) - costAmount.Amount;

        return(remaining >= 0);
    }
Beispiel #8
0
    public bool PayOut(ResourceCost cost)
    {
        if (!CheckPayOutPossible(cost) || !CheckCorrectResource(cost))
        {
            return(false);
            // error -> not enough resources || wrong resource type
        }

        storedResources -= cost.amount;
        return(true);
    }
Beispiel #9
0
    public void PayIn(ResourceCost cost)
    {
        if (!CheckCorrectResource(cost))
        {
            // error -> wrong resource type
            return;
        }

        //Debug.Log(cost.FormattedStatusString());
        storedResources += cost.amount;
    }
Beispiel #10
0
 public Attack(
     string name,
     ResourceCost mainResourceCost,
     string description,
     Sprite icon,
     List <Action> actions,
     PlayCondition playCondition = null,
     EndOfExecutionProcess endOfExecutionProcess = null
     ) :
     base(name, mainResourceCost, description, icon, actions, playCondition, endOfExecutionProcess)
 {
 }
Beispiel #11
0
 public AttackAbility(
     string name,
     ResourceCost mainResourceCost,
     string description,
     Sprite icon,
     List <Action> actions,
     PlayCondition playCondition = null,
     EndOfExecutionProcess endOfExecutionProcess = null,
     int totalCoolDown = 0
     ) :
     base(name, mainResourceCost, description, icon, actions, playCondition, endOfExecutionProcess, totalCoolDown)
 {
 }
        public static ReservationDateRangeItem Create(int reservationId, int resourceId, string resourceName, int procTechId, string procTechName, int clientId, string username, string lname, string fname, int activityId, string activityName, int accountId, string accountName, string shortCode, int chargeTypeId, bool isActive, bool isStarted, DateTime beginDateTime, DateTime endDateTime, DateTime?actualBeginDateTime, DateTime?actualEndDateTime, DateTime lastModifiedOn, DateTime?cancelledDateTime, double chargeMultiplier, IEnumerable <ICost> costs)
        {
            // we need to truncate dates to remove milliseconds or else we end up with very small
            // transfer durations (the difference between charged and utilized durations)

            var truncatedCancelledDateTime   = Utility.Truncate(cancelledDateTime);
            var truncatedBeginDateTime       = Utility.Truncate(beginDateTime);
            var truncatedEndDateTime         = Utility.Truncate(endDateTime);
            var truncatedActualBeginDateTime = Utility.Truncate(actualBeginDateTime);
            var truncatedActualEndDateTime   = Utility.Truncate(actualEndDateTime);

            bool          isCancelledBeforeCutoff = Reservations.GetIsCancelledBeforeCutoff(truncatedCancelledDateTime, truncatedBeginDateTime);
            IResourceCost cost = ResourceCost.CreateResourceCosts(costs.Where(c => (c.RecordID == resourceId || c.RecordID == 0) && c.ChargeTypeID == chargeTypeId)).FirstOrDefault();

            var chargeBeginDateTime = (truncatedActualBeginDateTime.HasValue && truncatedActualBeginDateTime < truncatedBeginDateTime) ? truncatedActualBeginDateTime.Value : truncatedBeginDateTime;
            var chargeEndDateTime   = (truncatedActualEndDateTime.HasValue && truncatedActualEndDateTime > truncatedEndDateTime) ? truncatedActualEndDateTime.Value : truncatedEndDateTime;

            var item = new ReservationDateRangeItem
            {
                ReservationID           = reservationId,
                ResourceID              = resourceId,
                ResourceName            = resourceName,
                ProcessTechID           = procTechId,
                ProcessTechName         = procTechName,
                ClientID                = clientId,
                UserName                = username,
                LName                   = lname,
                FName                   = fname,
                ActivityID              = activityId,
                ActivityName            = activityName,
                AccountID               = accountId,
                AccountName             = accountName,
                ShortCode               = shortCode,
                ChargeTypeID            = chargeTypeId,
                IsActive                = isActive,
                IsStarted               = isStarted,
                BeginDateTime           = truncatedBeginDateTime,
                EndDateTime             = truncatedEndDateTime,
                ActualBeginDateTime     = truncatedActualBeginDateTime,
                ActualEndDateTime       = truncatedActualEndDateTime,
                ChargeBeginDateTime     = chargeBeginDateTime,
                ChargeEndDateTime       = chargeEndDateTime,
                LastModifiedOn          = lastModifiedOn,
                IsCancelledBeforeCutoff = isCancelledBeforeCutoff,
                ChargeMultiplier        = chargeMultiplier,
                Cost = cost
            };

            return(item);
        }
Beispiel #13
0
 void AttachTowerComponentToPointer(ResourceController resourceController, ResourceCost resourceCost)
 {
     if (resourceController.CanAfford(resourceCost))
     {
         ComponentPlacer placer = cam.GetComponent <ComponentPlacer> ();
         placer.towerComponent    = towerComponent;
         placer.componentSelected = true;
         placer.AttachToPointer();
     }
     else
     {
         Debug.Log("Insufficient Resources");
     }
 }
    public ResourceTransaction GeneratePayOutTransaction()
    {
        ResourceTransaction transaction = ResourceTransactionFactory.Create();

        foreach (var workerMapEntry in workerCounts)
        {
            ResourceType type       = workerMapEntry.Key;
            int          numWorkers = workerMapEntry.Value;

            ResourceCost cost = ResourceCostFactory.Create(workerMapEntry.Key, numWorkers * resourcesGeneratedPerWorker);
            transaction.AddResourceCost(cost);
        }

        return(transaction);
    }
Beispiel #15
0
 public Card(
     string name,
     ResourceCost mainResourceCost,
     string description,
     Sprite icon,
     List <Action> actions,
     PlayCondition playCondition = null,
     EndOfExecutionProcess endOfExecutionProcess = null
     ) :
     base(name, mainResourceCost, description, icon, actions, playCondition, endOfExecutionProcess)
 {
     if (endOfExecutionProcess == null)
     {
         this.endOfExecutionProcess = new AddToDiscardEndOfExecutionProcess();
     }
 }
Beispiel #16
0
    /// <summary>
    /// Displays the resources required for the selected object as well as the current amount of resources
    /// </summary>
    /// <param name="args"></param>
    /// <returns></returns>
    public string GetCurrentResources(params string[] args)
    {
        if (HUD.currentObject == null)
        {
            return("You have to select a building for this to work");
        }
        HUD           hud           = Camera.main.GetComponent <HUD>();
        GameResources resources     = hud.GetResources();
        GameObject    currentObject = HUD.currentObject;
        ResourceCost  resCost       = currentObject.GetComponent <ResourceCost>();
        string        ret           = string.Format("Costs: {0} {1} {2}\r\n", resCost.CostRes1, resCost.CostRes2, resCost.CostRes3);

        ret += string.Format("Current resources: {0} {1} {2}\r\n", resources.GetResource(GameResources.ResourceTypes.RES1), resources.GetResource(GameResources.ResourceTypes.RES2), resources.GetResource(GameResources.ResourceTypes.RES3));
        ret += string.Format("Output of checkcost: {0}\r\n", resCost.CheckCost());
        return(ret);
    }
 public ActionGroup(string name,
                    ResourceCost mainResourceCost,
                    string description,
                    Sprite icon,
                    List <Action> actions,
                    PlayCondition playCondition = null,
                    EndOfExecutionProcess endOfExecutionProcess = null
                    )
 {
     this.name             = name;
     this.mainResourceCost = mainResourceCost;
     this.description      = description;
     this.icon             = icon;
     this.actions          = actions;
     this.playCondition    = playCondition;
 }
Beispiel #18
0
    // Use this for initialization
    void Start()
    {
        cam                = Camera.main;
        father             = gameObject.transform.parent.gameObject;
        button             = GetComponent <Button> ();
        resourceController = GameObject.FindWithTag("Player").GetComponent <ResourceController> ();
        resourceCost       = towerComponent.GetComponent <ResourceCost> ();

        button.onClick.AddListener(() => {
            AttachTowerComponentToPointer(resourceController, resourceCost);
        });

        button.onClick.AddListener(() => {
            CloseFather();
        });
    }
Beispiel #19
0
 /// <summary>
 ///
 /// Initialises the Resource Data on the card. To be called when the card is created
 ///
 /// </summary>
 public void ResourceInit()
 {
     if (!ResourceConvertedTo.HasValue || ResourceCost.Count == 0)
     {
         ResourceCost = new List <Resource>();
         Resources    = new List <CardResources>();
         foreach (var resource in DefaultCost)
         {
             ResourceCost.Add(new Resource(resource));
             Resources.Add(resource.ResourceType);
         }
     }
     else
     {
         ResourceCost.FirstOrDefault().SetValue(CardData.TotalResource);
         ResourceConvert(ResourceConvertedTo.Value);
     }
 }
Beispiel #20
0
    public static ResourceQuantity ResourcesSpent(this ResourceCost cost, Member m)
    {
        if (cost == null || cost.ResourceType == null)
        {
            return new ResourceQuantity {
                       Amount = 0, ResourceType = ""
            }
        }
        ;

        return(new ResourceQuantity
        {
            ResourceType = cost.ResourceType.Name,
            Amount = cost.IsXCost
                ? m.State[cost.ResourceType]
                : cost.Amount
        });
    }
Beispiel #21
0
    public static ResourceQuantity ResourcesGained(this ResourceCost gain, Member m)
    {
        if (gain == null || gain.ResourceType == null)
        {
            return new ResourceQuantity {
                       Amount = 0, ResourceType = ""
            }
        }
        ;

        return(new ResourceQuantity
        {
            ResourceType = gain.ResourceType.Name,
            Amount = gain.IsXCost
                ? m.ResourceMax(gain.ResourceType)
                : gain.Amount
        });
    }
}
Beispiel #22
0
    /// <summary>
    /// Responds to a hud action
    /// </summary>
    /// <param name="go">The gameobject that was clicked</param>
    public override void HUDAction(GameObject go)
    {
        ResourceCost resCost = go.GetComponent <ResourceCost>();

        if (resCost == null)
        {
            Debug.LogError(string.Format("Buildable object {0} does not have a resource cost script", go.name));
        }
        if (!resCost.CheckCost())
        {
            return;
        }
        resCost.DecreaseResources();
        ProductionStruct ps = new ProductionStruct();

        ps.productionObject = go;
        ps.turnsLeft        = go.GetComponent <Unit>().BuildTurns;
        buildQueue.Add(ps);
    }
 public bool CanAfford(ResourceCost resourceCost)
 {
     if (resourceCost.fruitAmount <= fruitAmount)
     {
         if (resourceCost.meatAmount <= meatAmount)
         {
             if (resourceCost.woodAmount <= woodAmount)
             {
                 if (resourceCost.stoneAmount <= stoneAmount)
                 {
                     if (resourceCost.metalAmount <= metalAmount)
                     {
                         return(true);
                     }
                 }
             }
         }
     }
     return(false);
 }
Beispiel #24
0
    bool ReduceResources(GameObject inSpawnObj)
    {
        ResourceCost resourceCost = inSpawnObj.GetComponent <ResourceCost> ();

        if (resourceCost == null)
        {
            //Debug.Log ("UnSpawnable Instance!!");
            return(false);
        }
        if (resourceCost.resourceCost > currentResource)
        {
            //Debug.Log ("Not enough resources!!");
            return(false);
        }

        currentResource         -= resourceCost.resourceCost;
        resourceSlider.value     = currentResource;
        currentResourceText.text = currentResource.ToString();
        return(true);
    }
        public decimal EstimateToolRunCost(int chargeTypeId, int resourceId, double duration)
        {
            //duration is minutes

            var costs = Provider.Data.Cost.FindToolCosts(resourceId, chargeTypeId: chargeTypeId);

            List <IResourceCost> resCosts = ResourceCost.CreateResourceCosts(costs).ToList();

            var rc = resCosts.FirstOrDefault();

            decimal result = 0;
            decimal dur    = Convert.ToDecimal(duration) / 60M;

            if (rc != null)
            {
                result = (rc.HourlyRate() * dur) + rc.PerUseRate();
            }

            return(result);
        }
        private static ReservationDateRangeItem CreateReservation(IReservationItem rsv, IEnumerable <ICost> costs)
        {
            var           filtered = costs.Where(c => (c.RecordID == rsv.ResourceID || c.RecordID == 0) && c.ChargeTypeID == rsv.ChargeTypeID).ToList();
            IResourceCost rc       = ResourceCost.CreateResourceCosts(filtered).FirstOrDefault();

            if (rc == null)
            {
                throw new Exception($"Cannot determine cost for Resource: [{rsv.ResourceID}] {rsv.ResourceName}");
            }

            return(new ReservationDateRangeItem()
            {
                ReservationID = rsv.ReservationID,
                ResourceID = rsv.ResourceID,
                ResourceName = rsv.ResourceName,
                ProcessTechID = rsv.ProcessTechID,
                ProcessTechName = rsv.ProcessTechName,
                ClientID = rsv.ClientID,
                UserName = rsv.UserName,
                LName = rsv.LName,
                FName = rsv.FName,
                ActivityID = rsv.ActivityID,
                ActivityName = rsv.ActivityName,
                AccountID = rsv.AccountID,
                AccountName = rsv.AccountName,
                ShortCode = rsv.ShortCode,
                ChargeTypeID = rsv.ChargeTypeID,
                IsActive = rsv.IsActive,
                IsStarted = rsv.IsStarted,
                BeginDateTime = rsv.BeginDateTime,
                EndDateTime = rsv.EndDateTime,
                ActualBeginDateTime = rsv.ActualBeginDateTime,
                ActualEndDateTime = rsv.ActualEndDateTime,
                ChargeBeginDateTime = rsv.ChargeBeginDateTime,
                ChargeEndDateTime = rsv.ChargeEndDateTime,
                LastModifiedOn = rsv.LastModifiedOn,
                IsCancelledBeforeCutoff = rsv.IsCancelledBeforeCutoff,
                ChargeMultiplier = rsv.ChargeMultiplier,
                Cost = rc
            });
        }
Beispiel #27
0
        /// <summary>
        /// Sells the given entity
        /// </summary>
        /// <param name="entity">Target entity to be sold</param>
        /// <returns>The amount of resources gained</returns>
        public List <ResourceCost> SellItem(GridEntity entity)
        {
            var result = new List <ResourceCost>();

            foreach (var cost in entity.ManufactureCost)
            {
                var resource       = cost.Resource;
                var amountRefunded = cost.Amount * Settings.GeneralSettings.RefundPriceRatio;

                var roomLeft    = this.GetResourceCapacity(resource);
                var amountOwned = this.GetResourceOwnedAmount(resource);
                var maxAmount   = amountOwned - roomLeft;

                var refundedCost = new ResourceCost();
                refundedCost.Resource = resource;
                refundedCost.Amount   = Mathf.Min(amountRefunded, maxAmount);

                this.CurrentSaveFile.Inventory[resource] += refundedCost.Amount;
                result.Add(refundedCost);
            }

            return(result);
        }
Beispiel #28
0
    /// <summary>
    ///
    /// Gets the status of a particular resource- i.e. whether it is increase, decreased or not changed
    ///
    /// </summary>
    private StatisticStatuses GetResourceStatus(CardResources resource)
    {
        if (ResourceConvertedTo.HasValue)
        {
            return(StatisticStatuses.Converted);
        }

        var currentCost = ResourceCost.Single(x => x.ResourceType == resource).Value;
        var defaultCost = DefaultCost.Single(x => x.ResourceType == resource).Value;

        //Note that the signs are flipped as cost is always negative
        if (currentCost > defaultCost)
        {
            return(StatisticStatuses.Buffed);
        }
        else if (currentCost < defaultCost)
        {
            return(StatisticStatuses.Debuffed);
        }
        else
        {
            return(StatisticStatuses.None);
        }
    }
Beispiel #29
0
    public bool RecalculateCost()
    {
        ResourceInit();

        foreach (var adjustCostObject in CostAdjustments)
        {
            if (!adjustCostObject.MustBeGreaterThan.HasValue || adjustCostObject.MustBeGreaterThan.HasValue && TotalResource < -adjustCostObject.MustBeGreaterThan.Value)
            {
                if (adjustCostObject.TargetResource.HasValue)
                {
                    if (!Resources.Contains(adjustCostObject.TargetResource.Value))
                    {
                        return(false);
                    }

                    var resourceCost = ResourceCost.Single(x => x.ResourceType == adjustCostObject.TargetResource);

                    switch (adjustCostObject.AdjustmentType)
                    {
                    case StatModifierTypes.Modify:
                        resourceCost.ModifyValue(-adjustCostObject.Value, adjustCostObject.MinCost.HasValue, -adjustCostObject.MinCost);
                        break;

                    case StatModifierTypes.Set:
                        resourceCost.SetValue(-adjustCostObject.Value);
                        break;

                    default:
                        throw new Exception("Not a valid stat mod type");
                    }
                }
                else
                {
                    foreach (var resourceCost in ResourceCost)
                    {
                        switch (adjustCostObject.AdjustmentType)
                        {
                        case StatModifierTypes.Modify:
                            resourceCost.ModifyValue(-adjustCostObject.Value, adjustCostObject.MinCost.HasValue, -adjustCostObject.MinCost);
                            break;

                        case StatModifierTypes.Set:
                            resourceCost.SetValue(-adjustCostObject.Value);
                            break;

                        default:
                            throw new Exception("Not a valid stat mod type");
                        }
                    }

                    //Removing the mixed modify cost as it was perhaps too complicated/confusing. May add this in later
                    //For now, modifying cost just modifies each resource in the list
                    #region Mixed Modify Cost
                    //if (Resources.Count == 1)
                    //{
                    //    var resourceCost = ResourceCost.FirstOrDefault();

                    //    switch (statModType)
                    //    {
                    //        case StatModifierTypes.Modify:
                    //            resourceCost.ModifyValue(-value, true);
                    //            break;
                    //        case StatModifierTypes.Set:
                    //            resourceCost.SetValue(value);
                    //            break;
                    //        default:
                    //            throw new Exception("Not a valid stat mod type");
                    //    }
                    //}
                    //else
                    //{
                    //    bool isOdd = false;
                    //    if (statModType == StatModifierTypes.Modify)
                    //    {
                    //        if (value % 2 == 1)
                    //        {
                    //            value -= 1;
                    //            isOdd = true;
                    //        }
                    //        else if (value % 2 == -1)
                    //        {
                    //            value += 1;
                    //            isOdd = true;
                    //        }
                    //        value /= Resources.Count;
                    //    }

                    //    switch (statModType)
                    //    {
                    //        case StatModifierTypes.Modify:
                    //            ResourceCost.ForEach(x => x.ModifyValue(-value, true));
                    //            break;
                    //        case StatModifierTypes.Set:
                    //            ResourceCost.ForEach(x => x.SetValue(value));
                    //            break;
                    //        default:
                    //            throw new Exception("Not a valid stat mod type");
                    //    }


                    //    if (isOdd)
                    //    {
                    //        var highestResources = ResourceCost.Where(x => x.Value == ResourceCost.Min(y => y.Value)).ToList();
                    //        var valueModifier = value > 0 ? -1 : 1;
                    //        if (highestResources.Count() == 1)
                    //        {
                    //            highestResources.FirstOrDefault().ModifyValue(valueModifier, true);
                    //        }
                    //        else
                    //        {
                    //            var randomResource = UnityEngine.Random.Range(0, highestResources.Count());
                    //            highestResources[randomResource].ModifyValue(valueModifier, true);
                    //        }
                    //    }
                    //}
                    #endregion
                }
            }
        }

        //Loops through each resource to clamp the values of each resource
        foreach (var resourceCost in ResourceCost)
        {
            //Modifies the cost by 0 to clamp the resource value
            resourceCost.ModifyValue(0, true);
        }

        return(true);
    }
	void init(bool isInsideCard, string cardName, ResourceCost cardCost) {
		this.isInsideCard = isInsideCard;
	}
        /// <summary>
        /// The recursive reduction function.  It searches every possible resource path until a good one is found,
        /// or if doing LowestCost, it searches every possible resource path and returns the cheapest one.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="lowCost"></param>
        /// <param name="remainingCost"></param>
        static void ReduceRecursively(ReduceState state, ref ResourceCost lowCost, string remainingCost)
        {
            if (remainingCost == string.Empty)
            {
                // success!  This combination of resources reduced the cost to zero.

                ResourceCost rc = new ResourceCost();

                foreach (ResourceUsed ru in state.currentResourceStack)
                {
                    if (ru.owner == ResourceOwner.Left)
                    {
                        rc.left += ru.cost * (ru.usedDoubleResource ? 2 : 1);
                    }
                    else if (ru.owner == ResourceOwner.Right)
                    {
                        rc.right += ru.cost * (ru.usedDoubleResource ? 2 : 1);
                    }
                    else
                    {
                        rc.bank += ru.cost;
                    }
                }

                if (state.marketEffects.HasFlag(CommerceEffects.ClandestineDockWest) && rc.left != 0) --rc.left;
                if (state.marketEffects.HasFlag(CommerceEffects.ClandestineDockEast) && rc.right != 0) --rc.right;

                bool replaceResourceStack = false;

                if (state.lowestCostResourceStack.Count == 0)
                {
                    replaceResourceStack = true;
                }
                else
                {
                    // When I started doing LowestCost, my initial implementation of this was to compare each
                    // resource used in this stack to those in the existing good stack, and replace any resources
                    // in the existing stack with those in the new stack, if the new stack had a lower cost.  However,
                    // this broke when there were choices (e.g. a forum), and this resource was being used twice.
                    // e.g. this test case was failing:
                    // expectedResult.leftCoins = 2;
                    // expectedResult.rightCoins = 1;
                    // Verify2(new Cost("WSBPG"), new List<ResourceEffect> { stone_1 /* putting a wood here works, stone does not */, caravansery, forum },
                    //     new List<ResourceEffect> { papyrus, glass, }, new List<ResourceEffect> { wood_clay },
                    //     ResourceManager.CommercePreferences.LowestCost | ResourceManager.CommercePreferences.BuyFromLeftNeighbor,
                    //     ResourceManager.CommerceEffects.EastTradingPost,
                    //    expectedResult);
                    //
                    // An analysis indicated what was happening was the Forum was being used twice to fulfill the Papyrus
                    // resource, once from the first match (when glass was purchased), then again from a later match,
                    // (when Papyrus was purchased)

                    if ((rc.left + rc.right + rc.bank) < (lowCost.left + lowCost.right + lowCost.bank))
                    {
                        // This is a cheaper overall stack than the existing one, so use it
                        replaceResourceStack = true;
                    }
                    else if ((rc.left + rc.right) == (lowCost.left + lowCost.right))
                    {
                        // This branch indicates the amount paid to each neighbor is the same in this stack compared with the
                        // existing good stack, so we do a secondary comparison for the costs to each neighbor and pay the
                        // preferred one if the cost to the non-preferred one is lower.  Note, that we intentionally do not
                        // the bank cost in this secondary comparison as we would prefer to pay for Bilkis' resource than pay
                        // a neighbor for theirs.
                        replaceResourceStack =
                            (state.pref.HasFlag(CommercePreferences.BuyFromLeftNeighbor) && lowCost.left < rc.left) ||
                            (state.pref.HasFlag(CommercePreferences.BuyFromRightNeighbor) && lowCost.right < rc.right);
                    }
                }

                if (replaceResourceStack)
                {
                    // replace the existing used resource list with this cheaper one.
                    state.lowestCostResourceStack.Clear();

                    foreach (ResourceUsed r in state.currentResourceStack)
                    {
                        state.lowestCostResourceStack.Add(r);
                    }

                    lowCost = rc;
                }

               // do not continue down this search path once we have a completed path.  The algorithm
               // searches every possible combination and if there's a cheaper good path, it will be found
               return;
            }

            // we need to check every possible path, starting at the current recursion level, going from cheapest
            // possible resource to the most expensive.  This should return the cheapest possible coin cost for
            // the structure under consideration.
            while (state.myResourceIndex < state.myResources.Count ||
                state.leftResourceIndex < state.leftResourcesAvailable ||
                state.rightResourceIndex < state.rightResourcesAvailable ||
                state.nBlackMarketIndex < state.nBlackMarketAvailable ||
                state.wildResource == SpecialTrait.Unused ||
                state.bilkis == SpecialTrait.Unused)
            {
                ResourceEffect res = null;

                if (state.lowestCostResourceStack.Count != 0 && !state.pref.HasFlag(CommercePreferences.LowestCost))
                    break;

                int myInc= 0;
                int leftInc = 0;
                int rightInc = 0;
                bool usedWildResource = false;
                bool usedBilkis = false;
                ResourceUsed resUsed;

                if (state.myResourceIndex < state.myResources.Count)
                {
                    // my city's resources are free, use them up first.
                    res = state.myResources[state.myResourceIndex];
                    myInc = 1;
                    resUsed = new ResourceUsed(ResourceOwner.Self, 0);
                }
                else if (state.nBlackMarketIndex < state.nBlackMarketAvailable)
                {
                    res = state.blackMarketResource;
                    resUsed = new ResourceUsed(ResourceOwner.Self, 0);
                }
                else if (state.wildResource == SpecialTrait.Unused)
                {
                    // Archimedes, Imhotep, Leonidas and Hammurabi.  These resources have no cost
                    usedWildResource = true;
                    res = state.wildResourceEffect;
                    resUsed = new ResourceUsed(ResourceOwner.Self, 0);
                }
                else if (state.bilkis == SpecialTrait.Unused)
                {
                    // Bilkis costs one coin but that's better than paying a neighbor (unless they have a Clandestine Dock)
                    usedBilkis = true;
                    res = state.wildResourceEffect;
                    resUsed = new ResourceUsed(ResourceOwner.Self, 1);
                }
                else
                {
                    // try to find the remaining resources via commerce.  By default, we prefer to purchase
                    // from our left neighbor, but this is controllable.

                    bool buyingFromLeft = true;

                    if (state.pref.HasFlag(CommercePreferences.BuyFromLeftNeighbor))
                    {
                        if (state.leftResourceIndex < state.leftResourcesAvailable)
                        {
                            buyingFromLeft = true;
                        }
                        else if (state.rightResourceIndex < state.rightResourcesAvailable)
                        {
                            buyingFromLeft = false;
                        }
                    }
                    else if (state.pref.HasFlag(CommercePreferences.BuyFromRightNeighbor))
                    {
                        if (state.rightResourceIndex < state.rightResourcesAvailable)
                        {
                            buyingFromLeft = false;
                        }
                        else if (state.leftResourceIndex < state.leftResourcesAvailable)
                        {
                            buyingFromLeft = true;
                        }
                    }
                    else
                    {
                        // not handling this situation yet.
                        throw new NotImplementedException();
                    }

                    ResourceOwner ro;
                    int resourceIndex;

                    // search using the left neighbor's resources before the right one.
                    if (buyingFromLeft)
                    {
                        resourceIndex = state.leftResourceIndex;
                        res = state.leftResources[resourceIndex];
                        leftInc = 1;
                        ro = ResourceOwner.Left;
                    }
                    else
                    {
                        resourceIndex = state.rightResourceIndex;
                        res = state.rightResources[resourceIndex];
                        rightInc = 1;
                        ro = ResourceOwner.Right;
                    }

                    if (res == null)
                    {
                        // logic error
                        throw new NotImplementedException();
                    }

                    int resCost = 2;

                    if (res.IsManufacturedGood())
                    {
                        if (state.marketEffects.HasFlag(CommerceEffects.Marketplace))
                        {
                            resCost--;
                        }
                    }
                    else
                    {
                        if (buyingFromLeft && state.marketEffects.HasFlag(CommerceEffects.WestTradingPost))
                        {
                            resCost--;
                        }
                        else if (!buyingFromLeft && state.marketEffects.HasFlag(CommerceEffects.EastTradingPost))
                        {
                            resCost--;
                        }
                    }

                    resUsed = new ResourceUsed(ro, resCost);
                }

                state.currentResourceStack.Push(resUsed);

                for (int resIndex = 0; resIndex < res.resourceTypes.Length; resIndex++)
                {
                    if (state.lowestCostResourceStack.Count != 0 && !state.pref.HasFlag(CommercePreferences.LowestCost))
                        break;

                    char resType = res.resourceTypes[resIndex];

                    // incomplete set of resources to buy this structure so far.
                    int ind = remainingCost.IndexOf(resType);

                    if (ind != -1)
                    {
                        int nResourceCostsToRemove = res.IsDoubleResource() && ((remainingCost.Length - ind) > 1) && (remainingCost[ind] == remainingCost[ind + 1]) ? 2 : 1;

                        if (nResourceCostsToRemove == 2)
                        {
                            resIndex++;

                            // note that both resources provided by this
                            // double-resource card were used (for cost-calculating purposes).
                            // don't need to worry about this for my city as there's no cost to use them.
                            state.currentResourceStack.Peek().usedDoubleResource = true;
                        }

                        // Secret Warehouse.  Must be considered _after_ double-type resources.  Only applies to our city's resources
                        // and only if they are a single, double, or either/or.  No Forum/Caravansery.
                        if (state.secretWarehouse == SpecialTrait.Unused && myInc == 1 && res.resourceTypes.Length <= 2 && res != state.blackMarketResource)
                        {
                            if (((remainingCost.Length - ind) > nResourceCostsToRemove) && (remainingCost[ind] == remainingCost[ind + nResourceCostsToRemove]))
                            {
                                // turn a single into a double or a double into a triple
                                ++nResourceCostsToRemove;
                                state.secretWarehouse = SpecialTrait.Used;
                            }
                        }

                        state.myResourceIndex += myInc;
                        state.leftResourceIndex += leftInc;
                        state.rightResourceIndex += rightInc;

                        if (usedWildResource)
                            state.wildResource = SpecialTrait.Used;

                        if (usedBilkis)
                            state.bilkis = SpecialTrait.Used;

                        if (res == state.blackMarketResource)
                            state.nBlackMarketIndex++;

                        ReduceRecursively(state, ref lowCost, remainingCost.Remove(ind, nResourceCostsToRemove));

                        state.myResourceIndex -= myInc;
                        state.leftResourceIndex -= leftInc;
                        state.rightResourceIndex -= rightInc;

                        if (usedWildResource)
                            state.wildResource = SpecialTrait.Unused;

                        if (usedBilkis)
                            state.bilkis = SpecialTrait.Unused;

                        if (state.secretWarehouse == SpecialTrait.Used)
                            state.secretWarehouse = SpecialTrait.Unused;

                        if (res == state.blackMarketResource)
                            state.nBlackMarketIndex--;
                    }
                }

                // pop the last ResourceEffect off, then move on to the next resource choice for this structure
                state.currentResourceStack.Pop();

                // increment the resource counter (only one of these is ever set to 1, the other two will be 0.
                state.myResourceIndex += myInc;
                state.leftResourceIndex += leftInc;
                state.rightResourceIndex += rightInc;

                if (usedWildResource)
                    state.wildResource = SpecialTrait.Used;

                if (usedBilkis)
                    state.bilkis = SpecialTrait.Used;

                if (res == state.blackMarketResource)
                    state.nBlackMarketIndex++;
            }
        }
        /// <summary>
        /// The entry point to the reduction algorithm
        /// </summary>
        /// <param name="cost">The cost in coins and resources of the structure</param>
        /// <param name="leftResources">Resources available for my city to purchase (Browns/Greys only)</param>
        /// <param name="rightResources">Resources available for my city to purchase (Browns/Greys only)</param>
        /// <param name="pref">Flags indicating how the search should be performed (Buy from Left or Right), find LowestCost, etc.</param>
        /// <returns></returns>
        public CommerceOptions CanAfford(Cost cost, List<ResourceEffect> leftResources, List<ResourceEffect> rightResources,
            CommercePreferences pref = CommercePreferences.LowestCost | CommercePreferences.BuyFromLeftNeighbor)
        {
            CommerceOptions commOptions = new CommerceOptions();
            ReduceState rs = new ReduceState();

            rs.myResources = resources;
            rs.leftResources = leftResources;
            rs.rightResources = rightResources;
            rs.leftResourcesAvailable = leftResources.Count();
            rs.rightResourcesAvailable = rightResources.Count();
            rs.currentResourceStack = new Stack<ResourceUsed>();
            rs.marketEffects = this.marketEffects;
            rs.pref = pref;
            rs.lowestCostResourceStack = new List<ResourceUsed>();
            ResourceCost lowCost = new ResourceCost();

            rs.wildResource = pref.HasFlag(CommercePreferences.OneResourceDiscount) ? SpecialTrait.Unused : SpecialTrait.Unavailable;
            rs.bilkis = marketEffects.HasFlag(CommerceEffects.Bilkis) ? SpecialTrait.Unused : SpecialTrait.Unavailable;

            if (rs.wildResource == SpecialTrait.Unused || rs.bilkis == SpecialTrait.Unused)
                rs.wildResourceEffect = new ResourceEffect(false, "WSBOCGP");

            rs.secretWarehouse = marketEffects.HasFlag(CommerceEffects.SecretWarehouse) ? SpecialTrait.Unused : SpecialTrait.Unavailable;
            rs.nBlackMarketIndex = 0;
            rs.nBlackMarketAvailable = 0;

            if (marketEffects.HasFlag(CommerceEffects.BlackMarket1))
                ++rs.nBlackMarketAvailable;

            if (marketEffects.HasFlag(CommerceEffects.BlackMarket2))
                ++rs.nBlackMarketAvailable;

            if (rs.nBlackMarketAvailable > 0)
            {
                string strBlackMarket = "WSBOCGP";

                foreach (ResourceEffect re in resources)
                {
                    // The Black Market only excludes resources produced by this
                    // city's brown or grey structures, which only have 1 or 2 resource types
                    // So this excludes the Caravansery, Forum, and any Wonder stages.
                    if (re.resourceTypes.Length <= 2)
                    {
                        foreach (char c in re.resourceTypes)
                        {
                            int index = strBlackMarket.IndexOf(c);

                            if (index >= 0)
                                strBlackMarket = strBlackMarket.Remove(index, 1);
                        }
                    }
                }

                rs.blackMarketResource = new ResourceEffect(false, strBlackMarket);
            }

            if (cost.resources != string.Empty)
            {
                // kick off a recursive reduction of the resource cost.  Paths that completely eliminate the cost
                // are returned in the requiredResourcesLists.
                ReduceRecursively(rs, ref lowCost, cost.resources);

                commOptions.bAreResourceRequirementsMet = rs.lowestCostResourceStack.Count != 0;
            }
            else
            {
                commOptions.bAreResourceRequirementsMet = true;
            }

            if (commOptions.bAreResourceRequirementsMet)
            {
                commOptions.bankCoins = lowCost.bank + cost.coin;
                commOptions.leftCoins = lowCost.left;
                commOptions.rightCoins = lowCost.right;
            }

            return commOptions;
        }
Beispiel #33
0
 public void AddResourceCost(ResourceCost cost)
 {
     resourceCosts.Add(cost);
 }