labag 2.5.1 → 2.6.1

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/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { LaBaG } from "./labag";
2
- import { modeList, ModeName } from "./modes";
2
+ import { modes } from "./modes";
3
3
  import { LaBaGEvent, Pattern, PatternName } from "./types";
4
4
  import { Mode } from "./mode";
5
5
  import { patterns } from "./pattern";
6
- import { Recorder, GameRecord } from './recorder';
6
+ import { Recorder, GameRecord } from "./recorder";
7
7
  import { RecordChecker } from "./recordChecker";
8
+ import { ModeName } from "./types/index";
8
9
  declare const labag: LaBaG;
9
10
  declare const recorder: Recorder;
10
11
  declare const checker: RecordChecker;
11
- export { labag, recorder, checker, modeList, patterns, LaBaG, Recorder, RecordChecker, Mode, type LaBaGEvent, type Pattern, type PatternName, type ModeName, type GameRecord };
12
+ export { labag, recorder, checker, modes, patterns, LaBaG, Recorder, RecordChecker, Mode, type LaBaGEvent, type Pattern, type PatternName, type GameRecord, type ModeName, };
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Mode = exports.RecordChecker = exports.Recorder = exports.LaBaG = exports.patterns = exports.modeList = exports.checker = exports.recorder = exports.labag = void 0;
3
+ exports.Mode = exports.RecordChecker = exports.Recorder = exports.LaBaG = exports.patterns = exports.modes = exports.checker = exports.recorder = exports.labag = void 0;
4
4
  const labag_1 = require("./labag");
5
5
  Object.defineProperty(exports, "LaBaG", { enumerable: true, get: function () { return labag_1.LaBaG; } });
6
6
  const modes_1 = require("./modes");
7
- Object.defineProperty(exports, "modeList", { enumerable: true, get: function () { return modes_1.modeList; } });
7
+ Object.defineProperty(exports, "modes", { enumerable: true, get: function () { return modes_1.modes; } });
8
8
  const mode_1 = require("./mode");
9
9
  Object.defineProperty(exports, "Mode", { enumerable: true, get: function () { return mode_1.Mode; } });
10
10
  const pattern_1 = require("./pattern");
@@ -15,7 +15,7 @@ const recordChecker_1 = require("./recordChecker");
15
15
  Object.defineProperty(exports, "RecordChecker", { enumerable: true, get: function () { return recordChecker_1.RecordChecker; } });
16
16
  const labag = new labag_1.LaBaG();
17
17
  exports.labag = labag;
