You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为rand_skill列表随机分配skill_points且总和固定,支持tag_list加权?

问题描述

需要将skill_points随机分配给rand_skill列表的元素,确保所有元素之和严格等于skill_points;同时要通过tag_list影响分配权重,让rand_skill中的指定元素更大概率获得较高点数。此前采用循环逐个给随机元素加1的方法,低效且粗糙,寻求更优实现方案。

现有roll_talents函数代码如下:

def roll_talents(skill_points, tag_list):
    talents = []
    # FIGHT
    talents[0] = 0 + get_attribute_mod(attributes[3]) + get_attribute_mod(attributes[4]) + rand_skill [0]
    talents[1] = 0 + get_attribute_mod(attributes[4]) + rand_skill [1]
    talents[2] = 0 + get_attribute_mod(attributes[3]) + rand_skill [2]
    talents[3] = 0 + get_attribute_mod(attributes[0]) + rand_skill [3]
    talents[4] = 0 + get_attribute_mod(attributes[5]) + rand_skill [4]
    talents[5] = 0 + rand_skill [5]
    # COMMUNIKATION
    talents[6] = 0 + get_attribute_mod(attributes[2]) + rand_skill [6]
    talents[7] = 0 + get_attribute_mod(attributes[3]) + rand_skill [7]
    talents[8] = 0 + get_attribute_mod(attributes[6]) + rand_skill [8]
    talents[9] = 0 + get_attribute_mod(attributes[1]) + rand_skill [9]
    # [...]
    return talents
解决方案

核心思路

采用加权多项式分布实现点数分配:先根据tag_list为目标技能设置更高权重,再基于权重随机分配skill_points,既保证总和恒定,又满足权重偏向需求。

方案1:基于Numpy的高效实现(推荐)

利用Numpy的multinomial函数,底层优化的算法能快速生成符合要求的整数分配结果,适合大点数场景。

  1. 生成加权权重
import numpy as np

def generate_skill_weights(skill_count, tag_list):
    # 初始化所有技能默认权重为1
    weights = np.ones(skill_count)
    # 为tag_list中的目标技能提升权重(这里设置为3倍,可按需调整)
    for skill_idx in tag_list:
        if 0 <= skill_idx < skill_count:
            weights[skill_idx] *= 3
    # 归一化权重为概率分布
    return weights / weights.sum()
  1. 分配技能点数
def allocate_skill_points(skill_points, skill_count, tag_list):
    weights = generate_skill_weights(skill_count, tag_list)
    # 生成总和为skill_points的随机分配数组
    rand_skill = np.random.multinomial(skill_points, weights)
    # 转为Python列表适配原有代码
    return rand_skill.tolist()
  1. 整合到原有函数
def roll_talents(skill_points, tag_list):
    # 确定技能总数,根据现有代码这里暂设为10,需与实际talents数量一致
    skill_count = 10
    rand_skill = allocate_skill_points(skill_points, skill_count, tag_list)
    
    talents = []
    # FIGHT模块
    talents.append(get_attribute_mod(attributes[3]) + get_attribute_mod(attributes[4]) + rand_skill[0])
    talents.append(get_attribute_mod(attributes[4]) + rand_skill[1])
    talents.append(get_attribute_mod(attributes[3]) + rand_skill[2])
    talents.append(get_attribute_mod(attributes[0]) + rand_skill[3])
    talents.append(get_attribute_mod(attributes[5]) + rand_skill[4])
    talents.append(rand_skill[5])
    # COMMUNIKATION模块
    talents.append(get_attribute_mod(attributes[2]) + rand_skill[6])
    talents.append(get_attribute_mod(attributes[3]) + rand_skill[7])
    talents.append(get_attribute_mod(attributes[6]) + rand_skill[8])
    talents.append(get_attribute_mod(attributes[1]) + rand_skill[9])
    # [...] 补充其他技能计算逻辑
    return talents

方案2:纯Python实现(无依赖)

如果无法引入Numpy,可使用标准库的random.choices实现,通过多次加权选择统计次数完成分配。

import random

def allocate_skill_points_pure_python(skill_points, skill_count, tag_list):
    # 初始化权重列表
    weights = [1] * skill_count
    # 为目标技能提升权重
    for skill_idx in tag_list:
        if 0 <= skill_idx < skill_count:
            weights[skill_idx] = 3  # 权重倍数可调整
    # 随机选择skill_points次技能索引,统计每个技能被选中的次数
    selections = random.choices(range(skill_count), weights=weights, k=skill_points)
    rand_skill = [selections.count(i) for i in range(skill_count)]
    return rand_skill

方案优势

  • 效率远高于逐个加1的循环方法,尤其是当skill_points数值较大时
  • 权重控制精准,标签指定的技能能稳定获得更高的点数分配概率
  • 天然保证所有元素之和严格等于skill_points,无需额外校验

内容的提问来源于stack exchange,提问作者aGuyCalledT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:09:58