@slot-engine/core 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +7 -14
- package/dist/index.d.ts +7 -14
- package/dist/index.js +68 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -90
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -1
- package/.turbo/turbo-build.log +0 -33
- package/.turbo/turbo-typecheck.log +0 -4
- package/CHANGELOG.md +0 -7
- package/dist/lib/zstd.exe +0 -0
- package/index.ts +0 -205
- package/lib/zstd.exe +0 -0
- package/optimizer-rust/Cargo.toml +0 -19
- package/optimizer-rust/src/exes.rs +0 -154
- package/optimizer-rust/src/main.rs +0 -1659
- package/src/Board.ts +0 -527
- package/src/Book.ts +0 -83
- package/src/GameConfig.ts +0 -148
- package/src/GameMode.ts +0 -86
- package/src/GameState.ts +0 -272
- package/src/GameSymbol.ts +0 -61
- package/src/ReelGenerator.ts +0 -589
- package/src/ResultSet.ts +0 -207
- package/src/Simulation.ts +0 -625
- package/src/SlotGame.ts +0 -117
- package/src/Wallet.ts +0 -203
- package/src/WinType.ts +0 -102
- package/src/analysis/index.ts +0 -198
- package/src/analysis/utils.ts +0 -128
- package/src/optimizer/OptimizationConditions.ts +0 -99
- package/src/optimizer/OptimizationParameters.ts +0 -46
- package/src/optimizer/OptimizationScaling.ts +0 -18
- package/src/optimizer/index.ts +0 -142
- package/src/utils/math-config.ts +0 -109
- package/src/utils/setup-file.ts +0 -36
- package/src/utils/zstd.ts +0 -28
- package/src/winTypes/ClusterWinType.ts +0 -3
- package/src/winTypes/LinesWinType.ts +0 -208
- package/src/winTypes/ManywaysWinType.ts +0 -3
- package/tsconfig.json +0 -19
- package/utils.ts +0 -270
package/src/ResultSet.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { AnyUserData } from "../index"
|
|
2
|
-
import { copy, RandomNumberGenerator, shuffle, weightedRandom } from "../utils"
|
|
3
|
-
import { Board } from "./Board"
|
|
4
|
-
import { GameConfig } from "./GameConfig"
|
|
5
|
-
import { AnySimulationContext, Simulation } from "./Simulation"
|
|
6
|
-
|
|
7
|
-
export class ResultSet<TUserState extends AnyUserData> {
|
|
8
|
-
criteria: string
|
|
9
|
-
quota: number
|
|
10
|
-
multiplier?: number
|
|
11
|
-
reelWeights: ReelWeights<TUserState>
|
|
12
|
-
userData?: Record<string, any>
|
|
13
|
-
forceMaxWin?: boolean
|
|
14
|
-
forceFreespins?: boolean
|
|
15
|
-
evaluate?: (ctx: AnySimulationContext<any, any, TUserState>) => boolean
|
|
16
|
-
|
|
17
|
-
constructor(opts: ResultSetOpts<TUserState>) {
|
|
18
|
-
this.criteria = opts.criteria
|
|
19
|
-
this.quota = opts.quota
|
|
20
|
-
this.multiplier = opts.multiplier
|
|
21
|
-
this.reelWeights = opts.reelWeights
|
|
22
|
-
this.userData = opts.userData
|
|
23
|
-
this.forceMaxWin = opts.forceMaxWin
|
|
24
|
-
this.forceFreespins = opts.forceFreespins
|
|
25
|
-
this.evaluate = opts.evaluate
|
|
26
|
-
|
|
27
|
-
if (this.quota < 0 || this.quota > 1) {
|
|
28
|
-
throw new Error(`Quota must be a float between 0 and 1, got ${this.quota}.`)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static assignCriteriaToSimulations(ctx: Simulation, gameModeName: string) {
|
|
33
|
-
const rng = new RandomNumberGenerator()
|
|
34
|
-
rng.setSeed(0)
|
|
35
|
-
|
|
36
|
-
if (!ctx.simRunsAmount) {
|
|
37
|
-
throw new Error("Simulation configuration is not set.")
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const simNums = ctx.simRunsAmount[gameModeName]
|
|
41
|
-
const resultSets = ctx.gameConfig.config.gameModes[gameModeName]?.resultSets
|
|
42
|
-
|
|
43
|
-
if (!resultSets || resultSets.length === 0) {
|
|
44
|
-
throw new Error(`No ResultSets found for game mode: ${gameModeName}.`)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (simNums === undefined || simNums <= 0) {
|
|
48
|
-
throw new Error(`No simulations configured for game mode "${gameModeName}".`)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const numberOfSimsForCriteria: Record<string, number> = Object.fromEntries(
|
|
52
|
-
resultSets.map((rs) => [rs.criteria, Math.max(Math.floor(rs.quota * simNums), 1)]),
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
let totalSims = Object.values(numberOfSimsForCriteria).reduce(
|
|
56
|
-
(sum, num) => sum + num,
|
|
57
|
-
0,
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
let reduceSims = totalSims > simNums
|
|
61
|
-
|
|
62
|
-
const criteriaToWeights = Object.fromEntries(
|
|
63
|
-
resultSets.map((rs) => [rs.criteria, rs.quota]),
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
while (totalSims != simNums) {
|
|
67
|
-
const rs = weightedRandom(criteriaToWeights, rng)
|
|
68
|
-
if (reduceSims && numberOfSimsForCriteria[rs]! > 1) {
|
|
69
|
-
numberOfSimsForCriteria[rs]! -= 1
|
|
70
|
-
} else if (!reduceSims) {
|
|
71
|
-
numberOfSimsForCriteria[rs]! += 1
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
totalSims = Object.values(numberOfSimsForCriteria).reduce(
|
|
75
|
-
(sum, num) => sum + num,
|
|
76
|
-
0,
|
|
77
|
-
)
|
|
78
|
-
reduceSims = totalSims > simNums
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let allCriteria: string[] = []
|
|
82
|
-
const simNumsToCriteria: Record<number, string> = {}
|
|
83
|
-
|
|
84
|
-
Object.entries(numberOfSimsForCriteria).forEach(([criteria, num]) => {
|
|
85
|
-
for (let i = 0; i <= num; i++) {
|
|
86
|
-
allCriteria.push(criteria)
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
allCriteria = shuffle(allCriteria, rng)
|
|
91
|
-
|
|
92
|
-
for (let i = 1; i <= Math.min(simNums, allCriteria.length); i++) {
|
|
93
|
-
simNumsToCriteria[i] = allCriteria[i]!
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return simNumsToCriteria
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Checks if core criteria is met, e.g. target multiplier or max win.
|
|
101
|
-
*/
|
|
102
|
-
meetsCriteria(ctx: AnySimulationContext<any, any, TUserState>) {
|
|
103
|
-
const customEval = this.evaluate?.(copy(ctx))
|
|
104
|
-
|
|
105
|
-
const freespinsMet = this.forceFreespins ? ctx.state.triggeredFreespins : true
|
|
106
|
-
|
|
107
|
-
const multiplierMet =
|
|
108
|
-
this.multiplier !== undefined
|
|
109
|
-
? ctx.wallet.getCurrentWin() === this.multiplier && !this.forceMaxWin
|
|
110
|
-
: ctx.wallet.getCurrentWin() > 0 && (!this.forceMaxWin || true)
|
|
111
|
-
|
|
112
|
-
const maxWinMet = this.forceMaxWin
|
|
113
|
-
? ctx.wallet.getCurrentWin() >= ctx.config.maxWinX
|
|
114
|
-
: true
|
|
115
|
-
|
|
116
|
-
const coreCriteriaMet = freespinsMet && multiplierMet && maxWinMet
|
|
117
|
-
|
|
118
|
-
const finalResult =
|
|
119
|
-
customEval !== undefined ? coreCriteriaMet && customEval === true : coreCriteriaMet
|
|
120
|
-
|
|
121
|
-
if (this.forceMaxWin && maxWinMet) {
|
|
122
|
-
ctx.record({
|
|
123
|
-
maxwin: true,
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return finalResult
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
interface ResultSetOpts<TUserState extends AnyUserData> {
|
|
132
|
-
/**
|
|
133
|
-
* A short string to describe the criteria for this ResultSet.
|
|
134
|
-
*/
|
|
135
|
-
criteria: string
|
|
136
|
-
/**
|
|
137
|
-
* The quota of spins, out of the total simulations, that must be forced to meet the specified criteria.\
|
|
138
|
-
* **Float from 0 to 1. Total quota of all ResultSets in a GameMode must be 1.**
|
|
139
|
-
*/
|
|
140
|
-
quota: number
|
|
141
|
-
/**
|
|
142
|
-
* The required multiplier for a simulated spin to be accepted.
|
|
143
|
-
*/
|
|
144
|
-
multiplier?: number
|
|
145
|
-
/**
|
|
146
|
-
* Configure the weights of the reels in this ResultSet.
|
|
147
|
-
*
|
|
148
|
-
* If you need to support dynamic / special reel weights based on the simulation context,\
|
|
149
|
-
* you can provide an `evaluate` function that returns the desired weights.
|
|
150
|
-
*
|
|
151
|
-
* If the `evaluate` function returns a falsy value, the usual spin type based weights will be used.
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* ```ts
|
|
155
|
-
* new ResultSet({
|
|
156
|
-
* criteria: "superFreespins",
|
|
157
|
-
* quota: 0.05,
|
|
158
|
-
* forceFreespins: true,
|
|
159
|
-
* reelWeights: {
|
|
160
|
-
* [GameConfig.SPIN_TYPE.BASE_GAME]: { base1: 1 },
|
|
161
|
-
* [GameConfig.SPIN_TYPE.FREE_SPINS]: { bonus1: 1, bonus2: 2 },
|
|
162
|
-
* evaluate: (ctx) => {
|
|
163
|
-
* if (ctx.state.userData.triggeredSuperFreespins) {
|
|
164
|
-
* return { superbonus: 1 }
|
|
165
|
-
* }
|
|
166
|
-
* }
|
|
167
|
-
* },
|
|
168
|
-
* userData: { forceSuperFreespins: true },
|
|
169
|
-
* }),
|
|
170
|
-
* ```
|
|
171
|
-
*/
|
|
172
|
-
reelWeights: ReelWeights<TUserState>
|
|
173
|
-
/**
|
|
174
|
-
* Optional data to use when evaluating the criteria.\
|
|
175
|
-
* This can be used to pass additional context or parameters needed for the evaluation.
|
|
176
|
-
*/
|
|
177
|
-
userData?: Record<string, any>
|
|
178
|
-
/**
|
|
179
|
-
* If set, this will force the game to always trigger a max win.
|
|
180
|
-
*/
|
|
181
|
-
forceMaxWin?: boolean
|
|
182
|
-
/**
|
|
183
|
-
* If set, this will force the game to always trigger free spins.
|
|
184
|
-
*/
|
|
185
|
-
forceFreespins?: boolean
|
|
186
|
-
/**
|
|
187
|
-
* Custom function to evaluate if the criteria is met.
|
|
188
|
-
*
|
|
189
|
-
* E.g. use this to check for free spins that upgraded to super free spins\
|
|
190
|
-
* or other arbitrary simulation criteria.
|
|
191
|
-
*/
|
|
192
|
-
evaluate?: (ctx: EvaluationContext<TUserState>) => boolean
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
interface ReelWeights<TUserState extends AnyUserData> {
|
|
196
|
-
[GameConfig.SPIN_TYPE.BASE_GAME]: Record<string, number>
|
|
197
|
-
[GameConfig.SPIN_TYPE.FREE_SPINS]: Record<string, number>
|
|
198
|
-
evaluate?: (
|
|
199
|
-
ctx: EvaluationContext<TUserState>,
|
|
200
|
-
) => Record<string, number> | undefined | null | false
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export type EvaluationContext<TUserState extends AnyUserData> = Board<
|
|
204
|
-
any,
|
|
205
|
-
any,
|
|
206
|
-
TUserState
|
|
207
|
-
>
|