18
- modes_1.modeList.forEach((mode) => {
18
+ modes_1.modes.forEach((mode) => {
19
19
  labag.addMode(mode);
20
20
  });
21
21
  const recorder = new recorder_1.Recorder(labag);
package/dist/labag.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Mode } from "./mode";
2
- import { ModeName } from "./modes";
3
- import { Pattern, LaBaGEvent } from "./types";
2
+ import { Pattern, LaBaGEvent, ModeName } from "./types";
4
3
  /**
5
4
  * 拉霸遊戲的主要類別。
6
5
  */
@@ -20,13 +19,10 @@ export declare class LaBaG {
20
19
  /** 當前轉出的圖案組合 */
21
20
  patterns: [Pattern | null, Pattern | null, Pattern | null];
22
21
  /** 遊戲模式列表 */
23
- modes: Mode<any>[];
22
+ modes: Mode<Record<string, any>>[];
24
23
  /** 事件監聽器列表 */
25
24
  eventListeners: Record<LaBaGEvent, ((game: LaBaG) => void)[]>;
26
- /**
27
- * 初始化拉霸遊戲。
28
- * @param times - 總遊玩次數,預設為 30。
29
- */
25
+ __defaultMode__: Mode<{}, "normal">;
30
26
  constructor(times?: number);
31
27
  /**
32
28
  * 觸發指定事件。
@@ -35,54 +31,69 @@ export declare class LaBaG {
35
31
  private emit;
36
32
  /**
37
33
  * 新增事件監聽器。
38
- * @param event - 事件名稱。
39
- * @param listener - 監聽器函式。
34
+ * @param event - 要監聽的事件名稱。
35
+ * @param listener - 事件觸發時要執行的函式。
36
+ * @remarks 可以為同一事件添加多個監聽器,這些監聽器將按照添加的順序依次執行。
37
+ * @example
38
+ * game.addEventListener("gameStart", (game) => {
39
+ * console.log("遊戲開始了!");
40
+ * });
41
+ * game.addEventListener("roundEnd", (game) => {
42
+ * console.log("一輪結束了!");
43
+ * });
40
44
  */
41
45
  addEventListener(event: LaBaGEvent, callbackFn: (game: LaBaG) => void): void;
42
46
  /**
43
47
  * 移除事件監聽器。
44
- * @param event - 事件名稱。
45
- * @param listener - 監聽器函式。
48
+ * @param event - 要移除監聽器的事件名稱。
49
+ * @param listener - 要移除的監聽器函式。
50
+ * @remarks 這將從指定事件的監聽器列表中移除第一個匹配的函式。
51
+ * @example
52
+ * const onGameStart = (game) => {
53
+ * console.log("遊戲開始了!");
54
+ * };
55
+ * game.addEventListener("gameStart", onGameStart);
56
+ * // 之後如果想要移除這個監聽器:
57
+ * game.removeEventListener("gameStart", onGameStart);
46
58
  */
47
59
  removeEventListener(event: LaBaGEvent, callbackFn: (game: LaBaG) => void): void;
48
60
  /**
49
61
  * 新增遊戲模式。
50
- * @param mode - 要新增的模式。
62
+ * @param mode - 要新增的遊戲模式實例。
63
+ * @remarks 這將把指定的模式添加到遊戲的模式列表中,並自動註冊該模式定義的事件監聽器。
64
+ * @example
65
+ * const myMode = new Mode({
66
+ * active: false,
67
+ * name: "myMode",
68
+ * rates: {
69
+ * gss: 10,
70
+ * hhh: 20,
71
+ * hentai: 30,
72
+ * handson: 20,
73
+ * kachu: 10,
74
+ * rrr: 10,
75
+ * },
76
+ * });
77
+ * game.addMode(myMode);
51
78
  */
52
79
  addMode(mode: Mode<any>): void;
53
- /**
54
- * 檢查遊戲是否正在進行中(未達次數上限)。
55
- * @returns 如果遊戲仍在進行中則返回 true,否則返回 false。
56
- */
57
- isRunning(): boolean;
58
80
  /**
59
81
  * 取得目前遊戲的相關設定
60
82
  */
61
83
  getCurrentConfig(): {
62
- modes: Mode<any>[];
84
+ modes: Mode<Record<string, any>, string>[];
63
85
  ranges: {
64
86
  threshold: number;
65
87
  pattern: Pattern;
66
88
  }[];
67
89
  };
68
- /**
69
- * 初始化遊戲狀態。
70
- */
71
90
  init(): void;
72
- /**
73
- * 新的一小輪開始。
74
- */
75
- private roundStart;
76
- /**
77
- * 轉動拉霸機,產生隨機圖案。
78
- */
79
- private rollSlots;
80
- /**
81
- * 計算分數。
82
- */
83
- private calculateScore;
84
- private roundEnd;
85
- private gameOver;
91
+ roundStart(): void;
92
+ rollSlots(): void;
93
+ calculateScore(): void;
94
+ roundEnd(): void;
95
+ gameOver(): void;
86
96
  play(): void;
87
- getMode(modeName: ModeName): Mode | undefined;
97
+ getModes(name: ModeName): Mode<Record<string, any>, string>[];
98
+ get isRunning(): boolean;
88
99
  }
package/dist/labag.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LaBaG = void 0;
4
+ const mode_1 = require("./mode");
4
5
  const pattern_1 = require("./pattern");
5
6
  const randInt_1 = require("./utils/randInt");
6
7
  /**
@@ -25,10 +26,7 @@ class LaBaG {
25
26
  modes;
26
27
  /** 事件監聽器列表 */
27
28
  eventListeners;
28
- /**
29
- * 初始化拉霸遊戲。
30
- * @param times - 總遊玩次數,預設為 30。
31
- */
29
+ __defaultMode__;
32
30
  constructor(times = 30) {
33
31
  this.times = times;
34
32
  this.played = 0;
@@ -46,6 +44,90 @@ class LaBaG {
46
44
  rollSlots: [],
47
45
  calculateScore: [],
48
46
  };
47
+ this.__defaultMode__ = new mode_1.Mode({
48
+ active: true,
49
+ name: "normal",
50
+ rates: {
51
+ gss: 36,
52
+ hhh: 24,
53
+ hentai: 17,
54
+ handson: 12,
55
+ kachu: 8,
56
+ rrr: 3,
57
+ },
58
+ eventListener: {
59
+ gameStart: (game) => {
60
+ game.played = 0;
61
+ game.rounds = 0;
62
+ game.score = 0;
63
+ game.marginScore = 0;
64
+ game.randNums = [];
65
+ game.patterns = [null, null, null];
66
+ },
67
+ roundStart: (game) => {
68
+ game.played += 1;
69
+ game.rounds += 1;
70
+ game.marginScore = 0;
71
+ },
72
+ rollSlots: (game) => {
73
+ const { ranges } = game.getCurrentConfig();
74
+ const rangesAcc = ranges.length > 0 ? ranges[ranges.length - 1].threshold : 0;
75
+ // 產生 3 個隨機數字並直接尋找對應圖案
76
+ for (let i = 0; i < 3; i++) {
77
+ const num = (0, randInt_1.randInt)(1, rangesAcc);
78
+ game.randNums[i] = num;
79
+ let matchedPattern = null;
80
+ for (let j = 0; j < ranges.length; j++) {
81
+ if (num <= ranges[j].threshold) {
82
+ matchedPattern = ranges[j].pattern;
83
+ break;
84
+ }
85
+ }
86
+ game.patterns[i] = matchedPattern;
87
+ }
88
+ },
89
+ calculateScore: (game) => {
90
+ const [p1, p2, p3] = game.patterns;
91
+ if (!p1 || !p2 || !p3) {
92
+ game.marginScore = 0;
93
+ return;
94
+ }
95
+ if (p1.name === p2.name && p2.name === p3.name) {
96
+ // 三個圖案相同
97
+ this.marginScore += p1.scores[0];
98
+ }
99
+ else if (p1.name === p2.name ||
100
+ p2.name === p3.name ||
101
+ p1.name === p3.name) {
102
+ // 兩個圖案相同
103
+ if (p1.name === p2.name) {
104
+ this.marginScore += p1.scores[1];
105
+ this.marginScore += p3.scores[2];
106
+ }
107
+ else if (p2.name === p3.name) {
108
+ this.marginScore += p2.scores[1];
109
+ this.marginScore += p1.scores[2];
110
+ }
111
+ else {
112
+ this.marginScore += p1.scores[1];
113
+ this.marginScore += p2.scores[2];
114
+ }
115
+ this.marginScore = Math.round(this.marginScore / 1.4);
116
+ }
117
+ else {
118
+ // 三個圖案皆不同
119
+ this.marginScore += p1.scores[2];
120
+ this.marginScore += p2.scores[2];
121
+ this.marginScore += p3.scores[2];
122
+ this.marginScore = Math.round(this.marginScore / 3);
123
+ }
124
+ },
125
+ roundEnd: (game) => {
126
+ game.score += game.marginScore;
127
+ },
128
+ },
129
+ });
130
+ this.addMode(this.__defaultMode__);
49
131
  }
50
132
  /**
51
133
  * 觸發指定事件。
@@ -59,26 +141,58 @@ class LaBaG {
59
141
  }
60
142
  /**
61
143
  * 新增事件監聽器。
62
- * @param event - 事件名稱。
63
- * @param listener - 監聽器函式。
144
+ * @param event - 要監聽的事件名稱。
145
+ * @param listener - 事件觸發時要執行的函式。
146
+ * @remarks 可以為同一事件添加多個監聽器,這些監聽器將按照添加的順序依次執行。
147
+ * @example
148
+ * game.addEventListener("gameStart", (game) => {
149
+ * console.log("遊戲開始了!");
150
+ * });
151
+ * game.addEventListener("roundEnd", (game) => {
152
+ * console.log("一輪結束了!");
153
+ * });
64
154
  */
65
155
  addEventListener(event, callbackFn) {
66
156
  this.eventListeners[event].push(callbackFn);
67
157
  }
68
158
  /**
69
159
  * 移除事件監聽器。
70
- * @param event - 事件名稱。
71
- * @param listener - 監聽器函式。
160
+ * @param event - 要移除監聽器的事件名稱。
161
+ * @param listener - 要移除的監聽器函式。
162
+ * @remarks 這將從指定事件的監聽器列表中移除第一個匹配的函式。
163
+ * @example
164
+ * const onGameStart = (game) => {
165
+ * console.log("遊戲開始了!");
166
+ * };
167
+ * game.addEventListener("gameStart", onGameStart);
168
+ * // 之後如果想要移除這個監聽器:
169
+ * game.removeEventListener("gameStart", onGameStart);
72
170
  */
73
171
  removeEventListener(event, callbackFn) {
74
- const index = this.eventListeners[event].indexOf(callbackFn);
172
+ const listeners = this.eventListeners[event];
173
+ const index = listeners.indexOf(callbackFn);
75
174
  if (index !== -1) {
76
- this.eventListeners[event].splice(index, 1);
175
+ listeners.splice(index, 1);
77
176
  }
78
177
  }
79
178
  /**
80
179
  * 新增遊戲模式。
81
- * @param mode - 要新增的模式。
180
+ * @param mode - 要新增的遊戲模式實例。
181
+ * @remarks 這將把指定的模式添加到遊戲的模式列表中,並自動註冊該模式定義的事件監聽器。
182
+ * @example
183
+ * const myMode = new Mode({
184
+ * active: false,
185
+ * name: "myMode",
186
+ * rates: {
187
+ * gss: 10,
188
+ * hhh: 20,
189
+ * hentai: 30,
190
+ * handson: 20,
191
+ * kachu: 10,
192
+ * rrr: 10,
193
+ * },
194
+ * });
195
+ * game.addMode(myMode);
82
196
  */
83
197
  addMode(mode) {
84
198
  this.modes.push(mode);
@@ -89,13 +203,6 @@ class LaBaG {
89
203
  }
90
204
  });
