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/runtime/AiBattlePersonality.ts

79 lines
2.6 KiB

import { RankDataManager } from '../../../manager/RankDataManager';
import { aiLog } from './AiLog';
/** 普通字策略类型(Rank.aiusetext 两档) */
export enum AiTextPolicyType {
/** 类型 1:等级优先 */
Type1 = 1,
/** 类型 2:单字冲级 */
Type2 = 2,
}
/** 开战时按对手段位权重抽样,整局固定 */
export interface AiBattlePersonality {
/** 本局普通字策略类型 */
readonly textPolicy: AiTextPolicyType;
}
/** 从 Rank.aiusetext 加权抽样整局策略 */
export class AiBattlePersonalityFactory {
/**
* 按对手段位配表抽样 personality。
* @param opponentRankId 对手段位 id
* @param seed 随机种子
*/
roll(opponentRankId: number, seed: number): AiBattlePersonality | null {
const rank = RankDataManager.getRankConfig(opponentRankId);
if (!rank) {
console.warn('[AiBattlePersonalityFactory] Rank missing,使用默认策略', opponentRankId);
return {
textPolicy: AiTextPolicyType.Type1,
};
}
const text = this._pickType(rank.aiusetext, 2, seed ^ 0x85ebca6b, 1);
if (text == null) {
console.warn('[AiBattlePersonalityFactory] 权重无效,使用默认策略', opponentRankId);
return {
textPolicy: AiTextPolicyType.Type1,
};
}
return {
textPolicy: text as AiTextPolicyType,
};
}
/**
* 加权抽类型(返回 1-based 类型号)。
* @param weights 权重数组
* @param expectLen 期望长度
* @param seed 种子
* @param typeBase 起始类型号
*/
private _pickType(weights: number[] | undefined, expectLen: number, seed: number, typeBase: number): number | null {
if (!weights || weights.length !== expectLen) {
aiLog('[AiBattlePersonalityFactory] weight length invalid', expectLen);
return null;
}
const w: number[] = [];
let total = 0;
for (let i = 0; i < expectLen; i++) {
const v = Math.max(0, Math.floor(Number(weights[i]) || 0));
w.push(v);
total += v;
}
if (total <= 0) {
aiLog('[AiBattlePersonalityFactory] weight total <= 0');
return null;
}
let x = (Math.floor(Number(seed) || 0) >>> 0) || 1;
x ^= x << 13;
x ^= x >>> 17;
x ^= x << 5;
let roll = ((x >>> 0) / 4294967296) * total;
for (let i = 0; i < expectLen; i++) {
roll -= w[i];
if (roll < 0) return typeBase + i;
}
return typeBase + expectLen - 1;
}
}