Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

User A can have many entities

A Entity is a object that has properties such as health, attack, defence, agility, stamina, etcetera.

When User A want to attack User B with x entities I am looking for the algorithm/equation to calculate the fight. I have brought some couple of ideas but they all have some pros and cons and I am not sure which one I would use or If I should use one of them at all?

Model A - The while loop Basically I would get all the entities that is suppose to fight in this battle, I would assign each of them (objects) in to an array (the User A array and the User B array). Now I would simply loop through until one of the array is empty. Inside the loop I would let one of the User attack first, calculate the result (If the Entity has 0 health, remove it) and then let the next User attack back, calculate the result (If the Entity has 0 health, remove it) And then continue.

The Pros with Model A would be that every entity would be battling and instead of just do a calculation on all around there would be a justice fight.

The Cons To loop through like 10 entities would be fine but what about 1000-2000 entities? And how about the different strength of each entity I mean how could I decide which entity should battle against what entity? This could be just an sorted array (weakest > to strongest) But then I couldn't have like different types of entities is better against a different type of entity, meaning like a Gunner wouldn't mean anything If it met a Swordsman even though a Gunner would most likely win such in a real fight.

Model B The idea of Model B is quite simple basically calculate all the attributes (properties) together and then If User A army has greater stats than User B army, User A army would win the fight. The Pros with this is it easy on the performance. The Cons are "Which entities would survive?" And it would basically be, the one with greatest army would win. You wouldn't even have a "chance" to win.

Model B B Then I started to think what If I take the concept of Model B calculate the stat and then I have a battle between just those two single entities. This way User B actually would have a chance ( a small one but the possibility to win) even though the User A has greater army (better stats). The Cons are yet again, How would I know which entities that would survive on the winning team?

The answer I am looking for to this question is what Model should I use? And how would I solve the cons in that particular Model. Or should I use some completely different model (idea) ? (If possible please provide some php pseudo code)

share|improve this question

3 Answers 3

up vote 5 down vote accepted

I've recently used both models A and B in two different games. Neptune's Pride and Jupiter Folly.

In both games, when two armies meet, they fight until one army remains.

In Neptune's Pride, players take turns inflicting damage on one another until one of the armies is dead. In Jupiter's Folly, the strength of the armies is simply compared and some die rolls are added to the result, the stronger army wins. The winner suffers damage equal to the loser strength.

For your games you must ask yourself, how well the player will be able to guess the outcome of the battle. Will they be able to calculate their odds in their head before the battle? Will they be able to understand the math that is going on under the hood.

Instead of thinking about the problem in terms of how you code it, you should think about what the player will see and think.

Model B will be much easier for the player to understand.

share|improve this answer

If a user is sending just 5 soldiers than of course there's no point in dividing in even smaller groups, let alone using different simulation models. But you also considered a case where there are 2000 entities in play.

If you want something even barely realistic, 2000 soldiers won't be attacking as a single mass of people (or stats). They would be divided in groups, possibly with different game stats.

Instead of just doing 500 VS 200 (where the 500 would win) or 500+rnd VS 200+rnd (where the 200 could have a slight probability of winning, depending on the rnd factor) you could define groups of (pick a number) 25 units and compare groupA1 VS groupB1 etc. And, to improve the randomness, making it groupA1+rnd VS groupB1+rnd.

Defining a formula to find out if a soldier is taken out of combat shouldn't be that hard at that point.

I.E: Let's say there's a 25 vs 20 situation. The 25 should have better probability of winning (and surviving). Random1 = random[0,5] and Random2 = [0,5]

So if it's Value1+Random1 VS Value2+Random2, the result could be 25 VS 25. Then you could say that taken_out1 = (group2/group1)+X taken_out2 = (group1/group2)+X

Where X is another random value (probably related to the other variables)

Of course all the numbers are just made up in a couple of minutes, but they should provide a decent enough example.

That way each group has a probability of winning, and a 2000 soldiers army would have 80 groups (that is, a maximum of 80 check to do).

That would make the battle both less predictable and less heavy to simulate, and also give you a way to modify your simulation later (adding specific unit types, or terrain variables, etc).

share|improve this answer

Here is a basic version of a battle model that combines some features of A and B with WWII troop organization, while at the same time avoiding a problem you mentioned, namely that "a Gunner wouldn't mean anything if it met a Swordsman even though a Gunner would most likely win in a real fight."

Define the interface of battle entities in ITroop. Implement ITroop with GunnerTroop, SwordmenTroop, etc., with different behaviors for finding targets, applying damage, reacting to battle events, etc.

Now implement the Composite design pattern in order to branch together several leaf like entities to form Troops of different sizes. Define Group (up to 10 single entities), Platoon (up to 4 Groups), Company (up to four Platoons), Battalion (up to 5 Companies), and Regiment (up to 8 Battalions). In each of these classes, define a couple of additional constants and methods:

