triplea-game / triplea

TripleA is a turn based strategy game and board game engine, similar to Axis & Allies or Risk.
https://triplea-game.org/
GNU General Public License v3.0
1.32k stars 392 forks source link

ConcurrentBattleCalculator#calculate:200 - java.lang.IllegalStateException #12488

Closed tripleabuilderbot closed 4 months ago

tripleabuilderbot commented 5 months ago

Map

world_war_ii_global

Log Message

java.lang.IllegalStateException: Round 10,000 reached in a battle. Something must be wrong. Please report this to TripleA. Territory: 62 Sea Zone Attacker: Japanese Attacking unit types: carrier,battleship,fighter,transport,destroyer,cruiser, Defending unit types: carrier,battleship,submarine,fighter,destroyer,cruiser

TripleA Version

2.6.14470

Java Version

11.0.4

Operating System

Windows 10

Stack Trace

Exception: java.lang.IllegalStateException java.lang.IllegalStateException: Round 10,000 reached in a battle. Something must be wrong. Please report this to TripleA.
 Territory: 62 Sea Zone Attacker: Japanese Attacking unit types: carrier,battleship,fighter,transport,destroyer,cruiser, Defending unit types: carrier,battleship,submarine,fighter,destroyer,cruiser
java.lang.Exception
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinTask.reportException(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinTask.invoke(Unknown Source)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(Unknown Source)
    at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
    at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
    at games.strategy.triplea.odds.calculator.ConcurrentBattleCalculator.calculate(ConcurrentBattleCalculator.java:200)
    at games.strategy.triplea.odds.calculator.BattleCalculatorPanel.lambda$updateStats$13(BattleCalculatorPanel.java:1173)
    at java.base/java.lang.Thread.run(Unknown Source)

Exception: java.lang.IllegalStateException Round 10,000 reached in a battle. Something must be wrong. Please report this to TripleA.
 Territory: 62 Sea Zone Attacker: Japanese Attacking unit types: carrier,battleship,fighter,transport,destroyer,cruiser, Defending unit types: carrier,battleship,submarine,fighter,destroyer,cruiser
java.lang.Exception
    at games.strategy.triplea.delegate.battle.MustFightBattle$29.execute(MustFightBattle.java:1344)
    at games.strategy.triplea.delegate.ExecutionStack.execute(ExecutionStack.java:34)
    at games.strategy.triplea.delegate.battle.MustFightBattle.fight(MustFightBattle.java:714)
    at games.strategy.triplea.odds.calculator.BattleCalculator.calculate(BattleCalculator.java:115)
    at games.strategy.triplea.odds.calculator.ConcurrentBattleCalculator.lambda$calculate$4(ConcurrentBattleCalculator.java:188)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source)
    at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
    at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(Unknown Source)
    at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(Unknown Source)
    at java.base/java.util.stream.AbstractTask.compute(Unknown Source)
    at java.base/java.util.concurrent.CountedCompleter.exec(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
beelee1 commented 5 months ago

hmm .. havent seen this in 2.6 Maybe try the latest 2.6 It might be already fixed

fasthard commented 5 months ago

Thx for your answer, but isn't 2.6.14470 the latest 2.6 version?

beelee1 commented 5 months ago

@fasthard looks as if 14705 is latest. https://github.com/triplea-game/triplea/releases/

I've been using 14696 and haven't noticed it. It may have just not come up yet though. Looked like when same units went at it is when it nutted up. So that's possible it's not known about and still going on.

asvitkine commented 5 months ago

@fasthard do you remember what happened when you got this error? Do you happen to have an autosave from a phase right before this that reproduces the error after loading?

We've gotten a few reports of this type of error, but not a reliable way to reproduce, so any help would be appreciated!

fasthard commented 5 months ago

Hi, well I edited this file: rus006.zip to this file: BM4_O&EvsA+22US7.zip Thanks for you effort!

asvitkine commented 4 months ago

@fasthard

Those two saves have all players set to human and there are no pending combat moves. So it doesn't seem like there's enough to reproduce the issue there?

Can you clarify again how you got the error? Were you playing this game online with a bunch of humans - or did you play with AIs? You don't have any autosaves from right before the bug happened?

asvitkine commented 4 months ago

Although I guess I can reproduce this by just leaving edit mode on when ending a phase. Here's a repro:

autosaveBeforeEndTurn.tsvg.zip

I guess we can make it so ending a phase will turn off edit mode. Or we can make it so no combats happen in edit mode.

asvitkine commented 4 months ago

Looks like the error is not new to 2.6. I tried with 2.5 and hit this one: https://github.com/triplea-game/triplea/issues/12434

asvitkine commented 4 months ago

I looked through at the code history of when edit mode was made to ignore combat casualties and it was when it was originally added here: https://github.com/triplea-game/triplea/commit/ab56e9cc32ebf0eb8bb2d32c8204a45839e7d113

So I guess it always worked this way (i.e. no casualties are done when edit mode is active in combat). I'm actually not sure why that's the case. To me, edit mode is just about editing the state of the game. I feel like after you do that, there's no reason to also make combat dice rolls have no effect - why not let it happen as normal?

That would simplify the code a lot and let us get rid of bugs like these.

beelee1 commented 4 months ago

@asvitkine

yea, so the G 40 Expansion mod uses edit with no casualties being selected so it can produce the desired game result that triplea can't do otherwise.

For example, there are units that get a +1 on 1st rd of attack or defense and then revert to there normal combat modes. The only way I can make it work, is to play the battle in edit and pick the casualties manually. They still show as a hit or not according to there combat values but don't auto hit.

If you make it so they auto hit, it will require a mass amount of edit to use and since the dice roller isn't documented, which would be a slower process, one would have to use an outside dice roller for verification.

Please don't change this behavior or maybe I have misunderstood what was being discussed

Edit yes i have encountered errors while in edit mode several times, but simply alerting the player that they shouldn't be in edit and they won't get the error should be a sufficient solution.

Being able to select casualties manually, same as you would playing in person, offers a lot of flexibility. Obviously, it's not ideal, but if not available it will limit ways to play that have rules that triplea can't do.

Cernelius commented 4 months ago

So I guess it always worked this way (i.e. no casualties are done when edit mode is active in combat). I'm actually not sure why that's the case. To me, edit mode is just about editing the state of the game. I feel like after you do that, there's no reason to also make combat dice rolls have no effect - why not let it happen as normal?

I don't think so. I remember that in the past having Edit Mode selected just allowed you to take whatever casualties you wanted (comprising possibly none at all), then (many years ago) the behaviour changed to everyone being immortal with Edit Mode on.

I guess it was not an intended change, but I think I've never reported it.

It was many years ago when this happened, so I might be remembering wrong, but I'm almost sure of what I'm saying.

asvitkine commented 4 months ago

@beelee1

Interesting. Can you give more details about how selecting casualties manually works in edit mode? From what I can tell (before my change) is it would just default to no units taking damage, but the dialog to select which ones to take as casualties still pops up.

Do you mean that you still play through the combat, but after each roll of dice, you go back to the map and delete units (and that affects the running battle)? Or is there some way to do this from the combat UI?

Seems like a pretty cumbersome use case. Perhaps we can just support whatever rules "G 40 Expansion" required natively in the engine? Are there any maps where people need to do this?

beelee1 commented 4 months ago

@asvitkine yea so here's how I currently do it on 2.6 14705 Just a quick hack to show it. If there are 3 Submarines, they get A1 D1 for first rd of combat only. Then they get there normal combat values of A2 D1. Here are some shots

so we have 3 U-boats attacking. When there are 3 they get a +1 attack for first rd only. So i use edit to be able to pick the casualties as needed.

Screenshot from 2024-04-26 10-56-31

so no hits in this case as a 4 and two sixes are rolled.

Screenshot from 2024-04-26 10-59-09

this is what shows up in the battle window. The hits are currently zero but I can pick as many as I want.

Screenshot from 2024-04-26 11-00-45

That way, if there was a hit at 3 in the first rd I could select it.

Hmm I don't think I explained it very well. Basically you can choose to take a hit or not

beelee1 commented 4 months ago

@asvitkine yea it's not ideal play wise but only way to be rule compliant with this mod :) It's actually just part of game play at this point as were on game 4 using it.

I'm not entirely sure I'm understanding your change. I haven't tried it yet. On 14705

asvitkine commented 4 months ago

@beelee1

I see, so if you select things in the battle window, then the hits will actually be done? OK, thanks. My change probably breaks this, so I suppose it should be reverted.

But I can take a look to see if engine support (for new XML) for the above could be added, so edit mode wouldn't be required.

I'm also wondering, I guess the above (edit mode to workaround triplea limitation) only works if the number of dice rolled is the same in the custom rules? For example, if custom rules say "roll an extra die on first round" or something, then it wouldn't work right?

For example, I was looking at that ruleset's pdf: https://drive.google.com/file/d/1SRDOsOwlO4Aa13cULwkWrorrXEmCmiN-/view

And on page 8, it's talking about Tank Armies and Army Corps which sound like they might be changing the number of dice rolled, etc. Wouldn't that not be supported with how Edit mode combat works due to number of dice differences?

beelee1 commented 4 months ago

@asvitkine

yea i'm not sure about the extra die rolls. If they show up in edit or not. I'll test it.

Try not to use edit if at all possible, so basically there are two units, U-boats and Paratroopers that need to be rolled in edit.

Would be way cool if you could add that ability to triplea. Idk how much labor would be involved on your part though.

While not perfect, it currently works as is.

Also, there may be other games that would need to use edit if they wanted. For example, the 1 DD blocks all subs in the Global game.

But yea, it is cumbersome and mistakes are easier to make, but basically it plays like a tabletop game when using it

Cernelius commented 4 months ago

@asvitkine yea so here's how I currently do it on 2.6 14705 Just a quick hack to show it. If there are 3 Submarines, they get A1 D1 for first rd of combat only. Then they get there normal combat values of A2 D1. Here are some shots

so we have 3 U-boats attacking. When there are 3 they get a +1 attack for first rd only. So i use edit to be able to pick the casualties as needed.

You mean that they get an ADDITIONAL A1 D1 for the first round of combat only, meaning that they'll have Attack 3 or Defence 2 on the first round and Attack 2 or Defence 1 on whatever other rounds?

@asvitkine A way to do this (which I think would stand a high chance to be used by other games too) would be by allowing an additional option for the current support attachments, defining the number of combat rounds for which the support lasts. Then, the game could be updated by having the submarines giving support to themselves accordingly.

I mean something like this.

        <attachment name="supportAttachmentSumbarine" attachTo="submarine" javaClass="games.strategy.triplea.attachments.UnitSupportAttachment" type="unitType">
            <option name="unitType" value="submarine"/>
            <option name="faction" value="allied"/>
            <option name="side" value="offence:defence"/>
            <option name="dice" value="strength"/>
            <option name="bonus" value="1"/>
            <option name="number" value="1"/>
            <option name="bonusType" value="submarine"/>
            <option name="maxRounds" value="1"/>
            <option name="players" value="..."/>
        </attachment>

The option which would need to be added is <option name="maxRounds" value="1"/> .

Descriptively maxRounds values: Sets for how many rounds the support is given. Negative (-1) means infinite. (default = -1). .

I think that such an option may have good applications to several over cases. For example, I can see game-makers wanting to have artillery support lasting only for the first round of combat or somesuch (as that would make sense).


While at it, I also suggest adding an "∀" or (if "∀" is not a valid character) "a" (meaning "all") or maybe "+" value for the "players" option, so you don't have to input every player when you want everyone to have the support (like you do now, and sometimes game-makers forget some players, especially the null ("Neutral") pseudo-player).

beelee1 commented 4 months ago

@Cernelius yea it would be a nice feature that a lot of people would use. Hopefully asvitkine is up for it :)

