Empire of Gold: New Conquest — Game Spec & Implementation Notes
Empire of Gold: New Conquest — Game Spec & Implementation Notes
Status: Implemented
GameId: empireofgoldnewconquest
Math file: empire-of-gold-new-conquest-R3.json
Math modes: R3
Pack: pack-alpha
1. Overview
Variant of empireofgold. Mechanically identical except for one addition: a
passive base-game metamorphic feature ("Symbol Change" / "Symbol Replacement")
that can upgrade all instances of a selected low-paying symbol into a selected
high-paying symbol under specific conditions.
All other mechanics (cluster pay, cascades, free-spin trigger, multipliers,
ANTE stacks, buy-bonus trigger, buy-bonus) are unchanged from empireofgold.
2. Symbol Change Feature
2.1 Rules
The feature runs on the initial reel view of a base-game spin, after reel generation (and after any ANTE stack replacement, though it only runs in BG anyway) and before pay evaluation.
Algorithm:
- Pick one low symbol
selectedLowfromSymbolChange_LowWeights(L1:15, L2:15, L3:20, L4:20, L5:18). - Pick one high symbol
selectedHighfromSymbolChange_HighWeights(H1:10, H2:25, H3:25, H4:25). - Count occurrences of
selectedLowandselectedHighon the reel view. - If
count(selectedLow) + count(selectedHigh) <= 7then do nothing. - Else roll
SymbolChange_TriggerWeights(Yes:1 / No:49, ~2% Yes). OnNo→ do nothing. - On
Yes→ replace every cell equal toselectedLowon the reel view withselectedHigh.
2.2 Scope
Runs in BG only. Does not run in:
ANTE(ante bet)BB_Trigger(buy-bonus trigger spin)- Free spins (
FG) or buy-bonus (BB) — the feature hook lives inengine.executeSpinwhich is not invoked for free spins; they run viaengine.executeFeature→logic.runFeature.
2.3 Cascade behavior
Runs exactly once per spin, on the initial reel view only. Does NOT re-run on any cascade following a win within the same spin.
2.4 Counting rules
- Straight cell-equality match against
selectedLow/selectedHigh(plain string compare). SC(scatter) andBN(bonus) cells are naturally excluded because they never equalL*/H*symbols.- At the point this feature runs, no
BN_<mult>suffix has been applied yet (those are added later inside the cascade loop), so no special-casing is needed.
2.5 Math weight tables (source of randomness)
All three live under BG in the math JSON in the 2D shape used by
@slot-platform/sdk getRandomValue<T>:
"SymbolChange_HighWeights": [["H1","H2","H3","H4"], [10,25,25,25]],
"SymbolChange_LowWeights": [["L1","L2","L3","L4","L5"], [15,15,20,20,18]],
"SymbolChange_TriggerWeights": [[true,false], [1,49]]
The trigger table uses booleans (not the raw "Yes"/"No" strings from the
XLSX) so getRandomValue<boolean> returns a directly-usable flag.
3. Architecture & File Layout
games/empireofgoldnewconquest/
├── project.json # Nx lib, mode R3 for simulate
├── tsconfig.json
├── tsconfig.lib.json
└── src/
├── index.ts # exports plugin + config + types
├── config.ts # EmpireOfGoldNewConquestConfig
├── interfaces.ts # adds SymbolChangeResult + field on SpinResult
├── plugin.ts # EmpireOfGoldNewConquestPlugin
├── engine.ts # hooks applySymbolChange on BG
├── logic.ts # unchanged vs empireofgold
├── symbol-change.ts # NEW: pure helper for the feature
└── maths/
└── empire-of-gold-new-conquest-R3.json
Path alias (inherited from the @slot-platform/game-* glob in
tsconfig.base.json):
@slot-platform/game-empireofgoldnewconquest → games/empireofgoldnewconquest/src/index.ts
3.1 Dependency graph
- Depends only on
@slot-platform/sdk(tagtype:game→type:sdk). - No NestJS dependency (same as all other games).
4. Implementation Details
4.1 engine.ts hook
In executeSpin, after reel generation and any ANTE stack replacement, and
before logic.spin(...):
let symbolChange: SymbolChangeResult | undefined;
if (gameType === 'BG') {
const sc = applySymbolChange({ reelView, mathByGameType });
reelView = sc.reelView;
symbolChange = sc.result;
}
const spinResult = this.logic.spin({ /* ... */ reelView, /* ... */ });
if (symbolChange) {
spinResult.symbolChange = symbolChange;
}
gameType is already computed at the top of executeSpin and is one of
'BG', 'ANTE', 'BB_Trigger'.
4.2 symbol-change.ts
Pure function, no side effects. Never mutates the input reelView — returns
a new 2D array when the feature applies, else returns the input reference.
Return value:
{
reelView: string[][];
result: {
applied: boolean;
selectedLow?: string;
selectedHigh?: string;
lowCount?: number;
highCount?: number;
triggered?: boolean; // only set when the trigger roll actually happened
};
}
4.3 SpinResult.symbolChange surface
Optional field on SpinResult (see interfaces.ts). Populated whenever the
feature hook ran (BG only), so even a "not applied" result is visible for
client / replay / simulator inspection.
Not involved in any win calculation.
4.4 Unchanged from empireofgold
logic.ts— identical cluster detection, cascade loop, BN multiplier logic, FS trigger, max-win cap, FS retrigger.- Free-spin path (
engine.executeFeature→logic.runFeature) is untouched. config.tsvalues (layout 5×6, min cluster 8, FS triggers, bets, max-win) are identical; only the exported symbol name was renamed.
4.5 Plugin registration
apps/pack-alpha/src/app.module.ts:
GameCoreModule.register([
new EmpireOfGoldPlugin(),
new EmpireOfGoldNewConquestPlugin(),
new Royale81Plugin(),
]);
apps/pack-alpha/games.json:
{ "games": ["empireofgold", "empireofgoldnewconquest", "royale81"] }
The pack's webpack config auto-copies the math JSON directory for every game
listed in games.json, so no webpack changes are needed.
5. Math Parser (feg_parse-maths)
New command registered in src/cli.module.ts:
- Command name:
empire-of-gold-new-conquest - Source file:
src/commands/empire-of-gold-new-conquest.commands.ts - Input XLSX:
./rawMaths/empireOfGoldNewConquest/GoO added feature PAR sheet.xlsx - Output:
./output/empire-of-gold-new-conquest-R3.json
5.1 Sheet layout differences vs original empireofgold XLSX
The only structural change in the new XLSX is in the Base Game sheet
where the "Symbol Change Feature" block was inserted at columns AJ..AN.
This pushed the existing cascade weight tables right by 6 columns. All other
sheets (Free Game, BuyBonus, BaB Trigger, Ante) use the same ranges as
empireofgold.
| Key | empireofgold | New Conquest |
|---|---|---|
BG_RallyNonRallyCascadeWeights_START_RANGE | AJ21:AK22 | AP21:AQ22 |
BG_RALLY_WEIGHT_TABLE_RANGE | AP27:AQ31 | AV27:AW31 |
BG_NONRALLY_WEIGHT_TABLE_RANGE | AS27:AT31 | AY27:AZ31 |
5.2 New ranges for the Symbol Change feature
| Key | Range | Notes |
|---|---|---|
BG_SymbolChange_HIGH_WEIGHTS_RANGE | AJ6:AK9 | H1..H4 |
BG_SymbolChange_LOW_WEIGHTS_RANGE | AM6:AN10 | L1..L5 |
BG_SymbolChange_TRIGGER_WEIGHTS_RANGE | AK21:AL22 | "Yes"/"No" → converted to booleans |
5.3 New helper in the parser
parseWeightTableAs2D(worksheet, range) reads a 2-column Symbol|Weight
block (skipping blanks) and emits [[keys], [weights]] ready for
getRandomValue. Used for all three new tables. For the trigger table the
"Yes"/"No" strings are mapped to true/false before emit.
5.4 Reel ranges
Same as original empireofgold. In particular, do not extend the reel
ranges past their documented ends — the columns underneath the reels
(H150/H118 etc.) contain numeric symbol-count statistics that would
pollute the reel strips if pulled in.
6. What is intentionally NOT changed
- Math numbers (pay table, bonus multiplier weights, cascade bracket weights, scatter pay, stack weights, reel strips, FS reels, etc.) are the same as the new XLSX provides. Where the new XLSX tables are identical to the original, the JSON values match. No manual balancing was done.
- Free spins, ANTE, buy-bonus, buy-bonus trigger.
SpinResultfields other than the addedsymbolChange.logic.tssource.
7. Known open items / heads-up
- The XLSX caption cell reads
> 8while the screenshot originally showed> 7. The implementation uses> 7, matching the confirmed spec. If the math team wants> 8, change the single constant ingames/empireofgoldnewconquest/src/symbol-change.ts. - No unit tests, no build verification, and no math simulation were run as part of the implementation (repo policy: only on explicit request).