TECHNICAL CASE STUDY · Performance and reliability
Battle-System Reliability and Performance
How diagnosable constraints and architecture changes reduced the risk of errors in the battle system.
Challenge
As the battle system grew, so did the risks: defects in complex scenarios, crashes, hard-to-reproduce state mismatches, and performance degradation. Some issues originated in early technical choices: the compiler could not detect them because event handling and the use of certain systems were only checked at runtime.
The task was not just to fix individual defects, but to turn recurring categories of problems into violations that could be detected earlier—during the build or through diagnostic events with context.
My responsibility
I profiled and optimised the system, fixed defects, wrote unit tests, and designed battle-architecture changes that improved observability and reliability.
Implementation
Guarding deterministic RNG
Battle used a deterministic random-number generator seeded by the server. Access outside an approved phase could silently desynchronise client and server.
I designed and implemented a runtime guard that controlled the permitted phases for accessing the generator and recorded violations. The guard wrapped legitimate deterministic battle phases; a violation did not interrupt a match, but became an analytics event with context for subsequent investigation.
Player input or battle start
│
▼
permitted Random phase
│
▼
Random called outside the phase ──► analytics event + debug context
Dispatching battle events through a Visitor
Five battle-visualisation managers independently handled approximately 111 event types through manual type checks. When a new event was added, it could accidentally be left unconnected in one of the managers—the compiler would not report an error, and the issue would surface only in a particular game situation.
Rather than using manual type-based dispatch, I introduced a Visitor interface with an explicit method for each battle-event type and migrated the existing visualisation managers to it. This is illustrative pseudocode demonstrating the principle without exposing the project’s internal API:
// Before: a new branch could be absent from one of the managers.
if (battleEvent is DamageEvent damage) ShowDamage(damage);
else if (battleEvent is EffectAppliedEvent effect) ShowEffect(effect);
// After: the contract explicitly lists the supported events.
interface IBattleEventVisitor
{
void Visit(DamageEvent battleEvent);
void Visit(EffectAppliedEvent battleEvent);
// … all other event types
}
// Every manager has to implement the entire contract.
Before: new event → manual checks in 5 managers → omission → runtime defect
After: new event → Visitor contract → compiler requires handling in every manager
This change made adding a new event type a task that could be checked at build time rather than a source of a hidden release defect.
Reducing the data volume saved with input
Profiling showed that saving input accounted for a noticeable share of time and memory allocations in a hot scenario: data was serialised and compressed for subsequent use in the battle process.
I preserved the semantics and reproducibility of input while reducing the volume of data compressed before saving. This reduced the cost of serialisation and compression in a critical path without changing the behaviour of the game mechanic itself.

Profiling the input-processing chain: saving data was one of the main consumers of time and memory allocations in the scenario examined.
Result
A quiet, hard-to-reproduce class of desynchronisations became observable: instead of investigating after the fact, the team received a specific analytics event with debug context. Handling approximately 111 battle-event types in five subsystems also became compiler-controlled, eliminating the category of defects where a new event was left unhandled.
Reducing the volume of compressed data made input processing lighter on CPU and memory in the profiled scenario. Together, architectural constraints, profiling, optimisation, and testing lowered the maintenance cost of an evolving battle system and helped release new content more reliably.