Pretty close, except the Subs get a D+2 so would D3 1st rd and D1 after

Cernelius commented 4 months ago

Pretty close, except the Subs get a D+2 so would D3 1st rd and D1 after

In this case, under my proposal, two attachments would be needed.

        <attachment name="supportAttachmentSumbarineOffence" attachTo="submarine" javaClass="games.strategy.triplea.attachments.UnitSupportAttachment" type="unitType">
            <option name="unitType" value="submarine"/>
            <option name="faction" value="allied"/>
            <option name="side" value="offence"/>
            <option name="dice" value="strength"/>
            <option name="bonus" value="1"/>
            <option name="number" value="1"/>
            <option name="bonusType" value="submarine"/>
            <option name="maxRounds" value="1"/>
            <option name="players" value="..."/>
        </attachment>

        <attachment name="supportAttachmentSumbarineDefence" attachTo="submarine" javaClass="games.strategy.triplea.attachments.UnitSupportAttachment" type="unitType">
            <option name="unitType" value="submarine"/>
            <option name="faction" value="allied"/>
            <option name="side" value="defence"/>
            <option name="dice" value="strength"/>
            <option name="bonus" value="2"/>
            <option name="number" value="1"/>
            <option name="bonusType" value="submarine"/>
            <option name="maxRounds" value="1"/>
            <option name="players" value="..."/>
        </attachment>