91
205
  }
92
- /**
93
- * 檢查遊戲是否正在進行中(未達次數上限)。
94
- * @returns 如果遊戲仍在進行中則返回 true,否則返回 false。
95
- */
96
- isRunning() {
97
- return this.played < this.times;
98
- }
99
206
  /**
100
207
  * 取得目前遊戲的相關設定
101
208
  */
@@ -116,7 +223,8 @@ class LaBaG {
116
223
  for (let i = 0; i < activeModes.length; i++) {
117
224
  const mode = activeModes[i];
118
225
  for (const patternName in mode.rates) {
119
- combinedRates[patternName] += mode.rates[patternName];
226
+ combinedRates[patternName] +=
227
+ mode.rates[patternName];
120
228
  }
121
229
  }
122
230
  // 預先計算合併後的區間
@@ -131,108 +239,41 @@ class LaBaG {
131
239
  }
132
240
  return { modes: activeModes, ranges };
133
241
  }
134
- /**
135
- * 初始化遊戲狀態。
136
- */
137
242
  init() {
138
- this.played = 0;
139
- this.score = 0;
140
- this.marginScore = 0;
141
- this.randNums = [];
142
- this.patterns = [null, null, null];
143
- this.rounds = 0;
144
243
  this.emit("gameStart");
145
244
  }
