0
\$\begingroup\$

If I created different XML files for each Nations' Stockpiles and made an XMLmanager to do updates such as resource consumption and trade, wouldn't that be too much resource intensive? I mean, if I had to access each Nations' stockpiles every tick and update them (Quantity, Price, Quality).

Is there any other faster way to manage all those updates?

From the back and forth in the comments, I've came up with this approach.

public class Nation
{
    public string NationName;
    public int Population;

    public void NationCreator(string name, int pop)
    {
        NationName = name;
        Population = pop;
    }

    public class Stockpile
    {
        public int food;
        public int water;
        public int wood;

        //Then methods to work with that stockpile
    }
}

However, after some thinking and reading, my next approach to this problem will be Arrays but I only know how to make an array of one particular type like:

double[] balance = { 2340.0, 4523.69, 3421.0};

How could I do an array like this (Lua style array) in C# language?:

raw_material = {
    cotton = { 
        Value = 17.50
    }
}
\$\endgroup\$
  • \$\begingroup\$ From your latest edit, it looks like you've understood the syntax. So what remaining problem are you trying to solve with this question? \$\endgroup\$ – DMGregory Dec 28 '17 at 21:56
  • \$\begingroup\$ I am not still satisfied with the result that compiles but does not do what i had in mind. I though about nesting a Stockpile class inside Nation class so when ever i instanciate a Nation, the stockpile gets "loaded" inside that Nation obj. \$\endgroup\$ – WhiteGlove Dec 28 '17 at 22:01
  • 1
    \$\begingroup\$ You can do that with a field initializer or a constructor. It sounds like you might want to work through a few more basic C# tutorials to get practice with core language features like this. \$\endgroup\$ – DMGregory Dec 28 '17 at 22:06
  • 3
    \$\begingroup\$ Please don't assume that your question is a back and forth work with a single user, it must be read as a whole at all time so that someone who has never read it can understand it easily. In it's current form, it's hard to understand what you're actually needing: there are 2 questions. \$\endgroup\$ – Vaillancourt Dec 29 '17 at 1:46
  • 2
    \$\begingroup\$ This question seems stem from an assumption that your non-implemented system is too slow. I would suggest you try to create a system, then ask for help if it is too slow / something goes wrong. You also seem inexperienced with the language you're using so I would suggest watching a few tutorials and getting a good grip of the basic features in C# before going further. \$\endgroup\$ – Charanor Dec 29 '17 at 2:00
1
\$\begingroup\$

I'd be inclined to do something a little like this:

First we define somewhere our collection of resource types (assuming this is a controlled list that will only be expanding occasionally during development. If you want dynamic resource types that can be expanded by mods / DLC, the Type Object Pattern can serve that need. But for most cases we can keep it simpler.)

public enum ResourceType {
    Food,
    Water,
    Wood
    // Add resources here as needed.
}

Next our stockpile can be implemented as a key-value store that maps resource IDs to the quantity of resource held. (If you need, instead of an int, the content of this structure can be a struct ResourceRecord including not just quantities but storage capacity, production rates, expiration date, quality, etc...)

Dictionary<ResourceType, int> _stockpile = new Dictionary<ResourceType, int>();    

public int GetResourceStock(ResourceType kind) {
    int held = 0;
    _stockpile.TryGetValue(kind, out held);
    return held;
}

public void AddResource(ResourceType kind, int quantity) {
    // For safety & debugging, you may want to Assert here that quantity > 0.
    int held = GetResourceStock(kind);
    _stockpile[kind] = held + quantity;
}

public bool TryWithdrawResource(ResourceType kind, int quantity) {
    int held = GetResourceStock(kind);
    if(held < quantity)
        return false; // I lack enough funds to spend.

    _stockpile[kind] = held - quantity;
    return true;      // Transaction completed successfully.
}

Here I've shown this as a dictionary, for maximum flexibility. This might be overkill for your needs though - if your list of resources is small & fixed, an array indexed by the enum-as-integer would work fine - I show that style in another answer. Or if any given stockpile can contain only a few (dozens of) resource types, a List<ResourceEntry> would be comparably fast to search.

What's nice about this is that now you can define resource production & costs in data. If our food and water resources are particular named variables, then we need different lines of code to check & modify each one. But by abstracting this out, the same code can act on any single resource or collection of resources with only data changes. For example, we can model costs & purchase checks for any number of resources like this:

public struct CostEntry {
    public ResourceType resource;
    public int quantity;
}

public bool CanAfford(CostEntry[] costs) {
    foreach(var cost in costs) {
        if(GetResourceStock(cost.resource) < cost.quantity)
            return false;
    }
    return true;
}

public bool TryPurchase(CostEntry[] costs) {
    // If we can't afford it, stop right away.
    if(CanAfford(costs) == false)
        return false;

    // Now that we know we can afford it, spend all the required resources.
    foreach(var cost in costs) {
        TryWithdrawResource(cost.resource, costquantity);
    }
    return true;  // Done.
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the guidance i will study hard you code and understand it. Then, i will try to apply to my concept. Also thanks for the extra help and references. \$\endgroup\$ – WhiteGlove Dec 29 '17 at 11:07
  • \$\begingroup\$ I also though about creating an Object Resource and then store it inside an Array (your dictionary maybe?) \$\endgroup\$ – WhiteGlove Dec 29 '17 at 11:08
  • \$\begingroup\$ Why use an object rather than a struct for a case like this? You probably don't want anything outside of the stockpile owner holding a reference to it. \$\endgroup\$ – DMGregory Dec 29 '17 at 17:50
  • \$\begingroup\$ I solved it the way i wanted, each nation with a stockpile, money and population. Now i will work out trade between nations (AI). Thanks for all the help \$\endgroup\$ – WhiteGlove Dec 29 '17 at 18:13
  • 1
    \$\begingroup\$ Yes, dictionaries are both more complex & more resource-intensive than a simple array. To look up an item from an array, you offset a pointer by the index. To look up an item from a dictionary, you hash the key, then transform that to a pointer offset, then probe or chase a linked list until you find the entry with the matching key. Each entry then needs to store both the value & the key, and the dict as a whole needs to keep some empty space for efficiency. Dictionaries handle dynamic sizing too, compared to a fixed-sized array. Dictionaries aren't bad by any means, just heftier than arrays. \$\endgroup\$ – DMGregory Jul 3 '18 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.