Cernelius commented 4 months ago

@Cernelius yea it would be a nice feature that a lot of people would use. Hopefully asvitkine is up for it :)

Pretty close, except the Subs get a D+2 so would D3 1st rd and D1 after

So the rule is that submarines are offence/defence 3/3 on the first round of combat and offence/defence 2/1 thereafter?

beelee1 commented 4 months ago

So the rule is that submarines are offence/defence 3/3 on the first round of combat and offence/defence 2/1 thereafter?

yes

Yea you'd need one for offense and defense both. The supportAttachment

Would be a super cool feature. There would be a lot of uses for it :)

Cernelius commented 4 months ago

I've just read that also air-transported paratroopers have a similar bonus, but I don't know if (in your game) there are dedicated transports for paratroopers (as in reality) or the bombers paratroop and bomb at the same time like in the basic games or paratroopers just jump on their own (not needing any aircraft) like in the 1940 series.

If the paratroopers are transported by air units, you would also need an other option which limits support only to transported units, then you could have the transporting aircraft giving support to the paratroopers (sort of like artillery does to infantry in the basic games). Such an option could be maybe also used for limiting support from land transports only to the transported units and maybe even for having sea transports giving support to the units which they offload. I don't actually know, though.

Definitely sounds good to me that paratroopers being used as such should be able to have different powers than paratroopers used as simple land units (sort of like the Marine bonus), but it's up to @asvitkine or whatever developer to see if they want to support such rules. Guess they'll have to read the rulebook to be sure.

Can you please reference the rulebook and the page or pages where the relevant rules are to be found?

beelee1 commented 4 months ago

@Cernelius here's the rulebook https://www.axisandallies.org/forums/topic/36945/axis-allies-global-1940-house-rules-expansion

Paratroopers are on page 18 and U-boats page 41.