const damageMultiplier
const damageFullRanks
isFull()

as well as any new behavior that troops of that type and troop size have:

reactToOnBeingTargeted()
reactToBeginSecondBattleRound()

The battle then follows these steps:

  • Before the fight starts, the entities of both armies are grouped by entity types. 10 entities of the same type and army are put into Groups (of the given entity type), until no more Groups can be filled that way. Groups of the same type are grouped together to form Companies, Companies of the same type to form Battalions, etc. For example, if you have 180 gunners, this process would result in one Company with 1 full Platoon and another half-full Platoon. Register the Company in the player's Army data structure as the biggest Troop of gunners available to that player. Also register any event handlers that Groups, Platoons, and Companies of gunners might have.
  • Cycle through the combat rounds and tell different entity types to act.
  • When it's player A's gunner's turn to shoot, look for the biggest Troop of gunners available to player A. Let's say that it is the Company described above. The Company now looks for a target in the other player's army; let's say that it looks for cavalry troops. Again, the biggest troop of that type is returned as the target.
  • Having found a suitable target, the Company determines how much damage it does. This is a two-step process:
    • Company calls its own isFull() method to see if the ranks of the Company are fully filled. If this is the case, return the constant damageFullRanks. This is a precalculated number that prevents large troops from causing a myriad of requests down the composite tree.
    • If Company is not fully filled, cycle through its members and ask for their damage. In this case, the first request goes to the full Platoon of gunners, which returns its damageFullRanks constant. The second request goes to the half-full Platoon, which in turns asks its members for their damage values. When all damage values are collected, Company applies the constant damageMultiplier to the sum of the damage of all its members.
  • Apply the damage at the target. If the troop size of the target drops because of the attack, register the new and smaller sized Troop object as the new biggest troop of that kind for that player.

This model has a couple of advantages:

  • Each unit fights. If there are other units of this type, it types within a Troop, but if not, it fights alone.
  • You don't need to handle the battle behavior of 2,000 individual objects. You might HAVE that many objects, but the number of attacks to be calculated is much lower, because the composite pattern groups many entities into bigger units.
  • damageMultipliers should be > 1, thus providing an incentive to build bigger armies. This represents the advantage that bigger armies have over smaller ones without aggregating all the units into a single number which is then compared to a single number of the opponent. The damageMultipliers > 1 should, of course, be thematically motivated somehow, for example by saying that a Company of Swordmen carries a banner that boosts morale, and that a Battalion has a commander who makes them more efficient.
  • Having different ITroop implementations for different unit types allows for game mechanics that require careful army composition (instead of just adding more junk to the pile in order to make the numbers bigger). For example, information about an enemy's army composition could be exploited by 'countering' his composition.
  • Another way to add a size bonus AND strategic depth to army composition is to define custom event listeners for different troop types and sizes. For example, each Company of gunners might have a canon that can do something fancy against another entity type once per battle to counter that entity type, or Groups of fairies might fight alongside Groups of Paladines, proving some kind of protection in case of certain onBeingAttacked events.
  • Having an OO design approach generally adds flexibility for whatever you might want to add to your game later on.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.
{"cc_re__cc_re__cc_by_sa_3_0": ["                  <li><a href=\"//area51.stackexchange.com\" title=\"proposing new sites in the Stack Exchange network\">Area 51</a></li>\r\n                        <li><a href=\"//careers.stackoverflow.com\">Stack Overflow Careers</a></li>\r\n                    \r\n                </ol>\r\n            </td>\r\n    </tr>\r\n</table>\r\n                </div>\r\n            </div>\r\n\r\n            <div id=\"copyright\">\r\n                site design / logo &#169; 2015 stack exchange inc; user contributions licensed under <a href=\"http://creativecommons.org/licenses/by-sa/3.0/\" rel=\"license\">cc by-sa 3.0</a> \r\n                with <a href=\"http://blog.stackoverflow.com/2009/06/attribution-required/\" rel=\"license\">attribution required</a>\r\n            </div>\r\n            <div id=\"svnrev\">\r\n                rev 2015.7.1.2693\r\n            </div>\r\n            \r\n        </div>\r\n    </div>\r\n    <noscript>\r\n        <div id=\"noscript-warning\">Game Development Stack Exchange works best with JavaScript enabled<img src=\"http://pixel.quantserve.com/pixel/p-c1rF4kxgLUzNc.gif\" alt=\"\" class=\"dno\"><"], "copyright__copyright__copyright": ["nter that entity type, or Groups of fairies might fight alongside Groups of Paladines, proving some kind of protection in case of certain onBeingAttacked events.\n  \u2022 Having an OO design approach generally adds flexibility for whatever you might want to add to your game later on.\nshare|improve this answer\n\nYour Answer\n\n\u00a0\ndiscard\n\nBy posting your answer, you agree to the privacy policy and terms of service.\n\nNot the answer you're looking for? Browse other questions tagged or ask your own question."]}