Custom Battle Phases
-
While I've been refactoring the battle engine code, I've been thinking of ways to simplify the logic in the engine as well as make the game xml's more obvious in what is happening.
Right now, the battle has roughly 4 different phases:
- AA/Targeted attacks
- Bombardment
- First Strike/Sneak Attack
- All other units
Each of those phases are basically the same thing: pick firing units, pick targeted units, fire, select casualties, mark casualties.
So, my thinking is to add a new XML section that defines the phases in a battle. You would specify which phase is happening, which units participate in the phase, and whether the hit targets can fire back later.
Here's an example of what I'm thinking (I'm using the custom firing groups that I've proposed in https://forums.triplea-game.org/topic/2348/custom-firing-groups-for-units) :
<battlePhases> <battlePhase name="AA" returnFire="false"> <firingGroup value="aaGuns" /> </battlePhase> <battlePhase name="Bombardment" rounds="1"> <firingGroup value="bombardmentUnits" side="offense" /> </battlePhase> <battlePhase name="General" default="true" /> </battlePhases>
This tells the engine that there are three phases to a battle in the game.
The first phase is called "AA" and the firing units are from the "aaGuns" firing group (which would be defined elsewhere in the XML). The units that are killed in this phase do not return fire.
The second phase is called "Bombardment" and the firing units are from the "bombardmentUnits" firing group but only if they are offensive units. This phase only happens one round as well. And the units that are killed can return fire.
The third phase is the default phase. Any unit that hasn't fired yet will get a chance to fire here.The one thing that I'm still trying to figure out is how to express all of the different variations of the battle phases that exist already. Things like subs firing in a different phase dependent on the existence of destroyers or indicating when the subs should submerge/retreat.
Thoughts?
-
Battle phases are driven by the presence of units with certain attributes. To get other interesting battle phases, like 'land-to-land' bombardment or 'sea-to-sea' bombardment, we'd need to have units with corresponding attributes. I don't know if it's therefore valuable to be able to specify the phases explicitly. For example, would we want every XML to specify that there must be a 'general' battle phase? For backward compatibility we would have to pre-fill in these values at the least.
Is there value in being able to re-alias the battle phase names? I think that is a question for map makers.
Ultimately my inclination is we focus on improving the core Battle logic and UI first before expanding it. I've noticed recently for example when "defenders roll", the "select attacker casualties" step is highlighted incorrectly and that does not advance correctly. There has been a lot of talk as well about changing the UI layout, for example putting dice rolls into columns underneath the respective unit power. We also have had ideas to be able to select previous battle phases to "go back" and view previously rolled results.
Bottom line from my perspective, I've no opposition to these updates, I'd look at the ROI compared to other initiatives. Perhaps there are maps out there that would highly benefit from altered battle phase names (others would have to weigh in there).
-
Thinking about this more, I'm sure there is more utility here than I initially give credit. Being able to re-order phases could be useful. I think I'm interested in hearing more about how this could be used and the benefits.
-
Changing the battle phase name is a very minor thing.
We have maps that require subs to fire before every one else but still allow casualties to fire back, we have maps that require subs to fire before every one else but don't allow casualties to fire back, and maps that require subs to fire with all of the other units. This logic is scattered between various attributes and properties. Having it in one location makes it easier to see exactly how the phases are supposed to work.
We also have logic that is scattered between various parts of the phases and can probably be encapsulated in some sort of strategy object. This would allow defining that strategy object at a higher level that allows more customization.
There have also been requests for the ability to do bombers to do a single round of attack (https://forums.triplea-game.org/topic/2463/bombers-single-round-attack), requests to be able to fire back at the bombarding units (I can't find the link for this one). This would allow the map maker to handle that scenario.
And instead of using various unit attributes to define which phases they go into, the map would have it explicit through the firing groups and the battle phases. So, instead of knowing that a
isFirstStrike
unit always fires during the first strike phase, the map would have a "first strike" firing group (or maybe a custom name for the map), and then a battle phase that fires before the default phase and that kills the targets instead of allowing them to fire back. -
Some more phases that come to mind:
- evasion (subs submerge)
- attacker retreat (probably always last phase)
whenHitPointsDamagedChangesInto
evaluation- potentially air battle phases preceding combat
@LaFayette Without understanding much of the code I'd guess that the ROI is fairly good, considering that this will probably weed out many tangled special cases and reduce maintenance in the long term.
-
Given some recent progress on this front, we need to be sure about two things:
- Be very clear about the value of this and why we should do it
- Be clear which maps would benefit, how many places would we actually use this?
- Carefully design how we will express this in XML
For example, re (3), we should consider whether it makes sense to define the battle phase a unit fires in as part of the unit type. That would avoid the problem where a unit type is omitted from any battle phase.
-
I actually like this idea when I thought about it in light of a build tool like Maven or Gradle. One could define rather arbitrary named phases and then "bind" units or behaviors to those phases. I think this is what @Trevan is getting at but I would propose the phases themselves have no special meanings or naming conventions. However, just like Maven, TripleA would have a series of "built in"/stock phases that units could bind to for standard behavior.
Phase attributes:
- Dice sides
- Max rounds
- Casualties fire back or not
Unit attributes:
- Which phases they participate in as attacker, defender, or target (able to be killed but not return fire)
For example, instead of saying a sub is sneak attack, you bind it to "phase 1", which is a no-fire-back phase with a max round of 1.
This would also allow interesting things like:
- AA guns fire 1
- Strategic bomb phase 1 with max dice sides 6 and max round of 1
- AA guns fire 2
- Strategic bomb phase 2 with max dice sides 8 and max round of 1
- AA guns fire 3
- Strategic bomb phase 3 with max dice sides 10 and max round of 1
(basically, being able to continue bombing with less likelihood of damage and more chances of AA to fire)
-
@LaFayette said in Custom Battle Phases:
Be clear which maps would benefit, how many places would we actually use this?
I, personally, think that all maps would benefit. Right now, to figure out which units fire when and how they fire is complicated. The information is spread out across lots of different properties and some aren't that obvious. Take for instance your request to group all of the dice when subs don't have first strike. Several of the responders were talking about isDestroyer implications and WW2V2 implications. But if, instead, the maps just specified how and when the units fire, then there isn't confusion about the affect of isDestroyer, WW2V2, isInfrastructure, AA, etc.
For example, here's how the WW2V2 could possible look:
<battlePhase name="First Strike"> <returnFire side="both"> <exists type="destroyer" /> </returnFire> <firingSquadron name="submarine" side="both"> <units type="submarine" /> <targets type="transport:submarine:destroyer:carrier:battleship" /> </firingSquadron> </battlePhase> <battlePhase name="General"> <firingSquadron name="air" side="both"> <units type="fighter:bomber" /> <targets type="infantry:artillery:armour:fighter:bomber:transport:destroyer:carrier:battleship" /> <targets type="submarine" exists="destroyer"/> </firingSquadron> <firingSquadron name="land" side="both"> <units type="infantry:artillery:armour" /> <targets type="infantry:artillery:armour:fighter:bomber" /> </firingSquadron> <firingSquadron name="sea" side="both"> <units type="destroyer:carrier:battleship" /> <targets type="fighter:bomber:transport:submarine:destroyer:carrier:battleship" /> </firingSquadron> </battlePhase>
That is really easy to see that submarines always fire together at the beginning and that destroyers only affect the return fire.
But for a non WW2V2, the xml could look like:
<battlePhase name="First Strike" returnFire="false"> <firingSquadron name="submarine sneak attack" notexists="destroyer" side="both"> <units type="submarine" /> <targets type="transport:submarine:destroyer:cruiser:carrier:battleship" /> </firingSquadron> </battlePhase> <battlePhase name="General"> <firingSquadron name="submarine" exists="destroyer" side="both"> <units type="submarine" /> <targets type="transport:submarine:destroyer:cruiser:carrier:battleship" /> </firingSquadron> <firingSquadron name="air" side="both"> <units type="fighter:tactical_bomber:bomber" /> <targets type="infantry:artillery:mech_infantry:armour:fighter:tactical_bomber:bomber:transport:destroyer:cruiser:carrier:battleship" /> <targets type="submarine" exists="destroyer"/> </firingSquadron> <firingSquadron name="land" side="both"> <units type="infantry:artillery:mech_infantry:armour" /> <targets type="infantry:artillery:mech_infantry:armour:fighter:tactical_bomber:bomber" /> </firingSquadron> <firingSquadron name="sea" side="both"> <units type="destroyer:cruiser:carrier:battleship" /> <targets type="fighter:tactical_bomber:bomber:transport:submarine:destroyer:cruiser:carrier:battleship" /> </firingSquadron> </battlePhase>
And now you can see that the destroyer is affecting when the submarines fire. And you could then change your request to ask that all of the units in the same BattlePhase fire roll together if they have the same targets.
-
An initial reaction is I wonder if this is too verbose? Are we going to have the same 30 lines per XML? We do still need to support all existing XMLs (we do not control all maps, we cannot break existing maps). So while we make existing maps more explicit, we are not necessarily changing anything. What's the benefit?
I've personally have been wanting to consolidate rules to a module so that it could be turned on and off per game. Would this structure lend itself easily to that?
For example, a map could in short say "WWv2" rules which then brings in 30 additional options that have default options. In turn, when a game starts we expose each of these default values for per-game configuration in the UI. I would also like to see unit stats and it's a natural add-on to extend that to unit abilities as well.
Does that change the calculus here at all? Do I understand right that the primary benefit is to make the rules more explicit and easier to determine by looking at the XML?
-
@LaFayette said in Custom Battle Phases:
An initial reaction is I wonder if this is too verbose?
That XML was a rough draft. I'm sure it can be tightened up quite a bit.
Are we going to have the same 30 lines per XML?
No, because maps generally have lots of different units. So, the map will need its own specific XML. Though, I guess with variables and such, it could be simplified and maybe will become similar across different maps.
We do still need to support all existing XMLs (we do not control all maps, we cannot break existing maps). So while we make existing maps more explicit, we are not necessarily changing anything. What's the benefit?
There have been requests to be able to make more custom battle groups/phases/etc. I've linked to a few in this thread as well as the custom firing groups thread. So map makers are wanting it. Also, they are currently using the AA/Targeted Attack to replicate some of this logic (see Warcraft and the extensive AA logic there). So, map makers will be able to benefit from it.
For me, personally, it clears up confusion on the differences between map versions (v1, v2, v3, v4, v5, etc). Instead of trying to track down which properties do what or adding a new property to support an obscure rule, this xml will make it easier to see how they work and to handle the obscure cases (such as v2 where subs always fire together).
@LaFayette said in Custom Battle Phases:
I've personally have been wanting to consolidate rules to a module so that it could be turned on and off per game. Would this structure lend itself easily to that?
For example, a map could in short say "WWv2" rules which then brings in 30 additional options that have default options. In turn, when a game starts we expose each of these default values for per-game configuration in the UI. I would also like to see unit stats and it's a natural add-on to extend that to unit abilities as well.
Does that change the calculus here at all?Maybe? I don't know?
-
What about combat AA units?
-
@Schulz said in Custom Battle Phases:
What about combat AA units?
What about them? They would be specified in the phase in the AA phase.
-
A few thoughts & feedback regarding this block:
<firingSquadron name="submarine sneak attack" notexists="destroyer" side="both"> <units type="submarine" /> <targets type="transport:submarine:destroyer:cruiser:carrier:battleship" /> </firingSquadron>
Units bind into their combat phase via their abilities and not type
- I think a unit should 'bind into' a combat phase and not the other way around. It is the unit ability that defines when it rolls, not the unit type persay.
Unit 'anti' abilities to define counter-abilities
- In that same manner, instead of 'isDestroyer', perhaps we should call that 'antiFirstStrike'. It negates or neutralizes the first strike ability from another unit.
Another related question is whether we should simplify our implementation of the rules for whether first strike is merely neutralized or negated. If we go with negated, that could be cohesive with any other unit ability that also has a counter ability.
Unit targeting by unit type
- For targets I'd rather we avoid delimited lists. It's easier to parse and less error prone to use canonical XML, eg:
<targets> <target>transport</target> : : </targets>
At this level of specification I also think we probably should favor defining a unit attribute that is targetted rather than specific units. For non-WW2 maps we should consider this further and whether it is better to specify specific units in addition to units by type. To this extent I'm thinking to have something like:
<targets type=naval />
Dynamic calculation of squadrons
- Though, similar to other points, I think it should be the unit that defines what it can target. Let's say for example there were multiple first strike units. Perhaps an air-to-air first strike unit. The combat phase should probably define which types of units roll during that phase, then it is up to the game engine to compute the intersections of which units can target others and break them up accordingly. For example, the engine is processing a first strike phase, it see that we have subs and air-to-air that have mutually exclusive targets. It would then dynamically create two groups to roll against their respective targets.
-
@LaFayette See the https://forums.triplea-game.org/topic/2348/custom-firing-groups-for-units/ for probably a better version of the targeting definition. It is based on the already existing typeAA and targetsAA.
And for the "Dynamic calculation of squadrons", the problem with that is you need to display a name in the Battle UI when things fire. So, my proposal allows the map maker to actually specify the name of the group. Again, this is similar to the typeAA property but centralizes it so you don't have accidental mistakes where two units with the same typeAA have different targetsAA (the engine will just pick the first one it sees).
-
How would you handle the hypothetical scenario with two first strike units each with different targets?
Couldn't the name just be derived based on some attributes of the unit?
-
@LaFayette said in Custom Battle Phases:
Another related question is whether we should simplify our implementation of the rules for whether first strike is merely neutralized or negated. If we go with negated, that could be cohesive with any other unit ability that also has a counter ability.
It depends on the map. In WW2V2, I would say that first strike is neutralized if an
isDestroyer
is present because the first strike still happens but the casualties can still fire back. In non-WW2V2, first strike is negated if anisDetroyer
is present because the first strike never happens and theisFirstStrike
units fire with the rest of the units. -
@Trevan Perhaps there is confusion, I'm not seeking clarification of the rules. I'm proposing that we consider removing that distinction so that an 'anti-ability' always removes the opposing ability. This creates symmetry and cohesiveness with any other anti-ability and creates a concept of an anti-ability with a well understood definition of what it does.
-
To another extent, what I'm getting at is it seems that any unique combat ability would roll on its own. This perhaps could be as simple as defining the ordering of when combat abilities would roll. We then know which abilities those target by looking at an ability definition XML and which units have that ability by looking at the unit definition.
-
@LaFayette said in Custom Battle Phases:
How would you handle the hypothetical scenario with two first strike units each with different targets?
Couldn't the name just be derived based on some attributes of the unit?
I would handle it similar to how AA units with different targets are handled, but in a centralized manner. Currently, with AA, you do the following:
<attachment name="unitAttachment" attachTo="destroyer" javaClass="games.strategy.triplea.attachments.UnitAttachment" type="unitType"> <option name="typeAA" value="Depth Charge" /> <option name="targetsAA" value="submarine" /> ... </attachment> <attachment name="unitAttachment" attachTo="cruiser" javaClass="games.strategy.triplea.attachments.UnitAttachment" type="unitType"> <option name="typeAA" value="Sea to Air" /> <option name="targetsAA" value="fighter" /> ... </attachment>
But as I mentioned, that has the problem (which I've found maps that do have this problem) of mistypes where the same typeAA has different targetsAA.
So, to fix that problem, it would be in a central location, inside of the
battlePhases
orbattleGroups
orfiringGroups
(the name doesn't really matter). And it could look like:<firingGroup name="Depth Charge"> <firingUnits> <unit name="destroyer" /> </firingUnits> <targetUnits> <unit name="submarine" /> </targetUnits> </firingGroup> <firingGroup name="Sea to Air"> <firingUnits> <unit name="cruiser" /> </firingUnits> <targetUnits> <unit name="fighter" /> </targetUnits> </firingGroup>
-
Would you comment on defining targets as part of unit abilities vs in battle phases?
I think the former scales better and would be more cohesive. I also think it would be fundamentally simpler, where the battle phases is largely just defining an ordering. There is more to the battle phases than the target groups, which makes me think keeping it largely to ordering would keep it simpler.