Yea the Paratroopers are self supported, so the air transport is included with the unit, similar to G40.

Yea, really hope he takes it on. It'd be way usefull for more than just this mod :)

Edit Here's a more direct link to the rulebook https://drive.google.com/file/d/1SRDOsOwlO4Aa13cULwkWrorrXEmCmiN-/view?pli=1

Cernelius commented 4 months ago

I see that paratroopers need to be both alone (beside aa guns) and having moved by air when attacking to have the special offensive or defensive power (attacking at 3 instead of at 1 or defending at 3 instead of at 2 during only the first round of combat). Moreover, paratroopers cannot be supported by artillery if they moved by air.

Assuming supports could be given on the first round of combat only (as per my proposal), the alone part could be actually sort of hacked by giving every fighting land and air non-paratrooper unit beside aa guns a -2 offensive modifier and -1 defensive modifier to infinite allied paratroopers units for the first round of combat while paratroopers give +2 and +1 respectively for offence and defence to themselves for the first round of combat, but this feels a bit of a work-around to me and would not cover the fact that every paratrooper can either move as a movement 1 land unit or as a movement 2 (3 with airfield) air unit which can land in enemy territories. This last alternative movement is sort of already supported in TripleA thanks to the "Airborne Combat Move" (but in the basic 1940.II series is tech dependant and requires the presence of an airfield in the starting territory, whereas no airfield is needed according to these rules but gives total air movement of 3 to paratroopers moving by air if present), comprising the fact that paratroopers moving as air units may get shot by AA guns, but TripleA itself would need to be made able to discern between paratroopers which moved by land and paratroopers which moved by air and somehow confer the offensive bonus only to the latter and only on the first round of combat.

Also considering that it is needed to disable the support ability of artillery in favour of paratroopers if these paratroopers moved by air, I would say this should be done by an additional option to the support attachment too. This option should be a flag which allows/disallows support depending on whether the receiving units moved by air or by other means, and then the artillery support should be updated as not to apply to units which moved by air, whereas two more couples of support attachments would be added, by which every paratrooper gives +2 attack / +1 defence power to itself on the first round of combat, and every non-paratrooper gives -2 attack / -1 defence to infinite paratroopers on the first round of combat, and both of these two additional couples of support attachments do not apply to units which have not moved by air.

Of course, the aforementioned workaround itself could be avoided by having an other option which disallows the support if any other units beside a list of exceptions (like aa guns) is present on its own side (comprising co-defenders, which are usually but not always allies). That way, only the couple of +2/+1 support to self for paratroopers would be needed, with the additional three options that these supports are active only for the first round of combat, only for paratroopers which moved by air and only as long as no other units but paratroopers and aa guns are partaking on the same side.

By the way, it feels very strange to me that paratroopers cannot attack at 3 if they are attacking together with air units like a bomber, but of course rules are rules if I'm understanding that correctly (that, if I send 1 paratrooper alone via air, it attacks at 3, whereas, if I send 1 paratrooper and 1 fighter alone via air, the paratrooper attacks at 1).

Moreover, I guess that the rule

When a Paratrooper attacks by land, it attacks as a regular infantry unit at “1” – in this case it can also be supported by an artillery unit and thereby attack at “2”.

is incomplete, and it actually applies also in case the paratrooper is offloaded (by a sea transport) so practically in every case the paratrooper attacks not by air (and not just in the case it attacks by land).

Moreover the rule

If Paratroopers attack by air and are supported by units other than Paratroopers, the Paratroopers attack at “1”.

is quite unclear in the moment it states "are supported by units other than Paratroopers", and I assume that what this part of the rules actually means is "are attacking together with units other than Paratroopers", which anyway would not clarify if my aforementioned paratrooper (which is attacking together with 1 fighter and no other units) would attack at 3 if the fighter is shot down by aa guns or anyway eliminated before the paratrooper can make its attack (assuming that the paratrooper attacks at 1 if the fighter attacks too).

Moreover, the aforementioned rule is still likely literally wrong with respect to what I can imagine the author intended to rule because it would imply that, for example, if I send 1 paratrooper by air and 1 paratrooper by land into the same territory to make battle, while sending no other units, then the paratrooper sent by air attacks at 3 (because it is not supported/accompanied by units other than paratroopers), and this clearly makes no sense in the moment that the same paratrooper would instead attack at 1 if the paratrooper moving by land was instead an infantry. My assumption is that the author intended to say that paratroopers attack at 3 only if they are alone and each of them moved by air, but this is not actually stated in these (additional) rules. Of course, I may be wrong here: maybe the author actually wanted that, when you have one or more paratroopers attacking a territory by air together with only one or more other paratroopers attacking the same by land or sea or both, the former paratroopers attack at 3 (on the first round of combat) and the latter ones attack at 1 (which is what the rules are literally stating).

Honestly, I find these paratroopers rules a bit too on the heavy side as a matter of quantity of rules, but that tends to be so with paratroopers rules in general (as they are the most complex tech also in the basic games).

