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

86 lines
2.8 KiB

import { RankDataManager } from '../../../manager/RankDataManager';
import { aiLog } from './AiLog';
/** 铲子策略类型(Rank.aiusechanzi 三档) */
export enum AiShovelPolicyType {
/** 类型 1:随机可铲格 */
Type1 = 1,
/** 类型 2:逐步扩张 */
Type2 = 2,
/** 类型 3:贴路 */
Type3 = 3,
}
/** 普通字策略类型(Rank.aiusetext 两档) */
export enum AiTextPolicyType {
/** 类型 1:等级优先 */
Type1 = 1,
/** 类型 2:单字冲级 */
Type2 = 2,
}
/** 开战时按对手段位权重抽样,整局固定 */
export interface AiBattlePersonality {
/** 本局铲子策略类型 */
readonly shovelPolicy: AiShovelPolicyType;
/** 本局普通字策略类型 */
readonly textPolicy: AiTextPolicyType;
}
/** 从 Rank.aiusechanzi / aiusetext 加权抽样整局策略 */
export class AiBattlePersonalityFactory {
/**
* 按对手段位配表抽样 personality。
* @param opponentRankId 对手段位 id
* @param seed 随机种子
*/
roll(opponentRankId: number, seed: number): AiBattlePersonality | null {
const rank = RankDataManager.getRankConfig(opponentRankId);
if (!rank) {
aiLog('[AiBattlePersonalityFactory] Rank missing', opponentRankId);
return null;
}
const shovel = this._pickType(rank.aiusechanzi, 3, seed, 1);
const text = this._pickType(rank.aiusetext, 2, seed ^ 0x85ebca6b, 1);
if (shovel == null || text == null) return null;
return {
shovelPolicy: shovel as AiShovelPolicyType,
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;
}
}