146
- /**
147
- * 新的一小輪開始。
148
- */
149
245
  roundStart() {
150
- this.played += 1;
151
- this.rounds += 1;
152
- this.marginScore = 0;
153
246
  this.emit("roundStart");
154
247
  }
155
- /**
156
- * 轉動拉霸機,產生隨機圖案。
157
- */
158
248
  rollSlots() {
159
- const { ranges } = this.getCurrentConfig();
160
- const rangesAcc = ranges.length > 0 ? ranges[ranges.length - 1].threshold : 0;
161
- // 產生 3 個隨機數字並直接尋找對應圖案
162
- for (let i = 0; i < 3; i++) {
163
- const num = (0, randInt_1.randInt)(1, rangesAcc);
164
- this.randNums[i] = num;
165
- let matchedPattern = null;
166
- for (let j = 0; j < ranges.length; j++) {
167
- if (num <= ranges[j].threshold) {
168
- matchedPattern = ranges[j].pattern;
169
- break;
170
- }
171
- }
172
- this.patterns[i] = matchedPattern;
173
- }
174
249
  this.emit("rollSlots");
175
250
  }
176
- /**
177
- * 計算分數。
178
- */
179
251
  calculateScore() {
180
- const [p1, p2, p3] = this.patterns;
181
- if (!p1 || !p2 || !p3) {
182
- throw new Error("圖案未正確生成,無法計算分數。");
183
- }
184
- if (p1.name === p2.name && p2.name === p3.name) {
185
- // 三個圖案相同
186
- this.marginScore += p1.scores[0];
187
- }
188
- else if (p1.name === p2.name ||
189
- p2.name === p3.name ||
190
- p1.name === p3.name) {
191
- // 兩個圖案相同
192
- if (p1.name === p2.name) {
193
- this.marginScore += p1.scores[1];
194
- this.marginScore += p3.scores[2];
195
- }
196
- else if (p2.name === p3.name) {
197
- this.marginScore += p2.scores[1];
198
- this.marginScore += p1.scores[2];
199
- }
200
- else {
201
- this.marginScore += p1.scores[1];
202
- this.marginScore += p2.scores[2];
203
- }
204
- this.marginScore = Math.round(this.marginScore / 1.4);
205
- }
206
- else {
207
- // 三個圖案皆不同
208
- this.marginScore += p1.scores[2];
209
- this.marginScore += p2.scores[2];
210
- this.marginScore += p3.scores[2];
211
- this.marginScore = Math.round(this.marginScore / 3);
212
- }
213
252
  this.emit("calculateScore");
214
253
  }