By the way, the rule that paratroopers must be completely alone to have the bonus definitely make no sense to me, but that is just my opinion.

I also dislike the exception by which paratroopers cannot air attack capitals because it is a restriction which makes realistically no sense to me, but that is again just my opinion (and yet an other special rule which would have to be supported which I've previously ignored because I already felt over-loaded).


Definitely this is a much more complex and exceptional rule than the simple bonus first round offence/defence for submarines, so maybe it is better just to think about it only after the submarine rule gets done (if it gets done), so we know at least how that actually works.

On top of that, if we are close to releasing 2.6, maybe it is better not to add features until after the release for safety? I've no idea about this nor how close to the release we actually are, so I would defer to @asvitkine or any developer.


To summarize, my suggestion to @asvitkine or any developer would be to support the aforementioned rules for submarines (units having a simple modifier for the first round of combat only) but to hold off for paratroopers until their rules are made clearer and simpler. However, I would say that having the ability to give paratroopers which are actually being air-dropped a different offensive value than paratroopers which have moved by land (or sea) is something which I see as very valuable (and it is quite surprising to me that the basic games do not have any such rules as far as I know) and conceptually akin to the already supported "Marine" rule.

beelee1 commented 4 months ago

@Cernelius yea I think the can't attack Capitals is for play balance. You'd be forced to keep a lot of defense there, although a lot of builds are in your Capital anyways. Especially moscow. But that is my understanding of it.

azimuth came up with a workaround here I think it should work. Haven't tried it yet. https://forums.triplea-game.org/topic/3795/broken-air-battles-with-2-6/14

Screenshot from 2024-04-27 08-59-33

Cernelius commented 4 months ago

That is not going to work because that way you cannot take the submarine as casualty in the first round of combat (the submarine will become practically invulnerable in the first round of combat).

beelee1 commented 4 months ago

oh ... bummer :(

yea they'd auto spawn to the new unit hmm ... yea I guess that won't work. Maybe you could have a token that gives the new unit combat support via support attachment and if it's not there the new unit wouldn't be able to do combat ? That way the token could take any first rd hits

no that wouldn't work either besides being a massive hack.

Edit actually it might work. idk tho. Think it'd be easier to just do it in edit and player enforce

Well hopefully asvitikine takes it on. It's actually not that big of a deal todo it in edit currently. We're kinda used to it at this point :)

asvitkine commented 4 months ago

If the current engine could already be scripted via XML to support it, then I don't think new features are needed.

How about having a trigger that spawns a special unit that doesn't have any attack, but provides bonus to 3 submarines (via number property on the support attachment) on attack and have that unit be flagged as isSuicideOnAttack.

Then, you just need to spawn that unit anywhere there are three groups of submarines of the current player. It's a bit convoluted, but I think it would work? The trigger should run at end of combat move phase. And there should be another trigger to remove all of these at the end of combat.

beelee1 commented 4 months ago

That sounds like it would work. I'll give it a shot

Edit Hmm ... it doesn't just do it for 3 submarines though. It would do it for 3 plus, so 4,5,6 etc would all get the bonus too. Anyway, I'll give it a shot

Edit 2 Ok it should still work values: how many units to be supported

beelee1 commented 4 months ago

@asvitkine yea unfornutaely isSuicideOnAttack doesn't work. What happens is, that it suicides before the units it's supporting roll. With set to true it didn't work. Set to false, it did work, but of course it doesn't kill itself.

That was good idea though and worth a try.

Edit Idky though. According to POS it shouldn't have died untill after the rolls.

isSuicideOnAttack values: unit suicides during round 1 when attacking, it will suicide right after its turn to fire so either right after normal rolls or right after first strike if that's set to true, can't target isSuicideOnDefense units since those will suicide themselves

hmm ... I will try and remove the "isSub" from it and see if that works or actually I think I need to add "isFirstStrike" to it. I thought "isSub" already did that ?

Well, I'll test a bit more

Edit 2 Yea ! Success ! Removing "isSub" makes it give it's support and it still dies and can't be taken as a casualty, even if the defender gets a hit. :)

Now we'll try it on defense and then move on to the paratroopers. Thanks again for the excellent suggestion.

I still use edit as is for landmine battles and it's just nice to have the flexibility to use as is, so please still don't change it :)

beelee1 commented 4 months ago

@asvitkine well it works on defense with one exception. This a G 40 mod and if submarines are attacked by other submarines with a Destroyer and they don't have a Destroyer to protect them, they will lose any FirstStrike hits before they can fire back.

This could lead to a situation where the Wolfpack would disolve due to having less than 3 subs. But they would still get there bonus on first rd of defense. Which would be incorrect.

Not a huge issue, but one would need to use edit in that case.

Still a great improvement :)

beelee1 commented 4 months ago

@asvitkine I had forgotten your question

And on page 8, it's talking about Tank Armies and Army Corps which sound like they might be changing the number of dice rolled, etc. Wouldn't that not be supported with how Edit mode combat works due to number of dice differences?

Yea the extra rolls show up in edit. So it works correctly.

