|
Post by sparrowhawk on Jul 28, 2004 7:51:56 GMT
Anyone had a chance to review this yet? Any thoughts or suggestions are welcome.
|
|
merlin
Public Area Guest
Posts: 19
|
Post by merlin on Jul 28, 2004 8:03:33 GMT
I've had a quick look, I'll try and take another look today. My first impressions were that it may actually be overcomplicated and that the first change should probably be simplification.
|
|
|
Post by sparrowhawk on Jul 28, 2004 8:08:10 GMT
Yep I agree. It's grown and grown and grown to the point where I was reluctant to take anything out in case the whole thing unravelled!
|
|
merlin
Public Area Guest
Posts: 19
|
Post by merlin on Jul 28, 2004 9:59:02 GMT
Just for reference here is the KILL code from LOM.
Basically for a lord chances=strength and success = energy+128 for a stronghold chances = soldiers/5 and success = (calculated but not important here )
What I like about this is that each chance is against a new army and has as much chance as failing. So we have small micro battles rather than ONE big calculation. I can imagine watching five soldiers sluggin it out!
To put this in context for LOM...
All Lords at a location fight the enemy first, just the lord not his army.
(BTW: A garrison is just placed as an army record, the enemy are all army records, the lords soldiers warriors and riders are also added as army records )
Then all the friend army records fight Then all the foe army records fight.
So to me, the modification to this system would be... all lords, their armie and garrisons become army records... sort these by courage+offence bonus and then pump these through the fight function.
Chances and Success can then be modified by any bonuses you require.
u32 battle::Fight ( u32 chances, u32 success, item::CArmy* foes[], u32& nFoes ) { int army; int killed;
killed=0;
while ( chances-- && nFoes ) {
if ( random(0,255) < success ) {
// pick a random army to fight from the // foe table army = random(0,nFoes-1); if ( random(0,255) > foes[army]->success ) { int amount = MIN(5,foes[army]->total);
foes[army]->total-=amount; killed+=amount;
// if this army has been wiped out // then remove it from the army table if ( foes[army]->total <= 0) { foes[army]->total=0; foes[army]=foes[nFoes-1]; nFoes--; }
}
} }
return killed; }
|
|
|
Post by celebaglar on Jul 28, 2004 21:24:36 GMT
Ta for the updated version.
One thing I noticed - which is more a design issue than a coding one - is the application of the bonus when fighting inside the citadels or keeps.
What happens - and this is a conclusion me and Mads reached previously when testing - is that citadels and keeps offer no defensive bonus at all, but they do cause the "invader" to take more casualties than normal[Note #1].
Now call me an old-fashioned stick-in-the-mud, but I always thought the main benefit of a walled stonghold is protection. Shouldn't the main bonus go towards reducing the allied casualties while only slightly increasing the invader's casualties?
Note that what I am querying here is the design, in case there is some deliberate reason why the bonus is implemented this way.
[1] Actually, this bonus is only applied in the original attack - subsequent rounds of fighting have no bonus, but that is a coding issue.
|
|
Ringthane
Public Area Guest
Ardet nec Consumitur
Posts: 5,446
|
Post by Ringthane on Jul 28, 2004 21:29:42 GMT
People may be expected to be skewered, cut down, trampled, peppered with projectiles, melted under a rain of burning oil, thrown from ladders, killed and generally mistreated when attacking...
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 29, 2004 4:42:13 GMT
Exactly, it should be more causalties for attacker and less for defender. Until the wall is breached, when the situation should be reversed. But I'm at a loss as how to determine that. Perhaps when the defending army gets reduced by half?
|
|
|
Post by sparrowhawk on Jul 29, 2004 8:25:38 GMT
I was thinking along the same lines myself as I simplified the script: I'd like the bonus to be defensive - the way to do it I think is to check whether the enemy Lord is at a friendly stronghold rather than when attacking lord is at a firendly stronghold (remember that enemy in this case could mean you, as it is looping through all lords - or will be when I fix it!) Would that work? I've just realised that the new script has a major bug - the enemy don't get to fight you! He, he. I need to change the script to loop through all non-aligned lords, not just vassals (as is does correctly in the previous version). Easy to address. Bill - why is the garrison bonus only happening once - could you point me to the error? I can't see the wood for the trees, so to speak. Too many hours staring at that script
|
|
|
Post by celebaglar on Jul 29, 2004 17:26:20 GMT
Bill - why is the garrison bonus only happening once - could you point me to the error? I can't see the wood for the trees, so to speak. Too many hours staring at that script Not sure yet. I'm a bit handicapped by not knowing PHP, and it isn't the most readable language I've ever seen (but better than perl *grin*) Is there an "intiative bonus" that takes into account the "attacking" army - as opposed to the "attack" turn each side gets within the battle?
|
|
Natmus
Morkin Admin
Fight the power!
Posts: 4,518
|
Post by Natmus on Jul 29, 2004 18:23:18 GMT
Is there an "intiative bonus" that takes into account the "attacking" army - as opposed to the "attack" turn each side gets within the battle? I don't think so. The actual battle calculation is this one: function kills($min, $max, $courage, $strength, $men, $bonus, $enemies){ //Calculates losses inflicted on enemy warriors or riders //Thanks to Gaz for the new & improved version 2.0! return round(rand($min,$max) * ($courage + 2) * (sqrt($strength + 0.1)) * $men * $bonus / 10000 / $enemies The $bonus is only derived from racial bonuses and being with allied garrisons. ($bonus is initialised as 1): //Calculate attack bonus $attackBonus += raceBonus($attackingLord->getRace()); if($attackingLord->getAllegianceID() == $garrison->getAllegianceID()) $attackBonus += strongholdBonus($garrison->getGarrison()); $mountedBonus = mountedBonus($attackingLord->isMounted());
|
|
Natmus
Morkin Admin
Fight the power!
Posts: 4,518
|
Post by Natmus on Jul 29, 2004 18:40:52 GMT
I think I see why battles with mixed armies tend to inflict significantly more losses.
In the attack cycle, for example, both the rider attack and the warrior attack routines check for the number of enemy lords "$enemyLords", and adjusts the number of casualties downwards proportionally.
However, both attack routines are divided up in seperate attacks against enemy riders and warriors, but no modifier is used here, so both types actually recieves a full attack from the attacking force. This is pretty much as our tests showed.
A solution (and making it a bit more complicated, but it's doable) is to calculate the proportion of each army segment (for example 1000R/1500W would be a .40/.60 proportion) and modify the losses in each routine with these numbers as well as "$enemyLords". Does that make any sense?
To elaborate, in the 1000R/1500W example, the army's riders would only suffer 40 percent of the casualties they take with the presen system, and the warriors only 60 percent of present losses.
Jean-Yves, we can take a test game along the lines of Bill's and mine, if you want to see the effect for yourself.
|
|
SkulkrinBait
Morkin Admin
Haxx0rs == Suxx0rs! v4
Posts: 6,680
|
Post by SkulkrinBait on Jul 29, 2004 19:44:42 GMT
If I may humbly butt in here.
I (as you know) am working on a motor racing game and the calculation for the laptimes is pretty complex. I found it useful to mess around with the formulae in Excel, trying it many times to give me a spread of sample results. I just tinkered with the formula in Excel until I liked the outcome.
Maybe that might help with this?
|
|
Natmus
Morkin Admin
Fight the power!
Posts: 4,518
|
Post by Natmus on Jul 29, 2004 22:15:03 GMT
Anyone had a chance to review this yet? Any thoughts or suggestions are welcome. I thought that making the modifiers for proportionate losses in mixed armies seemed simple enough, so I had a go at it. New or modified lines are marked with a "*" to the far left, so it's easy to find. //Loop through enemies here ---------------------------------------------------------------- while($dbRow2 = mysql_fetch_array($result2)){ $enemyLord = new CurrentLord($dbRow2["GML_ID"]); //create enemy lord object $enemyRiders = $enemyLord->getRiders(); $enemyWarriors = $enemyLord->getWarriors(); * $enemyTotal = $enemyRiders + $enemyWarriors ; * $ratioRiders = $enemyRiders / $enemyTotal ; * $ratioWarriors = $enemyWarriors / $enemyTotal ;
//Set some defaults $attackBonus = 1; $outcome = "C"; // C = Continue battle, neither lord killed
//Calculate attack bonus $attackBonus += raceBonus($attackingLord->getRace()); if($attackingLord->getAllegianceID() == $garrison->getAllegianceID()) $attackBonus += strongholdBonus($garrison->getGarrison()); $mountedBonus = mountedBonus($attackingLord->isMounted());
//Damage done by attacking lord him/herself ++++++++++++++++++++++++++++++++++++++++++++++++ $attackingLordRiderKills = 0; $attackingLordWarriorKills = 0;
$kills = round(rand($riderMin, $riderMax) * (($attackingLord->getCourage() + 2)/2) * (sqrt($attackingLord->getStrength() + 0.1)/100) * ($attackBonus + $mountedBonus));
if($kills > $enemyLord->getRiders()) $kills = $enemyLord->getRiders(); $attackingLordRiderKills += $kills; $enemyLord->adjustRiders($kills * -1);
$kills = round(rand($warriorMin, $warriorMax) * (($attackingLord->getCourage() + 2)/2) * (sqrt($attackingLord->getStrength() + 0.1)/100) * ($attackBonus + $mountedBonus)); if($kills > $enemyLord->getWarriors()) $kills = $enemyLord->getWarriors(); $attackingLordWarriorKills += $kills; $enemyLord->adjustWarriors($kills * -1);
//Damage done by attacking lord's army +++++++++++++++++++++++++++++++++++++++++++++++++++++ if($attackingLord->getRiders() > 0){ $riderKillsR = kills($riderMin, $riderMax, $attackingLord->getCourage(), $attackingLord->getRiderStrength(), $attackingLord->getRidersAtStartOfBattle(), $attackBonus, $enemyLords); * if($ratioRiders * $riderKillsR > $enemyLord->getRiders()) $riderKillsR = $enemyLord->getRiders();
$riderKillsW = kills($warriorMin, $warriorMax, $attackingLord->getCourage(), $attackingLord->getRiderStrength(), $attackingLord->getRidersAtStartOfBattle(), $attackBonus, $enemyLords); * if($ratioWarriors * $riderKillsW > $enemyLord->getWarriors()) $riderKillsW = $enemyLord->getWarriors();
* $enemyLord->adjustRiders($ratioRiders * $riderKillsR * -1); * $enemyLord->adjustWarriors($ratioWarriors * $riderKillsW * -1); } //End rider attack
if($attackingLord->getWarriors() > 0){
$warriorKillsR = kills($riderMin - 5, $riderMax - 5, $attackingLord->getCourage(), $attackingLord->getWarriorStrength(), $attackingLord->getWarriorsAtStartOfBattle(), $attackBonus, $enemyLords); * if($ratioRiders * $warriorKillsR > $enemyLord->getRiders()) $warriorKillsR = $enemyLord->getRiders(); $warriorKillsW = kills($warriorMin - 5, $warriorMax - 5, $attackingLord->getCourage(), $attackingLord->getWarriorStrength(), $attackingLord->getWarriorsAtStartOfBattle(), $attackBonus, $enemyLords); * if($ratioWarriors * $warriorKillsW > $enemyLord->getWarriors()) $warriorKillsW = $enemyLord->getWarriors();
* $enemyLord->adjustWarriors($ratioWarriors * $warriorKillsW * -1); * $enemyLord->adjustRiders($ratioRiders * $warriorKillsR * -1);
} //End warrior attack
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 30, 2004 5:31:53 GMT
There should be a check to avoid dividing by 0 army total, when a lord commands no army.
And ratio should be taken into account before the check is made if all enemy riders or warriors were killed.
|
|
Matija
Morkin Member
The Turtle Moves!
Posts: 1,696
|
Post by Matija on Jul 30, 2004 6:35:16 GMT
In fact, I would do it like this: Let be ar = attacking riders, aw = attacking warriors arb = attacking warrior bonuses, awb = attacking warrior bonuses the same, but with d substituted for a goes for the defending army, and drk = defence riders killed, drw = defence warriors killed Now ar*arb + aw*awb = as // attack strength dr*drb + dw*dwb = ds // defence strength c = kills(as, ds) // causalties if c = 0 then no causalties else if c >= dr + dw then // that should also be the case when ds = 0 drk = dr drw = dw else if c * dr*drb / ds >= dr then drk = dr dwk = c - dr else if c * dw*dwb / ds >= dw then dwk = dw drk = c - dw else drk = round(c * dr*drb / ds) dwk = c - drk Now drk and dwk have to be distributed by ar*arb and aw*awb ratio among attacking riders and warriors, to get their respective kills. Notes: All the random factors should already be picked when determining bonuses. The way the algorithm is written, the defence bonuses must be inverted, that is, the lesser the bonus means the less causalties, or, if more convenient, soldier numbers should be divided instead of multiplied with the bonus. Or, again, the proportions switched.
|
|