[POC] Proof of Concept of event-based kill assignment #4781
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Event-based Kill Tracking Proof of Concept
Summary
This is the rough initial attempt to implement some measure of Event-based kill claiming.
I'd like to have this looked at, and if it seems feasible at scale, implement a more robust version.
Details
The basic gist is:
Rather than tracking damage and attackers down into the multifarious damage resolution methods and special cases, I believe using event handling simplifies this problem considerably:
Because destruction must chronologically follow attacks or actions - there is no effect without a cause - this approach of registering Causes and then letting them decide which one is responsible for a later Effect assures us that we will not credit later Attacks for prior Kills, something that could happen with our depth-first approach to damage generation and limited tracking now. Conversely, while the linear approach to tracking damage to subsequent kills requires tracing multiple paths to confirm, say, that nobody died, the event-based approach can simply do nothing if nothing dies; it's quite economical.
Proof of Concept
This extremely rough POC adds only unit-level kill credit for:
It makes no attempt to resolve disputes over kill claims, awarding credit to any units that can "prove" that they attacked the dying unit. It cannot deal with long-range artillery, or accurately accumulate damage dealt over several turns. There are a number of methods of destruction it is not instrumented for. It's janky3.
Most importantly, it only claims kills for units, not for the team they belong to.
But I can already see how this approach would simplify kill accounting without requiring onerous levels of plumbing. For instance, to add kill-sharing for TAG scouts and missile boats, we would need only to add the following lines to the TAG-handling code:
somewhere around line 34,342 (!?) of
GameManager.java
. That should be all that's needed to give TAGgers credit for helping with kills.Full Implementation
I believe a full implementation will require rewriting the existing kill-tracking code completely; if part of it uses Events, it all should, for consistency and clarity. In writing the POC I didn't even find the final victory scoring code, so I can't say yet how much work it will require to replace. But it should be on the order of adding one or two lines in a few dozen places throughout
GameManager.java
, with a more substantial rework of victory scoring and implementation of a map of Unit->Kill Claims objects to tally damage dealt and claimed kills over the course of a game.I'd also say that tracking criteria for awarding kills (per unit or per team) should be split out of the GameUnitDeathListenerAdapter implementation, for a few reasons. While event handlers are terrific for ignoring everything except the specific information they are interested in, there are a few things they're ill-suited to:
That said, the simple Listener-clearing function I used in the POC should be replaced by a method of self-deleting4, within the listeners themselves, based on a timeframe and/or count of deaths:
etc.
Concerns
There are a lot of unknowns and provisos here:
Future
I could see us replacing a lot of fiddly multi-stage unit updating and nested if/else/switch/case code with fired events and simple handlers; this paradigm seems particularly well-suited to board games with limited numbers of units that need to deal with a wealth of different rules.
For instance, we could move a lot of the spaghetti code out of
GameManager.java
and into the individual unit Types. Green Gas attacks could just fire an Event that only units with old TSM would need to listen for. This approach is especially nice as an alternative to repeatedly polling each and every unit for location in the case of, e.g., an AE weapon. Well, code-wise it's nicer; under the hood it's doing much the same thing.Footnotes
GameManager.java
itself. Additionally, they do not allow for much information: we might know that Atlas A dealt 10 damage to Crusader C most recently, but lose the information that Blackjack B dealt 20 damage immediately prior, so can only give the kill to A.Media
I still want to do more testing, but here are files from a test game with the POC code bolted on to the side of the existing kill claim code. It seems to be working pretty well: although the majority of "deaths" came from auto-ejecting pilots, the kills were assigned (afiact) correctly to the units who made the attacks that caused those ejections. Dead units may still be listed as killed by "pilot error", but replacing that code with events would fix that.
megamek.log
gamelog.tar.gz
salvage.mul.tar.gz
Bot_Princess.mul.tar.gz