Yea Paratroopers will work with no edit now. This can probably be closed. wc has opened a feature request at the site https://forums.triplea-game.org/topic/3797/paratroopers-and-u-boats

It'd still be nice to have at some point in the future. A lot easier to work with and other maps might use it differently.

And still keep edit as is. There are other situations it's still needed. The flexibility it provides is a great tool for non rule compliant games.

Anyway, Thanks again for your help.

WCSumpton commented 4 months ago

@beelee1 You've created a condition to check every territory for paratroopers. Then created another condition to check every territory for the absence of allied units, except aaGuns. Created a trigger for every territory that checks those conditions to spawn a suicide unit to give a bonus for a single combat round. That's a wild hack! Way to go. LOL

Cheers...

beelee1 commented 4 months ago

@WCSumpton heh heh not that hardcore :) What I did was add a "ParatrooperBoost" unit that gives the support. He's "isAir" with 99 movement, so can go anywhere. There are two place phases. So you need to buy as many as you need at no cost and then place in 1st place phase. That way there ready for combat that turn.

It's essentially Player Enforced. If you forget to buy one or not enough, need to edit one in at start of CM. They are "isConstruction" so they don't count as a placement.

You'll have to edit them in for defense after the battle if you win. I have some extra boxes too and have thought about just at top of map I could store some in. Then you could just click on them in NCM and "Perform Move or Other Actions" . Might be a little easier than adding by hand. Edit Or just by a extra one at start. Leave him in your Capital. That'd be easy enough :)

Still have to hand roll for any AA fire they encounter as the defender can choose his targets if normal Air Units attack with it. Otherwise I could make a special aaGun to shoot at just the Paratroopers. I suppose I could make one trhat only shoots once and you can edit those in for the defender as needed. Idk, it's not to bad to hand roll. Too bad Dice Roller wasn't documented in History :) We just use the A&A.org one for our PBF games.

The Wolfpack is the one I went big on :) But I already had that done for removing the Wolfpack if there were less than 3 U-boats. Just for Atlantic and Med. So I just copied it and changed that for it to add a Wolfpack when theres 3 or more :)

A little edit still but a Major improvement :)

asvitkine commented 4 months ago

So assuming we want to keep edit as-is, how to resolve the 10000 rounds error?

For battle simulation (that AI does behind the scenes), it's easy enough to just turn edit off for the simulations. But then you get real AI battles - and those will just freeze triplea as it will actually try to go for that many rounds.

At first, I thought we could make AI retreat, but then that's not always an option. I guess the question is who should be selecting casualties in edit mode in that case? If it's AI vs. AI, I guess we could just make casualties be selected as if it's not auto. But theoretically if it's an AI vs. human or human vs. AI battle, you do want casualties selected manually?

asvitkine commented 4 months ago

I think for now, I'll just make edit mode get turned off when transitioning to an AI player step. Before the change, that would have just hit that error anyway, so now at least it won't.

asvitkine commented 4 months ago

@beelee1

I have another idea of how to make subs work as you want them. Same idea of spawning a special unit before attack phase whenever there are groups of three subs of the current player.

Make this unit suicide and make it actually have attacking rolls that the subs should have on first round. Then make its support attachment negatively affect the three subs by removing their dice rolls or changing what they hit on to 0.

I think that should work. Could you try it out?

beelee1 commented 4 months ago

@asvitkine

Yea Idk about player vs AI in edit. I would think that wouldn't work. Never tried it. I think edit would require a human to use it.

I'm actually quite pleased with how things are working now. Just a HUGE improvement thaks to your suggestion :) I like the support unit, because we can use hepps badass looking unit image, which helps tell at a glance that there is a wolfpack formed.

I will test out your latest idea though.

Thanks again. Really a Major improvement, with both it and paratroopers

beelee1 commented 4 months ago

@asvitkine

just reread. Yea, I see what you're saying now. The result would be the same, just a different way todo it. But I will test it

beelee1 commented 4 months ago

@asvitkine

Using your last suggestion I get an extra roll in combat. 3 U-boats and 1 Wolfpack get 4 rolls. Maybe I have the supportAttachment written wrong.

Screenshot from 2024-05-08 14-33-37

Screenshot from 2024-05-08 14-24-51

The negative bonus so the U-boats don't fire works correctly.

I tried it with 4 U-boats and got 5 dice. The Wolfpack is now A3 D3 and kills itself on both attack and defense.

Anyway, your original suggestion works great :) And revisiting this has made me realize I should try and have the Wolfpack spawn end of CombatTurn. Won't need to buy and place at all then :) I can also duplicate the triggers and have them respawn after place as well.

asvitkine commented 4 months ago

@beelee1

Is the Wolfpack the unit that's spawned when there are three u-boats? Then the support attachment isn't set up how I expected.

I would expect it to be attached to Wolfpack and not GermanUBoat and for it to have unitType be GermanUBoat. So you want the Wolfpack affecting the UBoats, not the other way around.

Then you want number to be set to 3 to affect 3 uboats. And you set <option name='dice' value='strength'/> and <option name='bonus' value='-1'/> to blank out their rolls.

