New Battle Calculator for TripleA! or rather, the current one is fixed

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
I just fixed a bug / missing feature in the Battle Calculator that has been annoying me for about a year.

Essentially, the battle calculator returns results that are wrong, sometimes very wrong, because it doesn't know how to take casualties properly.

Take for example this situation:
you have 10 infantry and 15 little_artillery
infantry are 1att / 2def, can be supported
little_artillery are 1att / 2def, gives support

and lets say you are attacking someone, and they get 10 hits.

the current battle calculator will take 10 infantry casualty.  or it will take 10 little_artillery casualty (i can't remember which).
if you actually go and fight this battle, you will be asked by triplea to take those 10 inf casualty.  AIs always take default casualties too, so this is problem for them too.

Obviously, this is the wrong casualty selection.

the correct casualty selection would be to:
FIRST take 5 little_artillery casualty
THEN interleave the artillery with the infantry, so that you take 2 more little_artillery and 3 infantry casualty (or 2 inf and 3 art)

so the correct casualties are:
7 little_artillery, 3 infantry

which will leave you with: 8 little_artillery, 7 infantry


now, this gets more complex when you consider this example:
you have:
10 conscripts (1 attack, 2 defense)
20 infantry ( 1 attack, 2 defense, can be supported)
25 little_artillery (1 attack, 1 defense, supports)
30 elites (2 attack, 2 defense, can be support)
20 artillery (2 attack, 2 defense, support)



at any rate, I fixed this issue.  It took all day, and a good amount of debugging, but it works.

Here are the results:

These are 2 pictures of the old and the new.  
In the old, the battle calc says you have 100% chance of Losing.  
In the new one, the battle calc shows the correct results, which is that you have a 100% chance of Winning!

OLD TRIPLEA (1.2.5.5):




NEW TRIPLEA (1.2.6.0), with my code for battle calcing:





An example of the game presenting to you default casualties, with the new code:


thanks,
Veqryn
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
Squid,

I would like to expand this to account for your Support Attachments.
Right now, it only accounts for Artillery and Supportable, and those two will go out of style in future maps.

How to do it?

While it is possible that people could and will have units that give a bonus of 2 or more (ie: jumping an infantry from 1 to 3), far more likely is a bonus of 1.  So i would like to just pretend that all bonuses are a bonus of 1 to make things relatively simple.  Things will get really complex if you have to decide to lose a 2 attack unit in order to save a 1 attack unit that gives +2 to some other unit.

Here is the code for the interleaver.
I'm sure this code is probably too long, and that you could do the same thing in half the lines or less... but i just don't know enough java or programming in general to think of how that is accomplished.
    public static Collection<Unit> sortUnitsForCasualtiesWithSupport(Collection<Unit> targets, boolean defending, PlayerID player, IntegerMap<UnitType> costs, GameData data)
    {
    List<Unit> sortedUnitsList = new ArrayList<Unit>(targets);
    Collections.sort(sortedUnitsList, new UnitBattleComparator(defending, player, costs, data));
    List<Unit> perfectlySortedUnitsList = new ArrayList<Unit>();

        int artillerySupportAvailable = DiceRoll.getArtillerySupportAvailable(sortedUnitsList, defending, player);
        int supportableAvailable = DiceRoll.getSupportableAvailable(sortedUnitsList, defending, player);
        if (artillerySupportAvailable == 0 || supportableAvailable == 0)
        return sortedUnitsList;
       
        // reset, as we don't want to count units which support themselves
        artillerySupportAvailable = 0;
        supportableAvailable = 0;
        List<List<Unit>> unitsByPowerAll = new ArrayList<List<Unit>>();
        List<List<Unit>> unitsByPowerBoth = new ArrayList<List<Unit>>();
        List<List<Unit>> unitsByPowerGives = new ArrayList<List<Unit>>();
        List<List<Unit>> unitsByPowerReceives = new ArrayList<List<Unit>>();
        List<List<Unit>> unitsByPowerNone = new ArrayList<List<Unit>>();
        // in order to merge lists, we need to separate sortedUnitsList into multiple lists by power
        for (int i = 0; i <= Constants.MAX_DICE; i++)
        {
        List<Unit> powerAll = new ArrayList<Unit>();
        List<Unit> powerBoth = new ArrayList<Unit>();
        List<Unit> powerGives = new ArrayList<Unit>();
        List<Unit> powerReceives = new ArrayList<Unit>();
        List<Unit> powerNone = new ArrayList<Unit>();
            Iterator<Unit> sortedIter = sortedUnitsList.iterator();
            while (sortedIter.hasNext())
            {
            Unit current = (Unit) sortedIter.next();
            if (getUnitPowerForSorting(current, defending, player, data) == i)
            {
            // TODO: if a unit supports itself, it should be in a different power list, as it will always support itself.  getUnitPowerForSorting() should test for this and return a higher number.
            powerAll.add(current);
            if (UnitAttachment.get(current.getType()).isArtillery() && UnitAttachment.get(current.getType()).isArtillerySupportable())
            powerBoth.add(current);
            else if (UnitAttachment.get(current.getType()).isArtillery())
            powerGives.add(current);
            else if (UnitAttachment.get(current.getType()).isArtillerySupportable())
            powerReceives.add(current);
            else
            powerNone.add(current);
            }
            }
            unitsByPowerAll.add(powerAll);
            unitsByPowerBoth.add(powerBoth);
            unitsByPowerGives.add(powerGives);
            unitsByPowerReceives.add(powerReceives);
            unitsByPowerNone.add(powerNone);
            artillerySupportAvailable += DiceRoll.getArtillerySupportAvailable(powerGives, defending, player);
            supportableAvailable += DiceRoll.getSupportableAvailable(powerReceives, defending, player);
        }
        // now merge the lists
        List<Unit> tempList1 = new ArrayList<Unit>();
        List<Unit> tempList2 = new ArrayList<Unit>();
        for (int i = 0; i <= Constants.MAX_DICE; i++)
        {
            int iArtillery = DiceRoll.getArtillerySupportAvailable(unitsByPowerGives.get(i), defending, player);
            int aboveArtillery = artillerySupportAvailable - iArtillery;
            artillerySupportAvailable -= iArtillery;
            int iSupportable = DiceRoll.getSupportableAvailable(unitsByPowerReceives.get(i), defending, player);
            int aboveSupportable = supportableAvailable - iSupportable;
            supportableAvailable -= iSupportable;
            if ((iArtillery == 0 && iSupportable == 0) || (iArtillery == 0 && aboveSupportable >= aboveArtillery)
            || ((iSupportable == 0 || iArtillery == 0) && aboveSupportable == aboveArtillery)
            || (iSupportable == 0 && aboveSupportable <= aboveArtillery))
            perfectlySortedUnitsList.addAll(unitsByPowerAll.get(i));
            else
            {
            int count = 0;
            while (0 < unitsByPowerBoth.get(i).size() || 0 < unitsByPowerGives.get(i).size()
                || 0 < unitsByPowerReceives.get(i).size() || 0 < unitsByPowerNone.get(i).size())
                {
                tempList1.clear();
                tempList2.clear();
                // four variables: we have artillery, we have support, above has artillery, above has support.  need every combination covered.
                if (iArtillery == 0 && aboveArtillery - aboveSupportable > 0 && unitsByPowerReceives.get(i).size() > 0)
                {
                while (aboveArtillery - aboveSupportable > 0 && unitsByPowerReceives.get(i).size() > 0)
                {
                int last = unitsByPowerReceives.get(i).size()-1;
                tempList2.add(unitsByPowerReceives.get(i).get(last));
                aboveSupportable += DiceRoll.getSupportableAvailable(unitsByPowerReceives.get(i).get(last), defending, player);
                unitsByPowerReceives.get(i).remove(last);
                }
                tempList1.addAll(unitsByPowerNone.get(i));
                tempList1.addAll(unitsByPowerGives.get(i));
                tempList1.addAll(unitsByPowerReceives.get(i));
                tempList1.addAll(unitsByPowerBoth.get(i));
                unitsByPowerNone.get(i).clear();
                unitsByPowerGives.get(i).clear();
                unitsByPowerReceives.get(i).clear();
                unitsByPowerBoth.get(i).clear();
                Collections.sort(tempList1, new UnitBattleComparator(defending, player, costs, data));
                Collections.sort(tempList2, new UnitBattleComparator(defending, player, costs, data));
                perfectlySortedUnitsList.addAll(tempList1);
                perfectlySortedUnitsList.addAll(tempList2);
                continue;
                }
                if (iSupportable == 0 && aboveSupportable - aboveArtillery > 0 && unitsByPowerGives.get(i).size() > 0)
                {
                while (aboveSupportable - aboveArtillery > 0 && unitsByPowerGives.get(i).size() > 0)
                {
                int last = unitsByPowerGives.get(i).size()-1;
                tempList2.add(unitsByPowerGives.get(i).get(last));
                aboveArtillery += DiceRoll.getArtillerySupportAvailable(unitsByPowerGives.get(i).get(last), defending, player);
                unitsByPowerGives.get(i).remove(last);
                }
                tempList1.addAll(unitsByPowerNone.get(i));
                tempList1.addAll(unitsByPowerGives.get(i));
                tempList1.addAll(unitsByPowerReceives.get(i));
                tempList1.addAll(unitsByPowerBoth.get(i));
                unitsByPowerNone.get(i).clear();
                unitsByPowerGives.get(i).clear();
                unitsByPowerReceives.get(i).clear();
                unitsByPowerBoth.get(i).clear();
                Collections.sort(tempList1, new UnitBattleComparator(defending, player, costs, data));
                Collections.sort(tempList2, new UnitBattleComparator(defending, player, costs, data));
                perfectlySortedUnitsList.addAll(tempList1);
                perfectlySortedUnitsList.addAll(tempList2);
                continue;
                }
                if (iSupportable + aboveSupportable > iArtillery + aboveArtillery && unitsByPowerReceives.get(i).size() > 0)
                {
                while (iSupportable + aboveSupportable > iArtillery + aboveArtillery && unitsByPowerReceives.get(i).size() > 0)
                {
                int first = 0;
                tempList1.add(unitsByPowerReceives.get(i).get(first));
                iSupportable -= DiceRoll.getSupportableAvailable(unitsByPowerReceives.get(i).get(first), defending, player);
                unitsByPowerReceives.get(i).remove(first);
                }
                tempList1.addAll(unitsByPowerNone.get(i));
                tempList1.addAll(unitsByPowerBoth.get(i));
                unitsByPowerNone.get(i).clear();
                unitsByPowerBoth.get(i).clear();
                Collections.sort(tempList1, new UnitBattleComparator(defending, player, costs, data));
                perfectlySortedUnitsList.addAll(tempList1);
                continue;
                }
                if (iSupportable + aboveSupportable < iArtillery + aboveArtillery)
                {
                while (iSupportable + aboveSupportable < iArtillery + aboveArtillery && unitsByPowerGives.get(i).size() > 0)
                {
                int first = 0;
                tempList1.add(unitsByPowerGives.get(i).get(first));
                iArtillery -= DiceRoll.getArtillerySupportAvailable(unitsByPowerGives.get(i).get(first), defending, player);
                unitsByPowerGives.get(i).remove(first);
                }
                tempList1.addAll(unitsByPowerNone.get(i));
                tempList1.addAll(unitsByPowerBoth.get(i));
                unitsByPowerNone.get(i).clear();
                unitsByPowerBoth.get(i).clear();
                Collections.sort(tempList1, new UnitBattleComparator(defending, player, costs, data));
                perfectlySortedUnitsList.addAll(tempList1);
                continue;
                }
                if (iSupportable + aboveSupportable == iArtillery + aboveArtillery)
                {
                tempList1.addAll(unitsByPowerNone.get(i));
                tempList1.addAll(unitsByPowerBoth.get(i));
                unitsByPowerNone.get(i).clear();
                unitsByPowerBoth.get(i).clear();
                if (!unitsByPowerGives.get(i).isEmpty())
                tempList2.add(unitsByPowerGives.get(i).get(0));
                if (!unitsByPowerReceives.get(i).isEmpty())
                tempList2.add(unitsByPowerReceives.get(i).get(0));
                Collections.sort(tempList2, new UnitBattleComparator(defending, player, costs, data));
                Unit u = tempList2.get(0);
                tempList1.add(u);
                UnitAttachment ua = UnitAttachment.get(u.getType());
                if (ua.isArtillery())
                {
                unitsByPowerGives.get(i).remove(0);
                iArtillery--;
                }
                else
                {
                unitsByPowerReceives.get(i).remove(0);
                iSupportable--;
                }
                Collections.sort(tempList1, new UnitBattleComparator(defending, player, costs, data));
                perfectlySortedUnitsList.addAll(tempList1);
                continue;
                }
                // and we should never get down here
                throw new IllegalStateException("Possibility not accounted for in sortUnitsForCasualtiesWithSupport.");
                }
            }
        }
        if (perfectlySortedUnitsList.isEmpty() || !perfectlySortedUnitsList.containsAll(sortedUnitsList)
        || !sortedUnitsList.containsAll(perfectlySortedUnitsList) || perfectlySortedUnitsList.size() != sortedUnitsList.size())
        throw new IllegalStateException("Possibility not accounted for in sortUnitsForCasualtiesWithSupport.");
       
        return perfectlySortedUnitsList;
    }

Also, how can I get battle information from battlecalc?  I need to know if a battle is amphibious or not....
from my new method: getUnitPowerForSorting()
                    /* TODO: figure out how to find if we are in a battle, and if that battle is amphibious
                if (ua.getIsMarine() && battle.isAmphibious())
                    {
                        Collection<Unit> landUnits = battle.getAmphibiousLandAttackers();
                        if(landUnits.contains(current))
                            ++tempStrength;
                    } */


thanks squid,
veqryn
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

squid_daddy
holy crap thats a lot of work.

about using the new support. It is not extremely good atm, I had meant to think of a better way to present it before weaving it into this and the AI functions.
but anyway you should be able to figure something out.

you need to use two static functions in DiceRoll.java

public static void getSupport(List<Unit> units, Set<List<UnitSupportAttachment>> support, IntegerMap<UnitSupportAttachment> supportLeft, GameData data, boolean defending) {
you call this once for the list of units on a side.
you pass in empty collections for data, support and supportLeft, these are modified.

supportLeft is a map of attachment->int, used as a counter of how many times the rules are used
eg
{artyold, 3}
{tacbomb, 1}

support is a set of lists of support rules, each list contains all rules for a bonustype
eg
{littleart, bigart},{tacbomb}

public static int getSupport (UnitType type, Set<List<UnitSupportAttachment>> support, IntegerMap<UnitSupportAttachment> supportLeft) {

returns the strength to add to a unit, you pass in the collections returned from the method above.
it figures out which support rules to use and decrements the counters


to match how dicerolling works you may want to apply this on your units sorted by strength.
you can use the static method
public static void sortByStrength (List<Unit> units, final boolean defending){

hope you can figure that out.
about the battle you can get the battle tracker.

DelegateFinder.battleDelegate(m_data).getBattleTracker();
then use it to find pending battles in your territory.
public Battle getPendingBattle(Territory t, boolean bombing)
    {
or
public Collection<Territory> getPendingBattleSites(boolean bombing)
    {
otherwise you could just have options in the ui for these kind of battle conditions.

edit: I realise the above is not actually all that helpful for you. it is just all that exists currently.
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Wisconsin
In reply to this post by Veqryn
Awesome, thanks Veqryn.

I did a performance test and the battle calc speed before and after: 6692 - 7144

I made a few changes and got it down around 7067, battleCalcPatch.patch
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
In reply to this post by squid_daddy
@ wisc,
thanks, i can see easily what you did, and ya its a little better

@ squid,
this could get really really complicated.

i mean, lets say you have 100 different units, some of them have no support at all, some of them give support to themselves, some of them give support to other units, some of them receive support, some of them receive support from some units and give support to other units, some of the support stacks with other support while some of the support does not stack.

i think it will take a ph.d in math to figure out a decent algorithm for finding the perfect casualties to take for any combination of the above, and for any number of casualties to take.


so, how do you propose we simplify this whole situation?

here is what I am thinking:

pretend that ALL supports are the same bonusType, (ie: no support stacks)
pretend that ALL support is bonus = 1 (ie: only gives 1 attack or 1 defense)
pretend that ALL support is to strength (ie: does not affect rolls, just strength)
pretend that ALL units that can receive support can receive all support given

that last one is key i think, because it eliminates the work we would have to do to determine who supports who.

so it would look like this:

go through all your units,
figure out who gives support and the number of support given.  add them up
figure out who receives support.  add them up

then just plug them into my algorithm just as if they were artillery, etc.


SO... if we go with that, I will need a couple new methods,

1. a way to figure out IF a unit supports themselves.  since this one is easy, I want to eliminate it from the consideration.  And since this one is easy, we can do exactly what the support says and modify the dice/strength by bonus, and throw it to the list as if those were its actual unit stats.

2. a way to figure out if a unit gives support.  basically, if I want to read if a unit has artillery, I do "ua.isArtillery".  what can i do for support?  "ua.supports.isAttachedTo" ?

3. a way to figure out if a unit can receive support.  

what do you think?
thanks,
veqryn
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
In reply to this post by Wisconsin
I changed this line, and i want to make sure my logic is correct.
it should speed it up, because you won't have to do all those calculations or create all those variables/lists if you don't have units with a power greater than 3.  It also should save from a java error, when you have heavy bombers with 2 dice.



        //Find what the biggest unit we have is. If they are bigger than max_dice, set to max_dice+1.
        int maxPower = Math.max(0, Math.min(getUnitPowerForSorting(sortedUnitsList.get(sortedUnitsList.size()-1), defending, player, data), 1 + Constants.MAX_DICE));
        //Fill the lists with the six dice numbers (plus Zero, and plus 1 above the max_dice in order to put units that have multiple rolls), or unit powers, which we will populate with the units
        for (int i = 0; i <= maxPower; i++)
        {
            unitsByPowerAll.add(new ArrayList<Unit>());
            unitsByPowerBoth.add(new ArrayList<Unit>());
            unitsByPowerGives.add(new ArrayList<Unit>());
            unitsByPowerReceives.add(new ArrayList<Unit>());
            unitsByPowerNone.add(new ArrayList<Unit>());
        }

        //in order to merge lists, we need to separate sortedUnitsList into multiple lists by power
        Iterator<Unit> sortedIter = sortedUnitsList.iterator();
        while (sortedIter.hasNext())
        {
            Unit current = (Unit) sortedIter.next();
            int unitPower = getUnitPowerForSorting(current, defending, player, data);
            unitPower = Math.max(0, Math.min(unitPower, 1 + Constants.MAX_DICE)); // getUnitPowerForSorting will return numbers over max_dice IF that units Power * DiceRolls goes over max_dice
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Wisconsin
Looks fine to me, and a quick run through the debugger shows it's getting the right numbers. (3 for GLW)

I just thought of something that could really speed up the calc'ing for the new AI... At the moment, each casualty selection call for each battle simulation for each battle calc calls the casualty sorting method, which, as far as I know, sorts all the possible units. If we could somehow have the AI only sort the possible casualties ONCE per battle calc, we could save literally hundreds of thousands of casualty sorting calls per round! (One GetBattleResults call that ran 2500 times resulted in over 5000 casualty sorting calls, and the new AI uses battle calc'ing many dozens of times per round)
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
wisc, in getDefaultCasualties(), just change:
List<Unit> sorted = new ArrayList<Unit>(sortUnitsForCasualtiesWithSupport(targets, defending, player, costs, data));
to:
List<Unit> sorted = new ArrayList<Unit>(targets);

then see how long it takes to run 20,000 calculations of something in low luck.
then compare with 20,000 calculations by default mode.
and then divide by 20,000
then multiply by the number of calculations you usually do (and add the time for two sortUnitsForCasualtiesWithSupport() call, since you have to do it twice at the beginning, once for each side)
and you have the amount of time saved.
not sure if its worth the effort, but i'll let you decide
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Wisconsin
Yes, it worked. I just finished a sorted-casualty caching patch: DynamixPatch25.patch (Also contains all Dynamix updates)

With this patch, it reduces the Odds calculating time from over 7000 to around 5500. (When the boolean option s_enableCasualtySortingCaching is turned on, which is currently only turned on while the DOddsCalculator class is running)

-Wisconsin
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
why should this be enabled only with dynamix ai?
I'll change to be enabled all the time, as this will save battle calcing time for humans too.
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

squid_daddy
In reply to this post by Veqryn
in unitSupportAttachment
public static Set<UnitSupportAttachment> get(UnitType u) {
will give you all supports attached to this unittype i.e. this unit type gives support.

public static Set<UnitSupportAttachment> get(GameData data)
    {
will give all USA's for all unittypes

you need to remember though that these things depend on other variables.
importantly defending, and players that the support is active for.
also potentially more complications may be allowed in the future perhaps.

so look. I would recommend that you retrieve all of your data from a single source
such as the static methods in diceroll.

I suggest you try to define precisely the information or data structure you require and we devise a method to add somewhere centrally. the current AI's will need to do something similar.
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Wisconsin
In reply to this post by Veqryn
This is enabled for humans in the 26 patch. (See other thread)
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
perhaps you don't have it enabled in the right place?
ie: humans start a battle calc in a different way than the way you assumed.
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
psi
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

psi
In reply to this post by Veqryn
Veqryn wrote
@ wisc,
thanks, i can see easily what you did, and ya its a little better

@ squid,
this could get really really complicated.

i mean, lets say you have 100 different units, some of them have no support at all, some of them give support to themselves, some of them give support to other units, some of them receive support, some of them receive support from some units and give support to other units, some of the support stacks with other support while some of the support does not stack.

i think it will take a ph.d in math to figure out a decent algorithm for finding the perfect casualties to take for any combination of the above, and for any number of casualties to take.
How about this algorithm  Losing a unit can mean losing some of the defense/offense value of the unit, losing some of the defense/offense value of any units it is non-superfluously supporting -- so you just sum these two and simply choose the unit that has the least impact (this algorithm would work even if units gave negative support ....).


edit2:

For the second value, calculate the support that each unit type would receive (including surpluses) and then see what if any unit types that are supported do not have a surplus (if support is stacked, see if any part of the stack does not have a surplus) and just count those support values as part of the second value -- sum them all up and then sum that with the first value.

And you can just loop through to get the whole thing sorted once at the beginning of combat.
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

grizzly
Sorry if this is off topic, but could a maintain destroyer option be added to the battle calculator?

It would help the ai too if they kept a single destroyer so that subs dont sink all the battleships and carriers casualty free
Just my 2 cents...
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
sometimes keeping a destroyer is bad,
like when the enemy has a lot of subs and you don't want them to keep taking casualties on subs and want to do casualties to their more expensive surface vessels

then there is also when you want to interleave carriers or other things,

and when you want to keep 2 hit units alive even when they have lower power than other units

and when you want to keep bombers alive on defense,

etc etc
this could get complicated....
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

FireZealot
Just so I am clear though, this bug did not affect NWO or any of Siegs games, right?
To the meaningless French idealisms: Liberty, Equality and Fraternity, we oppose the three German realities: Infantry, Cavalry, and Artillery - Prince Bernhard von B├╝low
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
this bug affects all games
(if you can really call it a bug)


you can only see it in games where a unit giving support and a unit receiving support have the same attack power

examples:
if artillery has 2 attack, and infantry has 1 attack, the battle calc will correctly take all infantry casualty first, then take the artillery casualty


if artillery has 1 attack, and infantry has 2 attack, the battle calc will correctly take all artillery casualty first, then take the infantry casualty


if artillery has attack EQUAL to the infantries attack value, then the battle calc will INCORRECTLY take all of one of them casualty first, then take all of the other.


So,... i don't know my NWO units that well, so I don't know if the bug is present or not in NWO's battle calcing

are there any units that give support, and any units that receive support, and they have the same power?
if so, then yes this bug is in NWO's battle calc

Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Veqryn
Administrator
In reply to this post by psi
psi, your method, as far as i can tell, will not interleave the units
interleaving the units is the point of this thread
Please contribute to the TripleA 2013 donation drive:
http://tripleadev.1671093.n2.nabble.com/2013-TripleA-Donation-Drive-tp7583455.html
Reply | Threaded
Open this post in threaded view
|

Re: New Battle Calculator for TripleA! or rather, the current one is fixed

Wisconsin
Not sure about carriers/planes and the other stuff, but I think his method would work for infantry/artillery interleaving. (Well, depends on how you code it. I think it would work if you start from the left of the list, and as you go, grab the unit to the right that lessens our total defense or attack score the least)
12