You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/script/battle/ai/match/AiBattlebuffPicker.ts

73 lines
2.9 KiB

3 weeks ago
import { TableNames } from '../../../game/ConfigTableData';
import { aiLog } from '../runtime/AiLog';
import { BattleBuffSlotType } from '../../../manager/battleBuff/BattleBuffTypes';
/** 局内 AI 可抽 functiontype 下限(新表 1~16;排除 type=3 局外即时) */
const AI_BUFF_FT_MIN = 1;
3 weeks ago
/** 局内 AI 可抽 functiontype 上限 */
const AI_BUFF_FT_MAX = 16;
3 weeks ago
/** Battlebuff 加权不重复抽取 */
3 weeks ago
export class AiBattlebuffPicker {
/**
* 按 type 与 weight 加权抽取不重复 buff id。
* 仅 `type=1|2` 且 `functiontype∈[1,16]`;**排除 type=3**。
* 新表无主动行时 `buffType=1` 返回 []。
3 weeks ago
* @param buffType 1=主动,2=被动
* @param count 目标个数
* @param seed 随机种子
*/
pick(buffType: 1 | 2, count: number, seed: number): number[] {
const need = Math.max(0, Math.floor(Number(count) || 0));
if (need <= 0) return [];
const list = gg.data.table.getTableList<ITableBattlebuff>(TableNames.Battlebuff) ?? [];
const ids: number[] = [];
const weights: number[] = [];
for (let i = 0; i < list.length; i++) {
const row = list[i];
const slotType = Math.floor(Number(row.type) || 0);
if (slotType === BattleBuffSlotType.Auto) continue;
if (slotType !== buffType) continue;
const ft = Math.floor(Number(row.functiontype) || 0);
if (ft < AI_BUFF_FT_MIN || ft > AI_BUFF_FT_MAX) continue;
const w = Math.max(0, Math.floor(Number(row.weight) || 0));
if (w <= 0) continue;
const id = Math.floor(Number(row.id) || 0);
if (id <= 0) continue;
ids.push(id);
weights.push(w);
}
if (ids.length < need) {
aiLog(`[AiBattlebuffPicker] candidate shortage buffType=${buffType} need=${need} have=${ids.length}`);
return [];
}
const picked: number[] = [];
let rng = (Math.floor(Number(seed) || 0) >>> 0) || 1;
for (let n = 0; n < need; n++) {
let total = 0;
for (let i = 0; i < weights.length; i++) total += weights[i];
if (total <= 0) {
aiLog(`[AiBattlebuffPicker] remaining weight 0 buffType=${buffType} picked=${picked.join(',')}`);
return [];
}
rng = (rng * 1664525 + 1013904223) >>> 0;
let roll = (rng / 4294967296) * total;
let choose = -1;
for (let i = 0; i < weights.length; i++) {
roll -= weights[i];
if (roll < 0) {
choose = i;
break;
}
}
if (choose < 0) choose = weights.length - 1;
picked.push(ids[choose]);
ids.splice(choose, 1);
weights.splice(choose, 1);
}
return picked;
}
}