WCSumpton commented 4 months ago

@beelee1, @asvitkine

Right now, the global_40_expansion_uhd_boxes.xml is over 78k lines long and makes for a difficult read. Every 'work-around'/hack only make editing more difficult. It's no wonder @beelee1 would rather leave thing 'as they are'. Even though the hacks look good here, each sea zone for subs, escorts, transports, etc. must be check 3 or 4 times per sea zone and there are 127 sea zones to check, and these checks are multiplied by each player. Without the use of variables and foreach loops, the number or xml lines just continues to increase.

Again, I suggest that adding "maxRounds" check to both supportAttachments and territoryEffectAttachments would be a better route for what @beelee1 wants to accomplish.

Cheers...

beelee1 commented 4 months ago

@asvitkine

I would expect it to be attached to Wolfpack and not GermanUBoat and for it to have unitType be GermanUBoat. So you want the Wolfpack affecting the UBoats, not the other way around.

yea that's how I set it up the first time, which works. I was just trying your new idea because you asked me to. I don't really see the difference result wise.

The Wolfpack boosts the U-boats +1 for 1 rd in the first way. The second way the U-boats boost the Wolfpack for 1 rd with the Wolfpack taking away the U-boat 1st rd combat to 0.

The first way works good, so i'll just roll with that :)

@WCSumpton yea it's pretty messy lol. I need to revisit the variables thing and try and clean it up. My past attempts have all failed :)

asvitkine commented 4 months ago

@asvitkine

I would expect it to be attached to Wolfpack and not GermanUBoat and for it to have unitType be GermanUBoat. So you want the Wolfpack affecting the UBoats, not the other way around.

yea that's how I set it up the first time, which works.

I thought it didn't work on attack because a suicide unit dies before it can provide support? Or did I misunderstand. I was trying to find a suggestion to workaround that.

I was just trying your new idea because you asked me to. I don't really see the difference result wise.

I think there was a miscommunication since my new idea was still having the special unit to provide support. It was meant to workaround it not working on attack due to the suicide thing - but maybe I didn't understand and it actually works already?

Again, I suggest that adding "maxRounds" check to both supportAttachments and territoryEffectAttachments would be a better route for what @beelee1 wants to accomplish.

Doesn't that still require the map script creating the support unit (which I think is the main part of the complexity)? I don't see it being different in terms of complexity of XML between the two solutions except adding that property requires coding engine changes (and a lot of complexity) whereas the idea behind my suggestion is existing features can already accomplish the task.

... And yeah if you want to do checks per-sea zone etc, that should be done with variables. If it's not doing that, that would be the first thing to clean up. (Just define a list of sea zones at the top of the file and do foreach on them.)

Also, just in terms of reducing file size, you can remove everything except the last name for all the javaClass= properties - i.e. javaClass="UnitSupportAttachment" instead of the very long thing. Same for every other attachment type.

asvitkine commented 4 months ago

Also, just in terms of reducing file size, you can remove everything except the last name for all the javaClass= properties - i.e. javaClass="UnitSupportAttachment" instead of the very long thing. Same for every other attachment type.

I sent a PR for that here: https://github.com/triplea-maps/global_40_expansion_uhd_boxes/pull/4

WCSumpton commented 4 months ago

Doesn't that still require the map script creating the support unit (which I think is the main part of the complexity)? I don't see it being different in terms of complexity of XML between the two solutions except adding that property requires coding engine changes (and a lot of complexity) whereas the idea behind my suggestion is existing features can already accomplish the task.

No, the GermanUBoat would apply the buff itself and there would be no need for a separate Wolfpack unit. If there was a "maxRounds" option in support attachments then:

    <attachment name="supportAttachmentWolfpackBuff" attachTo="GermanUBoat" javaClass="UnitSupportAttachment" type="unitType">
      <option name="unitType" value="GermanUBoat"/>
      <option name="faction" value="allied"/>
      <option name="side" value="offence"/>
      <option name="dice" value="strength"/>
      <option name="maxRounds" value="1"/>
      <option name="bonus" value="1"/>
      <option name="number" value="3"/>
      <option name="bonusType" value="Wolfpack_bonus" count="3"/>
      <option name="impArtTech" value="false"/>
      <option name="players" value="Germans"/>
    </attachment>
    <attachment name="supportAttachmentWolfpackDeBuff" attachTo="GermanUBoat" javaClass="UnitSupportAttachment" type="unitType">
      <option name="unitType" value="GermanUBoat"/>
      <option name="faction" value="allied"/>
      <option name="side" value="offence"/>
      <option name="dice" value="strength"/>
      <option name="maxRounds" value="1"/>
      <option name="bonus" value="-1"/>
      <option name="number" value="2"/>
      <option name="bonusType" value="Wolfpack_Debuff" count="2"/>
      <option name="impArtTech" value="false"/>
      <option name="players" value="Germans"/>
    </attachment>

Is all the code needed to handle the attack support. It's like "maxRoundsAA", which govern how may rounds a unit may conduct an AA attack.