215
254
  roundEnd() {
216
- this.score += this.marginScore;
217
255
  this.emit("roundEnd");
218
256
  }
219
257
  gameOver() {
220
258
  this.emit("gameOver");
221
259
  }
222
260
  play() {
223
- if (!this.isRunning()) {
224
- throw new Error("遊戲次數已達上限,無法繼續遊玩。");
261
+ if (!this.isRunning) {
262
+ throw new Error("遊戲已結束,無法繼續遊玩。");
225
263
  }
226
264
  this.roundStart();
227
265
  this.rollSlots();
228
266
  this.calculateScore();
229
267
  this.roundEnd();
230
- if (!this.isRunning()) {
268
+ if (!this.isRunning) {
231
269
  this.gameOver();
232
270
  }
233
271
  }
234
- getMode(modeName) {
235
- return this.modes.find((mode) => mode.name === modeName);
272
+ getModes(name) {
273
+ return this.modes.filter((m) => m.name === name);
274
+ }
275
+ get isRunning() {
276
+ return this.played < this.times;
236
277
  }
237
278
  }
238
279
  exports.LaBaG = LaBaG;
package/dist/mode.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { LaBaG } from "./labag";
2
2
  import { LaBaGEvent, Pattern, PatternName } from "./types";
3
- interface ModeConfig<VariableType extends Record<string, any>> {
3
+ interface ModeConfig<VariableType extends Record<string, any>, N extends string = string> {
4
4
  active: boolean;
5
- name: string;
5
+ name: N;
6
6
  rates: Record<PatternName, number>;
7
7
  eventListener?: Partial<Record<LaBaGEvent, (game: LaBaG, mode: Mode<VariableType>) => void>>;
8
8
  variable?: VariableType;
@@ -10,11 +10,11 @@ interface ModeConfig<VariableType extends Record<string, any>> {
10
10
  /**
11
11
  * 代表遊戲的一種模式,包含機率設定和事件監聽器。
12
12
  */
13
- export declare class Mode<VariableType extends Record<string, any> = Record<string, any>> implements ModeConfig<VariableType> {
13
+ export declare class Mode<VariableType extends Record<string, any> = Record<string, any>, N extends string = string> implements ModeConfig<VariableType, N> {
14
14
  /** 模式是否啟用 */
15
15
  active: boolean;
16
16
  /** 模式名稱 */
17
- name: string;
17
+ name: N;
18
18
  /** 各圖案出現的機率 */
19
19
  rates: Record<PatternName, number>;
20
20
  ranges: {
@@ -27,12 +27,34 @@ export declare class Mode<VariableType extends Record<string, any> = Record<stri
27
27
  variable: VariableType;
28
28
  /** 機率總和 */
29
29
  /**
30
- * 建立一個新的模式。
31
- * @param active - 是否啟用此模式。
32
- * @param name - 模式名稱。
33
- * @param rates - 各圖案的機率設定。
34
- * @param eventListener - 事件監聽器。
30
+ * 建立一個新的遊戲模式。
31
+ * @param config 模式的設定,包括啟用狀態、名稱、機率、事件監聽器和專屬變數。
32
+ * @remarks 會根據提供的機率設定預先計算出對應的區間,以便在遊戲中快速查找圖案。
33
+ * @example
34
+ * const myMode = new Mode({
35
+ * active: false,
36
+ * name: "myMode",
37
+ * rates: {
38
+ * gss: 10,
39
+ * hhh: 20,
40
+ * hentai: 30,
41
+ * handson: 20,
42
+ * kachu: 10,
43
+ * rrr: 10,
44
+ * },
45
+ * eventListener: {
46
+ * gameStart: (game, mode) => {
47
+ * console.log("遊戲開始了!", mode.name);
48
+ * },
49
+ * roundEnd: (game, mode) => {
50
+ * console.log("一輪結束了!", mode.name);
51
+ * },
52
+ * },
53
+ * variable: {
54
+ * myCustomValue: 123,
55
+ * },
56
+ * });
35
57
  */
36
- constructor(active: boolean, name: string, rates: Record<PatternName, number>, eventListener?: Partial<Record<LaBaGEvent, (game: LaBaG, mode: Mode<VariableType>) => void>>, variable?: VariableType);
58
+ constructor(config: ModeConfig<VariableType, N>);
37
59
  }
38
60
  export {};
package/dist/mode.js CHANGED
@@ -20,13 +20,36 @@ class Mode {
20
20
  variable;
21
21
  /** 機率總和 */
22
22
  /**
23
- * 建立一個新的模式。
24
- * @param active - 是否啟用此模式。
25
- * @param name - 模式名稱。
26
- * @param rates - 各圖案的機率設定。
27
- * @param eventListener - 事件監聽器。
23
+ * 建立一個新的遊戲模式。
24
+ * @param config 模式的設定,包括啟用狀態、名稱、機率、事件監聽器和專屬變數。
25
+ * @remarks 會根據提供的機率設定預先計算出對應的區間,以便在遊戲中快速查找圖案。
26
+ * @example
27
+ * const myMode = new Mode({
28
+ * active: false,
29
+ * name: "myMode",
30
+ * rates: {
31
+ * gss: 10,
32
+ * hhh: 20,
33
+ * hentai: 30,
34
+ * handson: 20,
35
+ * kachu: 10,
36
+ * rrr: 10,
37
+ * },
38
+ * eventListener: {
39
+ * gameStart: (game, mode) => {
40
+ * console.log("遊戲開始了!", mode.name);
41
+ * },
42
+ * roundEnd: (game, mode) => {
43
+ * console.log("一輪結束了!", mode.name);
44
+ * },
45
+ * },
46
+ * variable: {
47
+ * myCustomValue: 123,
48
+ * },
49
+ * });
28
50
  */
29
- constructor(active, name, rates, eventListener, variable) {
51
+ constructor(config) {
52
+ const { active, name, rates, eventListener, variable } = config;
30
53
  this.active = active;
31
54
  this.name = name;
32
55
  this.rates = rates;
@@ -16,5 +16,5 @@ declare const _default: Mode<{
16
16
  bonusTimes: number;
17
17
  requiredBindPatternCount: number;
18
18
  mutiplier: number;
19
- }>;
19
+ }, "greenwei">;
20
20
  export default _default;