Cheers...

beelee1 commented 4 months ago

@asvitkine

yea muts've been a Led Zeppelin breakdown. :) Your first solution works great.

I will look at the suggestions to clean up the code.

@WCSumpton

yea still wanna have the Wolfpack image show up thow, which is easy enough todo with conditions.

Anyway, it's working real good right now. I just changed it so the Wolfpacks place or remove before combat. Also after place. For placement, so if you buty 3 and place, then it'll spawn as well.

Only time we'd need to edit is if the Wolfpack disolved in defense. Like USA attacks, kills a U-boat and then UK attacks right after. If there were still 3 or more Wolfpacks left after the USA attack, you'd have to edit the Wolfpack back in since he'd be dead from the combat.

Anyway, I don't wanna bug on your guy's time. It's working real good right now.

Thanks for all your help :)

Rock On !!!

beelee1 commented 4 months ago

@WCSumpton

Actually your suggestion is the best, because if the U-boats were attacked during another players turn and still had at leat 3 present, the behavior would be correct.

The image would be gone, but bfd it'll respawn :)

WCSumpton commented 4 months ago

@beelee1

Let's take a second to look at what @asvitkine is suggesting. First you would need to create variable list or all the sea zones:

<variableList>
   <!-- A list of all Atlantic/Mediterranean sea zones to check for Walfpack -->
   <!-- There are 52 sea zones to check -->
   <variable name="WolfpackSeaZones">
      <!-- All sea zones end in " Sea Zone" so only the number is set -->
      <element name="127"/>
      <element name="126"/>
      ...
      ...
      ...
      <element name="68"/>
      <element name="67"/>
   </variable>
</variableList>

Now for some conditions:

<!-- Check for the presence of 3 German U-Boats -->
<attachment foreach="$WolfpackSeaZones$" name="conditionAttachment_3_GermanUBoat_@WolfpackSeaZones@_SeaZones" attachTo="Germans" javaClass="RulesAttachment" type="player">
   <option name="directPresenceTerritories" value="@WolfpackSeaZones@ Sea Zone" count="1"/>
   <option name="unitPresence" value="GermanUBoat" count="3"/>
</attachment>
<!-- Also check for the presence of any other friendly unit -->
<!-- This should check for all sea and air unit that can aid -->
<attachment foreach="$WolfpackSeaZones$" name="conditionAttachment_No_Allied_Help_@WolfpackSeaZones@_SeaZones" attachTo="Germans" javaClass="RulesAttachment" type="player">
   <option name="directPresenceTerritories" value="@WolfpackSeaZones@ Sea Zone" count="1"/>
   <option name="unitPresence" value="Battleship:Destroyer:every thing but Transport:and all air" count="1"/>
   <option name="invert" value="true"/>
</attachment>

Next are the triggers:

<!-- Place Wolfpack where there are 3 German U-Boats with no allied help -->
<attachment foreach="$WolfpackSeaZones$" name="triggerAttachment_Wolfpack_at@WolfpackSeaZones@_SeaZones" attachTo="Germans" javaClass="TriggerAttachment" type="player">
      <option name="conditions" value="conditionAttachment_3_GermanUBoat_@WolfpackSeaZones@_SeaZones:conditionAttachment_No_Allied_Help_@WolfpackSeaZones@_SeaZones"/>
      <option name="placement" value="@WolfpackSeaZones@ Sea Zone:Wolfpack" count="1"/> 
      <option name="when" value="after:germansCombatMove"/>
      <!-- These are added to ensure Wolfpack is placed for defensive purposes -->
      <option name="when" value="after:russiansCombatMove"/>
      <option name="when" value="after:americansCombatMove"/>
      <option name="when" value="after:chineseCombatMove"/>
      <option name="when" value="after:britishCombatMove"/>
      <option name="when" value="after:anzacCombatMove"/>
      <option name="when" value="after:frenchCombatMove"/>
    </attachment>
    <!-- Remove Wolfpack prior to NonCombat move (There was no check for enemy units) -->
    <attachment name="triggerAttachment_Remove_All_Wolfpack" attachTo="Germans" javaClass="TriggerAttachment" type="player">
      <option name="conditions" value="conditionAttachment_SwitchIsTrue"/>
      <!-- There are 52 sea zones, so 55 gives a little cushion -->
      <option name="removeUnits" value="all:Wolfpack" count="55"/> 
      <option name="when" value="before:germansNonCombatMove"/>
      <option name="when" value="before:russiansNonCombatMove"/>
      <option name="when" value="before:americansNonCombatMove"/>
      <option name="when" value="before:chineseNonCombatMove"/>
      <option name="when" value="before:britishNonCombatMove"/>
      <option name="when" value="before:anzacNonCombatMove"/>
      <option name="when" value="before:frenchNonCombatMove"/>
    </attachment>

If this seems easier, then there you have it!

Cheers...

beelee1 commented 4 months ago

@WCSumpton

Oh way sweet you taking time on this. :)

I'll look closer tommorow as it's getting late in the day for me :)

But yea, i need to get that variable shit to work lol