|
|

楼主 |
发表于 2026-9-3 19:21| 字数 71,386
|
显示全部楼层
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <windows.h>
// ========== 常量定义 ==========
// 基本数组大小限制
#define MAX_IDENTITIES 300 // 最大身份数量
#define MAX_NAME_LEN 16 // 身份名称最大长度
#define MAX_MOTHER_LEN 16 // 母身份名称最大长度
#define MIN_PLAYERS 9 // 最小游戏人数
#define MAX_PLAYERS 18 // 最大游戏人数
#define POOL_SIZE 200 // 身份池最大容量
// 循环尝试次数限制
#define MAX_TEST 1000 // 最大尝试次数(用于各种循环)
#define MAX_MAGNIFICATION_TEST 500 // 最大倍率调整尝试次数
#define MAX_CONFIG_GENERATIONS 5000 // 最大配置生成尝试次数
#define MAX_CONFIG_ATTEMPTS 50 // 生成单个配置时的最大尝试次数
#define MAX_ADJUST_LOOP 20 // 调整循环最大次数
#define MAX_POOL_BUILD_ATTEMPTS 20 // 构建身份池的最大尝试次数
// 目标配置数量(非测试模式下生成多少个不重复的配置)
#define TARGET_CONFIG_COUNT 3
// 长老狼固定算分(用于比例调整)
#define ELDER_WOLF_SCORE 8.0
// 测试模式常数
#define TEST_COUNT 10000 // 测试模式每种模式模拟次数
// 平衡范围常数(根据不同人数预设的倍率区间)
// 注意:这些数值是设计好的,不应随意更改
#define BALANCE_MIN_9 1.40
#define BALANCE_MAX_9 1.50
#define BALANCE_MIN_10 1.35
#define BALANCE_MAX_10 1.45
#define BALANCE_MIN_11 1.35
#define BALANCE_MAX_11 1.45
#define BALANCE_MIN_12 1.30
#define BALANCE_MAX_12 1.40
#define BALANCE_MIN_13 1.30
#define BALANCE_MAX_13 1.40
#define BALANCE_MIN_14 1.30
#define BALANCE_MAX_14 1.40
#define BALANCE_MIN_15 1.25
#define BALANCE_MAX_15 1.35
#define BALANCE_MIN_16 1.25
#define BALANCE_MAX_16 1.35
#define BALANCE_MIN_17 1.25
#define BALANCE_MAX_17 1.35
#define BALANCE_MIN_18 1.25
#define BALANCE_MAX_18 1.35
// 原始分类编号(用于身份定义中的 original_category)
#define ORIG_CAT_APPRAISAL 0 // 验人系
#define ORIG_CAT_WITCH 1 // 女巫系
#define ORIG_CAT_OTHER 2 // 其他神职
#define ORIG_CAT_INDEPENDENT 3 // 独立阵营
#define ORIG_CAT_INDEFINITE 4 // 不定阵营
#define ORIG_CAT_WEREWOLF 5 // 狼人
// ========== 枚举定义 ==========
// 游戏模式
typedef enum {
MODE_LIMITED_POOL = 0, // 限池模式
MODE_COMPREHENSIVE, // 综合模式
MODE_TEST // 测试模式
} GameMode;
// 阵营枚举
typedef enum {
FACTION_VILLAGER = 0, // 村民阵营
FACTION_WEREWOLF, // 狼人阵营
FACTION_INDEPENDENT, // 独立阵营
FACTION_INDEFINITE // 不定阵营
} Faction;
// 身份类别枚举(用于新的强神/弱神分类)
typedef enum {
CATEGORY_WEREWOLF = 0, // 狼人
CATEGORY_STRONG_CLERGY, // 强神
CATEGORY_WEAK_CLERGY, // 弱神
CATEGORY_INDEPENDENT, // 独立
CATEGORY_INDEFINITE // 不定
} Category;
// ========== 数据结构定义 ==========
// 身份数据结构
typedef struct {
int id; // 身份ID,对应identities数组下标
char name[MAX_NAME_LEN]; // 身份名称
Faction faction; // 所属阵营
Category category; // 所属类别(强神/弱神/狼人/独立/不定)
int original_category; // 原始分类:0=验人系,1=女巫系,2=其他神职,3=独立,4=不定,5=狼人
double base_score; // 基础算分(本版本中直接作为算分,不受人数影响)
double score_per_player; // 每增加一人增加的算分(本版本废弃,始终为0)
int min_players; // 最少游戏人数(该身份至少需要多少人才会出现)
char mother_name[MAX_MOTHER_LEN]; // 母身份名称(如果有)
int mother_id; // 母身份ID(由名称解析得到)
int has_mother; // 是否有母身份
int is_in_group; // 是否为群内狼人(1=是,0=否)
double weight; // 权重(用于限池模式的权重随机抽取)
} Identity;
// 配置结果结构(记录各类别数量)
typedef struct {
int werewolf_count; // 狼人数量
int strong_clergy_count; // 强神数量
int weak_clergy_count; // 弱神数量
int other_count; // 其他数量(独立+不定)
int appraisal_count; // 验人系数量(属于强神或弱神的一部分,单独记录)
int total_count; // 总人数
} ConfigResult;
// 抽取结果结构(记录具体选中的身份指针及计数)
typedef struct {
Identity* selected_identities[MAX_PLAYERS]; // 选择的身份指针数组
int identity_counts[MAX_IDENTITIES]; // 每个身份被选中的次数(用于检查重复)
int selected_count; // 已选择身份数量
} SelectionResult;
// 倍率检查结果结构
typedef struct {
double magnification; // 当前倍率 = 非狼人阵营算分之和 / 狼人阵营算分之和
double non_werewolf_score_sum; // 非狼人阵营算分之和
double werewolf_score_sum; // 狼人阵营算分之和
int is_balanced; // 是否在平衡范围内
} MagnificationCheck;
// 测试模式统计结构
typedef struct {
int total_simulations; // 总模拟次数
int successful_generations; // 成功生成配置的次数
long long identity_appearances[MAX_IDENTITIES]; // 各身份出现次数
} TestModeStats;
// 临时结构,用于测试结果输出排序
typedef struct {
char name[MAX_NAME_LEN];
int cat; // 排序用的类别索引
int original_category; // 原始分类
Faction faction; // 阵营
double rate; // 出场率或入池概率
} StatItem;
// ========== 全局变量 ==========
Identity identities[MAX_IDENTITIES]; // 所有可用的身份数据
TestModeStats test_stats; // 测试模式统计
int total_identities = 0; // 实际身份数量
int game_players = 0; // 当前游戏人数
GameMode current_mode = MODE_COMPREHENSIVE; // 当前游戏模式,默认为综合模式
// 用于输出的字符串映射
const char* faction_names[] = {"村民阵营", "狼人阵营", "独立阵营", "不定阵营"};
const char* category_names[] = {"狼人", "强神", "弱神", "独立", "不定"};
const char* mode_names[] = {"限池模式", "综合模式", "测试模式"};
// ========== 函数声明(按功能分组)=========
/* ----- 身份数据初始化与辅助 ----- */
void initialize_identities();
void add_identity(const char* name, Faction faction, int original_category, double base_score,
double score_per_player, int min_players, const char* mother_name, int is_in_group, double weight);
int find_identity_by_name(const char* name);
void process_mother_relationships();
double calculate_score(Identity* id, int n);
/* ----- 配置生成与数量规划 ----- */
ConfigResult generate_config(int n);
void get_balance_range(GameMode mode, int n, double* min_balance, double* max_balance);
/* ----- 身份抽取 ----- */
Identity* select_random_identity_from_pool(int* pool, int pool_size, int* exclude_ids, int exclude_count);
SelectionResult select_identities(ConfigResult* config);
SelectionResult select_identities_from_pool(ConfigResult* config, Identity* pool[], int pool_size);
/* ----- 合法性检查 ----- */
int validate_selection(SelectionResult* selection, ConfigResult config);
/* ----- 调整函数 ----- */
MagnificationCheck calculate_magnification(SelectionResult selection, ConfigResult config, int n);
int check_magnification_balance(MagnificationCheck check, int n);
int adjust_magnification(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[], int pool_size);
int adjust_elder_wolf(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[], int pool_size);
int adjust_mother_relationships(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[],
int pool_size);
/* ----- 身份池构建 ----- */
int build_identity_pool(Identity* pool[]);
int adjust_pool_for_mother_relationships(Identity* pool[], int pool_size);
/* ----- 生成单个配置 ----- */
int generate_single_configuration(int n, SelectionResult* result, ConfigResult* config_result);
int generate_single_configuration_from_pool(int n, SelectionResult* result, ConfigResult* config_result,
Identity* pool[], int pool_size);
/* ----- 输出与显示 ----- */
int compare_identities_for_display(const void* a, const void* b);
int compare_stats_items(const void* a, const void* b);
void print_identity_pool(Identity* pool[], int pool_size);
void print_configuration_formatted(SelectionResult sel, ConfigResult config, int config_num, int n);
/* ----- 各模式运行函数 ----- */
void run_limited_pool_mode();
void run_comprehensive_mode();
void run_test_mode();
void initialize_test_stats();
void update_test_stats(SelectionResult selection);
void print_test_results();
// ========== 身份数据初始化函数实现 ==========
/**
* 初始化所有身份数据,调用add_identity添加每个身份
* 注意:此函数依赖全局变量game_players,但本版本中所有身份无人数相关算分调整。
*/
void initialize_identities() {
total_identities = 0;
// ========== 强神 ==========
// 验人系强神 (original_category = 0)
add_identity("纯白之女", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 9.0, 0.0, 9, "", 0, 2.0);
add_identity("巡夜人", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("教宗", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("通灵师", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("预言家", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 6.0, 0.0, 9, "", 0, 43.0);
// 女巫系强神 (original_category = 1)
add_identity("玄武", FACTION_VILLAGER, ORIG_CAT_WITCH, 10.0, 0.0, 9, "", 0, 1.0);
add_identity("炼金魔女", FACTION_VILLAGER, ORIG_CAT_WITCH, 9.0, 0.0, 9, "", 0, 2.0);
add_identity("枢", FACTION_VILLAGER, ORIG_CAT_WITCH, 9.0, 0.0, 9, "", 0, 1.0);
add_identity("天使长", FACTION_VILLAGER, ORIG_CAT_WITCH, 9.0, 0.0, 9, "", 0, 1.0);
add_identity("魂灵使徒", FACTION_VILLAGER, ORIG_CAT_WITCH, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("女巫", FACTION_VILLAGER, ORIG_CAT_WITCH, 8.0, 0.0, 9, "", 0, 40.0);
add_identity("灵鹿", FACTION_VILLAGER, ORIG_CAT_WITCH, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("亡灵法师", FACTION_VILLAGER, ORIG_CAT_WITCH, 7.0, 0.0, 9, "", 0, 1.0);
// 其他神职强神 (original_category = 2)
add_identity("火神", FACTION_VILLAGER, ORIG_CAT_OTHER, 10.0, 0.0, 9, "", 0, 1.0);
add_identity("舞者", FACTION_VILLAGER, ORIG_CAT_OTHER, 10.0, 0.0, 9, "", 0, 1.0);
add_identity("企鹅", FACTION_VILLAGER, ORIG_CAT_OTHER, 9.0, 0.0, 9, "", 0, 1.0);
add_identity("仲裁官", FACTION_VILLAGER, ORIG_CAT_OTHER, 9.0, 0.0, 9, "阴谋家", 0, 1.0);
add_identity("水手", FACTION_VILLAGER, ORIG_CAT_OTHER, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("特工", FACTION_VILLAGER, ORIG_CAT_OTHER, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("斩魔大帝", FACTION_VILLAGER, ORIG_CAT_OTHER, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("道士", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("皇城空卫", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("流光伯爵", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "蚀日侍女", 0, 2.0);
add_identity("龙魂", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("魔偶师", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("挽风", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("小木匠", FACTION_VILLAGER, ORIG_CAT_OTHER, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("白昼学者", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "寂夜导师", 0, 2.0);
add_identity("布恐师", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("哈利波特", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("科技先驱", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("猎魔人", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 2.0);
add_identity("灵境行者", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("梦林", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("判官", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("启明星使", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("医生", FACTION_VILLAGER, ORIG_CAT_OTHER, 6.0, 0.0, 9, "", 0, 1.0);
// ========== 弱神 ==========
// 验人系弱神 (original_category = 0)
add_identity("迪拉熊", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("解谜者", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("循声检事", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("狐狸", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("熊", FACTION_VILLAGER, ORIG_CAT_APPRAISAL, 4.0, 0.0, 9, "", 0, 2.0);
// 其他神职弱神 (original_category = 2)
add_identity("伏兵", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("领袖", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("魔术师", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 2.0);
add_identity("骑士", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 15.0);
add_identity("摄梦人", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 9.0);
add_identity("守卫", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 21.0);
add_identity("修女", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("弈圣", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("钟", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 1.0);
add_identity("子狐", FACTION_VILLAGER, ORIG_CAT_OTHER, 5.0, 0.0, 9, "", 0, 2.0);
add_identity("摆渡人", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("海象", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("河豚", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 3.0);
add_identity("黑商", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("潜行者", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("赏金猎人", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("太阳", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("线人", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("隐者", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("侦探", FACTION_VILLAGER, ORIG_CAT_OTHER, 4.0, 0.0, 9, "", 0, 1.0);
add_identity("保险丝", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 1.0);
add_identity("定序王子", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 2.0);
add_identity("猎人", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 29.0);
add_identity("灵能", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 1.0);
add_identity("女王观战者", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 1.0); // 分数暂为3,后续根据模式调整
add_identity("乌鸦", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 4.0);
add_identity("锈剑骑士", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 1.0);
add_identity("灾星", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 0.3);
add_identity("长老", FACTION_VILLAGER, ORIG_CAT_OTHER, 3.0, 0.0, 9, "", 0, 1.0);
add_identity("白痴", FACTION_VILLAGER, ORIG_CAT_OTHER, 2.0, 0.0, 9, "", 0, 10.0);
add_identity("白猫", FACTION_VILLAGER, ORIG_CAT_OTHER, 2.0, 0.0, 9, "", 0, 1.0);
add_identity("法医", FACTION_VILLAGER, ORIG_CAT_OTHER, 2.0, 0.0, 9, "", 0, 0.3);
add_identity("克隆人", FACTION_VILLAGER, ORIG_CAT_OTHER, 1.0, 0.0, 9, "", 0, 1.0);
add_identity("月亮", FACTION_VILLAGER, ORIG_CAT_OTHER, 1.0, 0.0, 9, "", 0, 1.0);
// ========== 狼人 ==========
// 群内狼人 (is_in_group = 1)
add_identity("刺客鸭", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 10.0, 0.0, 9, "", 1, 1.0);
add_identity("黑武士", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 10.0, 0.0, 9, "", 1, 1.0);
add_identity("混沌之魔", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 10.0, 0.0, 9, "", 1, 2.0);
add_identity("白狼王", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 9.0, 0.0, 9, "", 1, 10.0);
add_identity("大野狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 9.0, 0.0, 9, "", 1, 1.0);
add_identity("吸血鬼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 9.0, 0.0, 9, "", 1, 1.0);
add_identity("赤狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 1.0);
add_identity("黑蝙蝠", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 1.0);
add_identity("混血猎手", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 1.0);
add_identity("教主", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 1.0);
add_identity("狼美人", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 7.0);
add_identity("血魔", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 2.0);
add_identity("血月使徒", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 2.0);
add_identity("幼狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 2.0);
add_identity("长老狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 1, 1.0);
add_identity("大尾巴狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 2.0);
add_identity("恶灵骑士", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 4.0);
add_identity("黑狼王", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 14.0);
add_identity("狼巫", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 3.0);
add_identity("夜翎", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 1.0);
add_identity("真理祭坛", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 1, 1.0);
add_identity("邪恶术士", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 6.0, 0.0, 9, "", 1, 1.0);
// 非群内狼人 (is_in_group = 0)
add_identity("大灰狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 9.0, 0.0, 9, "", 0, 1.0);
add_identity("蚀日侍女", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 9.0, 0.0, 9, "流光伯爵", 0, 2.0);
add_identity("刺客", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("噩梦之影", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 4.0);
add_identity("黑骑士", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("寂夜导师", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "白昼学者", 0, 2.0);
add_identity("军团", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("狼道君", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 1.0);
add_identity("狼鸦之爪", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "", 0, 3.0);
add_identity("阴谋家", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 8.0, 0.0, 9, "仲裁官", 0, 1.0);
add_identity("哈迪寂亚", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("蚀时狼妃", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 0, 4.0);
add_identity("邪恶赌怪", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 7.0, 0.0, 9, "", 0, 1.0);
add_identity("花蝴蝶", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 6.0, 0.0, 9, "", 0, 1.0);
add_identity("隐狼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 6.0, 0.0, 9, "", 0, 3.0);
add_identity("石像鬼", FACTION_WEREWOLF, ORIG_CAT_WEREWOLF, 5.0, 0.0, 9, "", 0, 3.0);
// ========== 独立阵营 ==========
add_identity("鬼魂新娘", FACTION_INDEPENDENT, ORIG_CAT_INDEPENDENT, -2.0, 0.0, 13, "", 0, 1.0);
add_identity("白眼狼", FACTION_INDEPENDENT, ORIG_CAT_INDEPENDENT, -3.0, 0.0, 9, "", 0, 1.0);
add_identity("吹笛者", FACTION_INDEPENDENT, ORIG_CAT_INDEPENDENT, -3.0, 0.0, 9, "", 0, 1.0);
add_identity("占星师", FACTION_INDEPENDENT, ORIG_CAT_INDEPENDENT, -3.0, 0.0, 9, "", 0, 1.0);
add_identity("妖狐", FACTION_INDEPENDENT, ORIG_CAT_INDEPENDENT, -4.0, 0.0, 9, "", 0, 1.0);
// ========== 不定阵营 ==========
add_identity("暗恋者", FACTION_INDEFINITE, ORIG_CAT_INDEFINITE, -2.0, 0.0, 9, "", 0, 1.0);
add_identity("混血儿", FACTION_INDEFINITE, ORIG_CAT_INDEFINITE, -2.0, 0.0, 9, "", 0, 1.0);
add_identity("丘比特", FACTION_INDEFINITE, ORIG_CAT_INDEFINITE, -2.0, 0.0, 13, "", 0, 6.0);
add_identity("复仇者", FACTION_INDEFINITE, ORIG_CAT_INDEFINITE, -4.0, 0.0, 9, "", 0, 1.0);
// 处理母身份关系
process_mother_relationships();
// 根据模式调整女王观战者的分数
for (int i = 0; i < total_identities; i++) {
if (strcmp(identities[i].name, "女王观战者") == 0) {
if (current_mode == MODE_LIMITED_POOL) {
identities[i].base_score = 2.0;
} else {
identities[i].base_score = 3.0;
}
break;
}
}
}
/**
* 添加一个身份到全局数组identities中
* @param name 身份名称
* @param faction 阵营
* @param original_category 原始分类(0-5)
* @param base_score 基础算分
* @param score_per_player 每增加一人增加的算分(本版本废弃)
* @param min_players 最少游戏人数
* @param mother_name 母身份名称(若无则传空字符串)
* @param is_in_group 是否为群内狼人(1是0否)
* @param weight 权重(用于限池模式)
*/
void add_identity(const char* name, Faction faction, int original_category,
double base_score, double score_per_player,
int min_players, const char* mother_name,
int is_in_group, double weight) {
Identity new_id;
new_id.id = total_identities;
strcpy(new_id.name, name);
new_id.faction = faction;
new_id.original_category = original_category;
new_id.base_score = base_score;
new_id.score_per_player = score_per_player;
new_id.min_players = min_players;
new_id.has_mother = (mother_name && strlen(mother_name) > 0);
if (new_id.has_mother) strcpy(new_id.mother_name, mother_name);
else new_id.mother_name[0] = '\0';
new_id.mother_id = -1;
new_id.is_in_group = is_in_group;
new_id.weight = weight;
// 设置新类别(强神/弱神/狼人/独立/不定)
if (faction == FACTION_WEREWOLF) new_id.category = CATEGORY_WEREWOLF;
else if (faction == FACTION_INDEPENDENT) new_id.category = CATEGORY_INDEPENDENT;
else if (faction == FACTION_INDEFINITE) new_id.category = CATEGORY_INDEFINITE;
else {
// 村民阵营:根据原始分类和算分判断强神/弱神
if (original_category == ORIG_CAT_WITCH) new_id.category = CATEGORY_STRONG_CLERGY;
else new_id.category = (base_score >= 5.5) ? CATEGORY_STRONG_CLERGY : CATEGORY_WEAK_CLERGY;
}
identities[total_identities++] = new_id;
}
/**
* 根据身份名称查找对应的ID
* @param name 要查找的身份名称
* @return 身份ID(如果找到),否则返回-1
*/
int find_identity_by_name(const char* name) {
for (int i = 0; i < total_identities; i++)
if (strcmp(identities[i].name, name) == 0) return i;
return -1;
}
/**
* 处理所有身份的母身份关系,填充mother_id字段
* 在身份初始化完成后调用
*/
void process_mother_relationships() {
for (int i = 0; i < total_identities; i++) {
if (identities[i].has_mother) {
identities[i].mother_id = find_identity_by_name(identities[i].mother_name);
if (identities[i].mother_id == -1) identities[i].has_mother = 0;
}
}
}
/**
* 计算某身份在n人局中的算分
* 本版本中算分仅等于base_score,忽略人数影响
* @param id 身份指针
* @param n 游戏人数(未使用)
* @return 算分值
*/
double calculate_score(Identity* id, int n) {
return id->base_score;
}
// ========== 生成配置 ==========
/**
* 根据游戏人数n生成各类别的数量配置
* 各人数有固定的基础数量,部分人数有随机微调
* @param n 游戏人数
* @return 配置结果结构体,若人数不支持则返回全0结构
*/
ConfigResult generate_config(int n) {
ConfigResult res = {0};
res.total_count = n;
if (n == 9) {
res.werewolf_count = 3;
res.strong_clergy_count = 3;
res.weak_clergy_count = 3;
res.other_count = 0;
res.appraisal_count = 1;
} else if (n == 10) {
res.werewolf_count = 3;
res.strong_clergy_count = 3;
res.weak_clergy_count = 3;
res.other_count = 1;
res.appraisal_count = 1;
} else if (n == 11) {
res.werewolf_count = 3;
res.strong_clergy_count = 3;
res.weak_clergy_count = 3;
res.other_count = 0;
// 随机决定增加狼人还是其他
if (rand() % 2 == 0) res.werewolf_count++;
else res.other_count++;
// 随机决定增加强神还是弱神
if (rand() % 2 == 0) res.strong_clergy_count++;
else res.weak_clergy_count++;
res.appraisal_count = 1;
} else if (n == 12) {
res.werewolf_count = 4;
res.strong_clergy_count = 4;
res.weak_clergy_count = 4;
res.other_count = 0;
res.appraisal_count = 1;
} else if (n == 13) {
res.werewolf_count = 4;
res.strong_clergy_count = 4;
res.weak_clergy_count = 4;
res.other_count = 1;
res.appraisal_count = 1;
} else if (n == 14) {
res.werewolf_count = 4;
res.strong_clergy_count = 4;
res.weak_clergy_count = 4;
res.other_count = 0;
if (rand() % 2 == 0) res.werewolf_count++;
else res.other_count++;
if (rand() % 2 == 0) res.strong_clergy_count++;
else res.weak_clergy_count++;
res.appraisal_count = 1;
} else if (n == 15) {
res.werewolf_count = 4;
res.strong_clergy_count = 4;
res.weak_clergy_count = 4;
res.other_count = 0;
// 随机打乱类别顺序,然后给前三个各加1
int categories[4] = {0,1,2,3}; // 0狼人,1强神,2弱神,3其他
for (int i = 0; i < 3; i++) {
int j = i + rand() % (4 - i);
int tmp = categories[i];
categories[i] = categories[j];
categories[j] = tmp;
}
for (int i = 0; i < 3; i++) {
if (categories[i] == 0) res.werewolf_count++;
else if (categories[i] == 1) res.strong_clergy_count++;
else if (categories[i] == 2) res.weak_clergy_count++;
else res.other_count++;
}
res.appraisal_count = 1;
} else if (n == 16) {
res.werewolf_count = 5;
res.strong_clergy_count = 5;
res.weak_clergy_count = 5;
res.other_count = 1;
// 验人系数量有5%概率为2
res.appraisal_count = (rand() % 100 < 5) ? 2 : 1;
} else if (n == 17) {
res.werewolf_count = 5;
res.strong_clergy_count = 5;
res.weak_clergy_count = 5;
res.other_count = 1;
// 随机选择一个类别增加1
int cat = rand() % 4;
if (cat == 0) res.werewolf_count++;
else if (cat == 1) res.strong_clergy_count++;
else if (cat == 2) res.weak_clergy_count++;
else res.other_count++;
// 验人系数量有10%概率为2
res.appraisal_count = (rand() % 100 < 10) ? 2 : 1;
} else if (n == 18) {
res.werewolf_count = 5;
res.strong_clergy_count = 5;
res.weak_clergy_count = 5;
res.other_count = 1;
if (rand() % 2 == 0) res.werewolf_count++;
else res.other_count++;
if (rand() % 2 == 0) res.strong_clergy_count++;
else res.weak_clergy_count++;
// 验人系数量有15%概率为2
res.appraisal_count = (rand() % 100 < 15) ? 2 : 1;
} else {
return (ConfigResult){0}; // 无效人数返回空
}
int total = res.werewolf_count + res.strong_clergy_count + res.weak_clergy_count + res.other_count;
if (total != n) {
ConfigResult empty = {0};
return empty;
}
return res;
}
/**
* 获取指定模式和人数的平衡范围
* 注意:此版本中所有模式共用相同的平衡范围,仅依赖于人数n
* @param mode 游戏模式(未使用)
* @param n 游戏人数
* @param min_balance 输出参数:最小平衡倍率
* @param max_balance 输出参数:最大平衡倍率
*/
void get_balance_range(GameMode mode, int n, double* min_balance, double* max_balance) {
// 所有模式共用相同的平衡范围
if (n == 9) { *min_balance = BALANCE_MIN_9; *max_balance = BALANCE_MAX_9; }
else if (n <= 11) { *min_balance = BALANCE_MIN_10; *max_balance = BALANCE_MAX_10; } // 10-11相同
else if (n <= 14) { *min_balance = BALANCE_MIN_12; *max_balance = BALANCE_MAX_12; } // 12-14相同
else { *min_balance = BALANCE_MIN_15; *max_balance = BALANCE_MAX_15; } // 15-18相同
}
// ========== 从候选池中随机抽取一个身份 ==========
/**
* 从候选ID池中均匀随机抽取一个身份,排除已选ID
* @param pool 候选ID数组
* @param pool_size 池大小
* @param exclude_ids 要排除的ID数组
* @param exclude_count 排除数量
* @return 指向所选身份的指针,若无可用则返回NULL
*/
Identity* select_random_identity_from_pool(int* pool, int pool_size, int* exclude_ids, int exclude_count) {
if (pool_size <= 0) return NULL;
int available[MAX_IDENTITIES], avail_cnt = 0;
for (int i = 0; i < pool_size; i++) {
int id = pool[i];
int skip = 0;
for (int j = 0; j < exclude_count; j++) if (id == exclude_ids[j]) { skip = 1; break; }
if (!skip) available[avail_cnt++] = i; // 存储索引
}
if (avail_cnt == 0) return NULL;
int idx = available[rand() % avail_cnt];
return &identities[pool[idx]];
}
// ========== 从全局身份中抽取(综合模式) ==========
/**
* 综合模式:从全局身份中按原始分类均匀抽取配置
* 先抽取女巫系、验人系,然后依次抽取剩余强神、弱神、狼人、其他
* @param config 配置结果(包含各类别数量)
* @return 抽取结果,若失败则selected_count为0
*/
SelectionResult select_identities(ConfigResult* config) {
SelectionResult res = {0};
int exclude[MAX_IDENTITIES], excl = 0;
// 1. 女巫系 (original_category == 1)
int witch_pool[MAX_IDENTITIES], witch_cnt = 0;
for (int i = 0; i < total_identities; i++)
if (identities[i].original_category == ORIG_CAT_WITCH)
witch_pool[witch_cnt++] = i;
Identity* witch = select_random_identity_from_pool(witch_pool, witch_cnt, exclude, excl);
if (!witch) return res;
res.selected_identities[res.selected_count++] = witch;
res.identity_counts[witch->id] = 1;
exclude[excl++] = witch->id;
// 2. 验人系 (original_category == 0)
int app_pool[MAX_IDENTITIES], app_cnt = 0;
for (int i = 0; i < total_identities; i++)
if (identities[i].original_category == ORIG_CAT_APPRAISAL)
app_pool[app_cnt++] = i;
int appraisal_needed = config->appraisal_count;
int app_strong_taken = 0, app_weak_taken = 0;
for (int i = 0; i < appraisal_needed; i++) {
Identity* app = select_random_identity_from_pool(app_pool, app_cnt, exclude, excl);
if (!app) return res;
res.selected_identities[res.selected_count++] = app;
res.identity_counts[app->id] = 1;
exclude[excl++] = app->id;
if (app->category == CATEGORY_STRONG_CLERGY) app_strong_taken++;
else app_weak_taken++;
}
// 3. 剩余强神 (original_category == 2 且 category为强神)
int strong_pool[MAX_IDENTITIES], strong_cnt = 0;
for (int i = 0; i < total_identities; i++) {
if (identities[i].category == CATEGORY_STRONG_CLERGY &&
identities[i].original_category == ORIG_CAT_OTHER)
strong_pool[strong_cnt++] = i;
}
int need_strong = config->strong_clergy_count - 1 - app_strong_taken; // 减去女巫系(1)和已取的强神验人系
for (int i = 0; i < need_strong; i++) {
Identity* id = select_random_identity_from_pool(strong_pool, strong_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 4. 剩余弱神 (original_category == 2 且 category为弱神)
int weak_pool[MAX_IDENTITIES], weak_cnt = 0;
for (int i = 0; i < total_identities; i++) {
if (identities[i].category == CATEGORY_WEAK_CLERGY &&
identities[i].original_category == ORIG_CAT_OTHER)
weak_pool[weak_cnt++] = i;
}
int need_weak = config->weak_clergy_count - app_weak_taken; // 减去已取的弱神验人系
for (int i = 0; i < need_weak; i++) {
Identity* id = select_random_identity_from_pool(weak_pool, weak_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 5. 狼人
int wolf_pool[MAX_IDENTITIES], wolf_cnt = 0;
for (int i = 0; i < total_identities; i++)
if (identities[i].category == CATEGORY_WEREWOLF)
wolf_pool[wolf_cnt++] = i;
for (int i = 0; i < config->werewolf_count; i++) {
Identity* id = select_random_identity_from_pool(wolf_pool, wolf_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 6. 其他(独立+不定)
int other_pool[MAX_IDENTITIES], other_cnt = 0;
for (int i = 0; i < total_identities; i++) {
if (identities[i].faction == FACTION_INDEPENDENT || identities[i].faction == FACTION_INDEFINITE)
other_pool[other_cnt++] = i;
}
for (int i = 0; i < config->other_count; i++) {
Identity* id = select_random_identity_from_pool(other_pool, other_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
if (res.selected_count != config->total_count) {
SelectionResult empty = {0};
return empty;
}
return res;
}
// ========== 从限池模式的身份池中抽取配置(均匀随机) ==========
/**
* 限池模式:从给定的身份池中均匀抽取配置
* 抽取逻辑与综合模式相同,但候选池仅限于pool中的身份
* @param config 配置结果
* @param pool 身份池指针数组
* @param pool_size 池大小
* @return 抽取结果,若失败则selected_count为0
*/
SelectionResult select_identities_from_pool(ConfigResult* config, Identity* pool[], int pool_size) {
SelectionResult res = {0};
int exclude[MAX_IDENTITIES], excl = 0;
// 将池中的身份ID转换为数组,便于使用 select_random_identity_from_pool
int pool_ids[MAX_IDENTITIES];
for (int i = 0; i < pool_size; i++) {
pool_ids[i] = pool[i]->id;
}
// 1. 女巫系
int witch_pool[MAX_IDENTITIES], witch_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->original_category == ORIG_CAT_WITCH) witch_pool[witch_cnt++] = pool[i]->id;
}
Identity* witch = select_random_identity_from_pool(witch_pool, witch_cnt, exclude, excl);
if (!witch) return res;
res.selected_identities[res.selected_count++] = witch;
res.identity_counts[witch->id] = 1;
exclude[excl++] = witch->id;
// 2. 验人系
int app_pool[MAX_IDENTITIES], app_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->original_category == ORIG_CAT_APPRAISAL) app_pool[app_cnt++] = pool[i]->id;
}
int appraisal_needed = config->appraisal_count;
int app_strong_taken = 0, app_weak_taken = 0;
for (int i = 0; i < appraisal_needed; i++) {
Identity* app = select_random_identity_from_pool(app_pool, app_cnt, exclude, excl);
if (!app) return res;
res.selected_identities[res.selected_count++] = app;
res.identity_counts[app->id] = 1;
exclude[excl++] = app->id;
if (app->category == CATEGORY_STRONG_CLERGY) app_strong_taken++;
else app_weak_taken++;
}
// 3. 剩余强神
int strong_pool[MAX_IDENTITIES], strong_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->category == CATEGORY_STRONG_CLERGY && pool[i]->original_category == ORIG_CAT_OTHER)
strong_pool[strong_cnt++] = pool[i]->id;
}
int need_strong = config->strong_clergy_count - 1 - app_strong_taken;
for (int i = 0; i < need_strong; i++) {
Identity* id = select_random_identity_from_pool(strong_pool, strong_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 4. 剩余弱神
int weak_pool[MAX_IDENTITIES], weak_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->category == CATEGORY_WEAK_CLERGY && pool[i]->original_category == ORIG_CAT_OTHER)
weak_pool[weak_cnt++] = pool[i]->id;
}
int need_weak = config->weak_clergy_count - app_weak_taken;
for (int i = 0; i < need_weak; i++) {
Identity* id = select_random_identity_from_pool(weak_pool, weak_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 5. 狼人
int wolf_pool[MAX_IDENTITIES], wolf_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->category == CATEGORY_WEREWOLF) wolf_pool[wolf_cnt++] = pool[i]->id;
}
for (int i = 0; i < config->werewolf_count; i++) {
Identity* id = select_random_identity_from_pool(wolf_pool, wolf_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
// 6. 其他
int other_pool[MAX_IDENTITIES], other_cnt = 0;
for (int i = 0; i < pool_size; i++) {
if (pool[i]->faction == FACTION_INDEPENDENT || pool[i]->faction == FACTION_INDEFINITE)
other_pool[other_cnt++] = pool[i]->id;
}
for (int i = 0; i < config->other_count; i++) {
Identity* id = select_random_identity_from_pool(other_pool, other_cnt, exclude, excl);
if (!id) return res;
res.selected_identities[res.selected_count++] = id;
res.identity_counts[id->id] = 1;
exclude[excl++] = id->id;
}
if (res.selected_count != config->total_count) {
SelectionResult empty = {0};
return empty;
}
return res;
}
// ========== 合法性检查 ==========
/**
* 验证抽取结果是否合法
* @param sel 选择结果
* @param config 期望的配置
* @return 1表示合法,0表示不合法
*/
int validate_selection(SelectionResult* sel, ConfigResult config) {
// 检查每个身份的最低游戏人数
for (int i = 0; i < sel->selected_count; i++)
if (game_players < sel->selected_identities[i]->min_players) return 0;
// 检查不可重复身份是否出现多次(所有身份均不可重复)
for (int i = 0; i < total_identities; i++)
if (sel->identity_counts[i] > 1) return 0;
int cnt[5] = {0}; // 五种类别的计数
int appraisal_actual = 0; // 实际验人系数目
for (int i = 0; i < sel->selected_count; i++) {
cnt[sel->selected_identities[i]->category]++;
if (sel->selected_identities[i]->original_category == ORIG_CAT_APPRAISAL) appraisal_actual++;
}
if (appraisal_actual != config.appraisal_count) return 0;
if (cnt[CATEGORY_WEREWOLF] != config.werewolf_count) return 0;
if (cnt[CATEGORY_STRONG_CLERGY] != config.strong_clergy_count) return 0;
if (cnt[CATEGORY_WEAK_CLERGY] != config.weak_clergy_count) return 0;
int other_actual = cnt[CATEGORY_INDEPENDENT] + cnt[CATEGORY_INDEFINITE];
if (other_actual != config.other_count) return 0;
return 1;
}
// ========== 倍率计算 ==========
/**
* 计算配置的倍率
* @param sel 选择结果
* @param config 配置信息
* @param n 游戏人数
* @return 倍率检查结果
*/
MagnificationCheck calculate_magnification(SelectionResult sel, ConfigResult config, int n) {
MagnificationCheck chk = {0};
for (int i = 0; i < sel.selected_count; i++) {
Identity* id = sel.selected_identities[i];
double score = calculate_score(id, n);
if (id->faction == FACTION_WEREWOLF)
chk.werewolf_score_sum += score;
else
chk.non_werewolf_score_sum += score;
}
if (chk.werewolf_score_sum > 0)
chk.magnification = chk.non_werewolf_score_sum / chk.werewolf_score_sum;
chk.is_balanced = check_magnification_balance(chk, n);
return chk;
}
/**
* 检查倍率是否在平衡范围内
* @param chk 倍率检查结果
* @param n 游戏人数
* @return 1表示平衡,0表示不平衡
*/
int check_magnification_balance(MagnificationCheck chk, int n) {
double minb, maxb;
get_balance_range(current_mode, n, &minb, &maxb);
return (chk.magnification >= minb && chk.magnification <= maxb);
}
// ========== 倍率调整 ==========
/**
* 调整倍率:通过替换配置中的某个身份,使倍率趋向平衡范围
* @param sel 选择结果(将被修改)
* @param config 配置信息
* @param n 游戏人数
* @param pool 身份池(限池模式时使用,综合模式为NULL)
* @param pool_size 池大小(综合模式为0)
* @return 1表示成功调整至平衡,0表示调整失败
*/
int adjust_magnification(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[], int pool_size) {
int replaced_flag[MAX_PLAYERS] = {0}; // 标记已尝试替换的位置
int total_pos = sel->selected_count;
int attempts = 0, max_attempts = MAX_MAGNIFICATION_TEST;
double minb, maxb;
get_balance_range(current_mode, n, &minb, &maxb);
MagnificationCheck chk = calculate_magnification(*sel, *config, n);
chk.is_balanced = check_magnification_balance(chk, n);
while (attempts < max_attempts && !chk.is_balanced) {
attempts++;
// 检查是否所有位置都已尝试过,若是则重置标记
int avail = 0;
for (int i = 0; i < total_pos; i++) if (!replaced_flag[i]) { avail = 1; break; }
if (!avail) memset(replaced_flag, 0, sizeof(replaced_flag[0]) * total_pos);
int idx;
do { idx = rand() % total_pos; } while (replaced_flag[idx]); // 随机选一个未尝试过的位置
Identity* old = sel->selected_identities[idx];
Category cat = old->category;
int old_orig = old->original_category;
Faction old_fac = old->faction;
int need_increase_werewolf = (chk.magnification < minb) ? 1 : 0;
// 倍率过低需要加强狼人(即增加狼人算分或减少好人算分)
int candidates[MAX_IDENTITIES], ccnt = 0;
// 构建候选身份列表:与旧身份同类别、同原始分类(或同阵营),且算分方向符合需求
if (pool != NULL) {
// 限池模式:从池中找
for (int j = 0; j < pool_size; j++) {
Identity* id = pool[j];
if (id->id == old->id) continue;
if (sel->identity_counts[id->id] > 0) continue;
if (id->category != cat) continue;
if (old_orig == ORIG_CAT_APPRAISAL && id->original_category != ORIG_CAT_APPRAISAL) continue;
if (old_orig == ORIG_CAT_WITCH && id->original_category != ORIG_CAT_WITCH) continue;
if (old_fac == FACTION_INDEPENDENT && id->faction != FACTION_INDEPENDENT) continue;
if (old_fac == FACTION_INDEFINITE && id->faction != FACTION_INDEFINITE) continue;
double old_score = calculate_score(old, n);
double new_score = calculate_score(id, n);
if (old_fac == FACTION_WEREWOLF) {
if (need_increase_werewolf && new_score > old_score) candidates[ccnt++] = id->id;
else if (!need_increase_werewolf && new_score < old_score) candidates[ccnt++] = id->id;
} else {
if (need_increase_werewolf && new_score < old_score) candidates[ccnt++] = id->id;
else if (!need_increase_werewolf && new_score > old_score) candidates[ccnt++] = id->id;
}
}
} else {
// 综合模式:从全局找
for (int i = 0; i < total_identities; i++) {
if (i == old->id) continue;
if (sel->identity_counts[i] > 0) continue;
if (identities[i].category != cat) continue;
if (old_orig == ORIG_CAT_APPRAISAL && identities[i].original_category != ORIG_CAT_APPRAISAL) continue;
if (old_orig == ORIG_CAT_WITCH && identities[i].original_category != ORIG_CAT_WITCH) continue;
if (old_fac == FACTION_INDEPENDENT && identities[i].faction != FACTION_INDEPENDENT) continue;
if (old_fac == FACTION_INDEFINITE && identities[i].faction != FACTION_INDEFINITE) continue;
double old_score = calculate_score(old, n);
double new_score = calculate_score(&identities[i], n);
if (old_fac == FACTION_WEREWOLF) {
if (need_increase_werewolf && new_score > old_score) candidates[ccnt++] = i;
else if (!need_increase_werewolf && new_score < old_score) candidates[ccnt++] = i;
} else {
if (need_increase_werewolf && new_score < old_score) candidates[ccnt++] = i;
else if (!need_increase_werewolf && new_score > old_score) candidates[ccnt++] = i;
}
}
}
if (ccnt == 0) {
replaced_flag[idx] = 1; // 无可替换,标记为已尝试
continue;
}
int pick = candidates[rand() % ccnt];
sel->identity_counts[old->id] = 0;
sel->selected_identities[idx] = &identities[pick];
sel->identity_counts[pick] = 1;
replaced_flag[idx] = 1;
chk = calculate_magnification(*sel, *config, n);
chk.is_balanced = check_magnification_balance(chk, n);
}
return chk.is_balanced ? 1 : 0;
}
// ========== 长老狼调整 ==========
/**
* 调整长老狼比例:确保群内狼比例在合理范围
* 若群内狼比例过低(≤1/3),则尝试将某个狼人替换为长老狼
* 若群内狼比例过高(>2/3),则尝试将长老狼替换为其他群内狼
* @param sel 选择结果(将被修改)
* @param config 配置信息
* @param n 游戏人数
* @param pool 身份池(限池模式时使用,综合模式为NULL)
* @param pool_size 池大小
* @return 1表示执行了替换,0表示未执行
*/
int adjust_elder_wolf(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[], int pool_size) {
int total_wolves = 0, group_wolves = 0, elder_index = -1;
for (int i = 0; i < sel->selected_count; i++) {
Identity* id = sel->selected_identities[i];
if (id->faction == FACTION_WEREWOLF) {
total_wolves++;
if (id->is_in_group) group_wolves++;
if (strcmp(id->name, "长老狼") == 0) elder_index = i;
}
}
if (total_wolves == 0) return 0;
int need_change = 0, target_index = -1;
Identity* new_id = NULL;
if (group_wolves * 3 <= total_wolves) {
// 群内狼比例 ≤ 1/3,需要增加群内狼,最好是长老狼
if (elder_index == -1) {
need_change = 1;
double elder_score = ELDER_WOLF_SCORE;
double best_diff = 1e9;
int candidates[MAX_PLAYERS], cand_count = 0;
// 优先从群内狼中选算分最接近的
for (int i = 0; i < sel->selected_count; i++) {
Identity* id = sel->selected_identities[i];
if (id->faction == FACTION_WEREWOLF && id->is_in_group) {
double diff = fabs(calculate_score(id, n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = i;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = i;
}
}
}
if (cand_count == 0) {
// 若无群内狼,则从所有狼中选
best_diff = 1e9;
for (int i = 0; i < sel->selected_count; i++) {
Identity* id = sel->selected_identities[i];
if (id->faction == FACTION_WEREWOLF) {
double diff = fabs(calculate_score(id, n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = i;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = i;
}
}
}
}
if (cand_count > 0) {
target_index = candidates[rand() % cand_count];
for (int j = 0; j < total_identities; j++)
if (strcmp(identities[j].name, "长老狼") == 0) new_id = &identities[j];
if (pool != NULL) {
// 限池模式需检查长老狼是否在池中
int in_pool = 0;
for (int k = 0; k < pool_size; k++)
if (pool[k]->id == new_id->id) { in_pool = 1; break; }
if (!in_pool) return 0;
}
}
}
} else if (group_wolves * 3 > 2 * total_wolves) {
// 群内狼比例 > 2/3,需要减少群内狼,将长老狼替换为非长老狼的群内狼或普通狼
if (elder_index != -1) {
need_change = 1;
target_index = elder_index;
double elder_score = calculate_score(sel->selected_identities[elder_index], n);
double best_diff = 1e9;
int candidates[MAX_IDENTITIES], cand_count = 0;
if (pool != NULL) {
// 限池模式
for (int j = 0; j < pool_size; j++) {
Identity* id = pool[j];
if (id->faction == FACTION_WEREWOLF && id->is_in_group &&
strcmp(id->name, "长老狼") != 0) {
if (sel->identity_counts[id->id] > 0) continue;
double diff = fabs(calculate_score(id, n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = id->id;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = id->id;
}
}
}
if (cand_count == 0) {
best_diff = 1e9;
for (int j = 0; j < pool_size; j++) {
Identity* id = pool[j];
if (id->faction == FACTION_WEREWOLF && strcmp(id->name, "长老狼") != 0) {
if (sel->identity_counts[id->id] > 0) continue;
double diff = fabs(calculate_score(id, n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = id->id;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = id->id;
}
}
}
}
} else {
// 综合模式
for (int j = 0; j < total_identities; j++) {
if (identities[j].faction == FACTION_WEREWOLF && identities[j].is_in_group &&
strcmp(identities[j].name, "长老狼") != 0) {
if (sel->identity_counts[j] > 0) continue;
double diff = fabs(calculate_score(&identities[j], n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = j;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = j;
}
}
}
if (cand_count == 0) {
best_diff = 1e9;
for (int j = 0; j < total_identities; j++) {
if (identities[j].faction == FACTION_WEREWOLF &&
strcmp(identities[j].name, "长老狼") != 0) {
if (sel->identity_counts[j] > 0) continue;
double diff = fabs(calculate_score(&identities[j], n) - elder_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = j;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = j;
}
}
}
}
}
if (cand_count > 0) {
int pick = candidates[rand() % cand_count];
new_id = &identities[pick];
}
}
}
if (need_change && target_index != -1 && new_id != NULL) {
Identity* old = sel->selected_identities[target_index];
sel->identity_counts[old->id]--;
sel->selected_identities[target_index] = new_id;
sel->identity_counts[new_id->id]++;
return 1;
}
return 0;
}
// ========== 母身份调整 ==========
/**
* 调整母身份关系:确保每个有母身份的狼人其母身份也在配置中
* 若缺失,以1/2概率执行操作A(将某个同类别身份替换为母身份)
* 或以1/2概率执行操作B(将当前子身份替换为同类别同原始分类的另一身份)
* @param sel 选择结果(将被修改)
* @param config 配置信息
* @param n 游戏人数
* @param pool 身份池(限池模式时使用,综合模式为NULL)
* @param pool_size 池大小
* @return 1表示执行了替换,0表示未执行
*/
int adjust_mother_relationships(SelectionResult* sel, ConfigResult* config, int n, Identity* pool[],
int pool_size) {
for (int i = 0; i < sel->selected_count; i++) {
Identity* child = sel->selected_identities[i];
if (!child->has_mother) continue;
int mother_present = 0;
for (int j = 0; j < sel->selected_count; j++) {
if (sel->selected_identities[j]->id == child->mother_id) {
mother_present = 1;
break;
}
}
if (mother_present) continue;
if (rand() % 2 == 0) {
// 操作A:替换为母身份
Identity* mother = &identities[child->mother_id];
if (pool != NULL) {
int in_pool = 0;
for (int k = 0; k < pool_size; k++)
if (pool[k]->id == mother->id) { in_pool = 1; break; }
if (!in_pool) continue;
}
Category mother_cat = mother->category;
double mother_score = calculate_score(mother, n);
int candidates[MAX_PLAYERS], cand_count = 0;
double best_diff = 1e9;
for (int j = 0; j < sel->selected_count; j++) {
Identity* id = sel->selected_identities[j];
if (id->category != mother_cat) continue;
// 如果母身份是强神,不能替换验人系或女巫系(固定身份)
if (mother_cat == CATEGORY_STRONG_CLERGY &&
(id->original_category == ORIG_CAT_APPRAISAL || id->original_category == ORIG_CAT_WITCH))
continue;
double score = calculate_score(id, n);
double diff = fabs(score - mother_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = j;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = j;
}
}
if (cand_count > 0) {
int pick = candidates[rand() % cand_count];
Identity* old = sel->selected_identities[pick];
sel->identity_counts[old->id]--;
sel->selected_identities[pick] = mother;
sel->identity_counts[mother->id]++;
return 1;
}
} else {
// 操作B:将当前子身份替换为同类别、同原始分类且与自身算分最接近的另一个身份
Category cat = child->category;
double child_score = calculate_score(child, n);
int candidates[MAX_IDENTITIES], cand_count = 0;
double best_diff = 1e9;
if (pool != NULL) {
for (int j = 0; j < pool_size; j++) {
Identity* id = pool[j];
if (id->id == child->id) continue;
if (sel->identity_counts[id->id] > 0) continue;
if (id->category != cat) continue;
if (child->original_category != id->original_category) continue;
double score = calculate_score(id, n);
double diff = fabs(score - child_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = id->id;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = id->id;
}
}
} else {
for (int j = 0; j < total_identities; j++) {
if (j == child->id) continue;
if (sel->identity_counts[j] > 0) continue;
if (identities[j].category != cat) continue;
if (child->original_category != identities[j].original_category) continue;
double score = calculate_score(&identities[j], n);
double diff = fabs(score - child_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = j;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = j;
}
}
}
if (cand_count > 0) {
int pick = candidates[rand() % cand_count];
sel->identity_counts[child->id]--;
sel->selected_identities[i] = &identities[pick];
sel->identity_counts[pick]++;
return 1;
}
}
}
return 0;
}
// ========== 身份池构建 ==========
/**
* 构建限池模式的身份池
* 根据当前游戏人数 game_players 动态决定各分类的配额,按权重抽取,并强制包含长老狼
* 构建完成后进行母身份调整,确保所有母身份成对出现
* @param pool 输出数组,存储选中身份的指针
* @return 实际池中身份数量(成功时为正数),失败返回0
*/
int build_identity_pool(Identity* pool[]) {
int max_attempts = MAX_POOL_BUILD_ATTEMPTS;
int n = game_players;
// 根据人数定义配额(各分类所需数量)
int wolf_target, strong_app_target, strong_witch_target, strong_other_target,
weak_app_target, weak_other_target, other_target;
if (n == 9) {
wolf_target = 12;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 6;
weak_app_target = 2;
weak_other_target = 10;
other_target = 0;
} else if (n == 10) {
wolf_target = 12;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 6;
weak_app_target = 2;
weak_other_target = 10;
other_target = 4;
} else if (n == 11) {
wolf_target = 14;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 8;
weak_app_target = 2;
weak_other_target = 12;
other_target = 2;
} else if (n == 12) {
wolf_target = 16;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 10;
weak_app_target = 2;
weak_other_target = 14;
other_target = 0;
} else if (n == 13) {
wolf_target = 16;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 10;
weak_app_target = 2;
weak_other_target = 14;
other_target = 4;
} else if (n == 14) {
wolf_target = 18;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 12;
weak_app_target = 2;
weak_other_target = 16;
other_target = 2;
} else if (n == 15) {
wolf_target = 19;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 13;
weak_app_target = 2;
weak_other_target = 17;
other_target = 3;
} else if (n == 16) {
wolf_target = 20;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 14;
weak_app_target = 2;
weak_other_target = 18;
other_target = 4;
} else if (n == 17) {
wolf_target = 21;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 15;
weak_app_target = 2;
weak_other_target = 19;
other_target = 5;
} else if (n == 18) {
wolf_target = 22;
strong_app_target = 2;
strong_witch_target = 4;
strong_other_target = 16;
weak_app_target = 2;
weak_other_target = 20;
other_target = 6;
} else {
return 0;
}
for (int attempt = 0; attempt < max_attempts; attempt++) {
int pool_count = 0;
int used[MAX_IDENTITIES] = {0};
// --- 狼人:强制包含长老狼 ---
int elder_id = -1;
for (int i = 0; i < total_identities; i++) {
if (strcmp(identities[i].name, "长老狼") == 0) {
elder_id = i;
break;
}
}
if (elder_id == -1) {
printf("错误:找不到长老狼\n");
return 0;
}
if (identities[elder_id].min_players > n) {
goto next_attempt;
}
used[elder_id] = 1;
pool[pool_count++] = &identities[elder_id];
int wolf_remaining = wolf_target - 1;
int wolf_candidates[MAX_IDENTITIES];
int wolf_cand_count = 0;
for (int i = 0; i < total_identities; i++) {
if (used[i]) continue;
if (identities[i].category == CATEGORY_WEREWOLF &&
identities[i].original_category == ORIG_CAT_WEREWOLF) {
if (identities[i].min_players > n) continue;
wolf_candidates[wolf_cand_count++] = i;
}
}
if (wolf_cand_count < wolf_remaining) {
goto next_attempt;
}
for (int t = 0; t < wolf_remaining; t++) {
double total_weight = 0;
for (int i = 0; i < wolf_cand_count; i++) {
int id = wolf_candidates[i];
if (!used[id]) total_weight += identities[id].weight;
}
if (total_weight <= 0) total_weight = 1e-9;
double rval = (double)rand() / RAND_MAX * total_weight;
double cum = 0;
int pick = -1;
for (int i = 0; i < wolf_cand_count; i++) {
int id = wolf_candidates[i];
if (used[id]) continue;
cum += identities[id].weight;
if (rval <= cum) {
pick = id;
break;
}
}
if (pick == -1) {
for (int i = 0; i < wolf_cand_count; i++) {
if (!used[wolf_candidates[i]]) {
pick = wolf_candidates[i];
break;
}
}
}
if (pick == -1) goto next_attempt;
used[pick] = 1;
pool[pool_count++] = &identities[pick];
}
// --- 其他类别(强神、弱神) ---
typedef struct {
Category cat;
int orig;
int target;
} CatReq;
CatReq categories[] = {
{CATEGORY_STRONG_CLERGY, ORIG_CAT_APPRAISAL, strong_app_target},
{CATEGORY_STRONG_CLERGY, ORIG_CAT_WITCH, strong_witch_target},
{CATEGORY_STRONG_CLERGY, ORIG_CAT_OTHER, strong_other_target},
{CATEGORY_WEAK_CLERGY, ORIG_CAT_APPRAISAL, weak_app_target},
{CATEGORY_WEAK_CLERGY, ORIG_CAT_OTHER, weak_other_target},
};
int num_cats = sizeof(categories) / sizeof(categories[0]);
for (int c = 0; c < num_cats; c++) {
int target = categories[c].target;
if (target == 0) continue;
int candidates[MAX_IDENTITIES];
int cand_count = 0;
for (int i = 0; i < total_identities; i++) {
if (used[i]) continue;
if (identities[i].category == categories[c].cat &&
identities[i].original_category == categories[c].orig) {
if (identities[i].min_players > n) continue;
candidates[cand_count++] = i;
}
}
if (cand_count < target) {
goto next_attempt;
}
for (int t = 0; t < target; t++) {
double total_weight = 0;
for (int i = 0; i < cand_count; i++) {
int id = candidates[i];
if (!used[id]) total_weight += identities[id].weight;
}
if (total_weight <= 0) total_weight = 1e-9;
double rval = (double)rand() / RAND_MAX * total_weight;
double cum = 0;
int pick = -1;
for (int i = 0; i < cand_count; i++) {
int id = candidates[i];
if (used[id]) continue;
cum += identities[id].weight;
if (rval <= cum) {
pick = id;
break;
}
}
if (pick == -1) {
for (int i = 0; i < cand_count; i++) {
if (!used[candidates[i]]) {
pick = candidates[i];
break;
}
}
}
if (pick == -1) goto next_attempt;
used[pick] = 1;
pool[pool_count++] = &identities[pick];
}
}
// --- 其他(独立+不定) ---
if (other_target > 0) {
int other_candidates[MAX_IDENTITIES];
int other_cnt = 0;
for (int i = 0; i < total_identities; i++) {
if (used[i]) continue;
if (identities[i].faction == FACTION_INDEPENDENT ||
identities[i].faction == FACTION_INDEFINITE) {
if (identities[i].min_players > n) continue;
other_candidates[other_cnt++] = i;
}
}
if (other_cnt < other_target) {
goto next_attempt;
}
for (int t = 0; t < other_target; t++) {
double total_weight = 0;
for (int i = 0; i < other_cnt; i++) {
int id = other_candidates[i];
if (!used[id]) total_weight += identities[id].weight;
}
if (total_weight <= 0) total_weight = 1e-9;
double rval = (double)rand() / RAND_MAX * total_weight;
double cum = 0;
int pick = -1;
for (int i = 0; i < other_cnt; i++) {
int id = other_candidates[i];
if (used[id]) continue;
cum += identities[id].weight;
if (rval <= cum) {
pick = id;
break;
}
}
if (pick == -1) {
for (int i = 0; i < other_cnt; i++) {
if (!used[other_candidates[i]]) {
pick = other_candidates[i];
break;
}
}
}
if (pick == -1) goto next_attempt;
used[pick] = 1;
pool[pool_count++] = &identities[pick];
}
}
// 检查池大小是否匹配
int expected_size = wolf_target + strong_app_target + strong_witch_target +
strong_other_target + weak_app_target + weak_other_target + other_target;
if (pool_count != expected_size) {
goto next_attempt;
}
// 母身份调整
if (adjust_pool_for_mother_relationships(pool, pool_count)) {
return pool_count;
}
next_attempt:
continue;
}
printf("错误:无法构建满足规则的身份池(尝试%d次后失败)\n", max_attempts);
return 0;
}
/**
* 调整身份池,确保所有母身份成对出现。
* 遍历池中每个有母身份的身份,若母身份缺失,则以1/2概率执行:
* 操作A:从池中选一个与母身份同类别且算分最接近的身份,替换为母身份。
* 操作B:将当前子身份替换为同类别、同原始分类且与自身算分最接近的另一个身份(从全局未使用中找)。
* 若有多个同分候选,按权重随机选择。
* @param pool 身份池指针数组
* @param pool_size 池大小
* @return 1表示调整成功,0表示调整失败(无法满足)
*/
int adjust_pool_for_mother_relationships(Identity* pool[], int pool_size) {
// 获取长老狼的ID
int elder_id = -1;
for (int i = 0; i < total_identities; i++) {
if (strcmp(identities[i].name, "长老狼") == 0) {
elder_id = i;
break;
}
}
if (elder_id == -1) {
printf("错误:找不到长老狼\n");
return 0;
}
int max_attempts = 20;
for (int attempt = 0; attempt < max_attempts; attempt++) {
int changed = 0;
for (int i = 0; i < pool_size; i++) {
Identity* child = pool[i];
if (!child->has_mother) continue;
// 检查母身份是否已在池中
int mother_present = 0;
for (int j = 0; j < pool_size; j++) {
if (pool[j]->id == child->mother_id) {
mother_present = 1;
break;
}
}
if (mother_present) continue;
// 母身份缺失,以1/2概率决定操作
if (rand() % 2 == 0) {
// 操作A:从池中选一个与母身份同类别且算分最接近的身份,替换为母身份
Identity* mother = &identities[child->mother_id];
// 检查母身份是否满足人数
if (mother->min_players > game_players) continue;
Category mother_cat = mother->category;
double mother_score = calculate_score(mother, game_players);
int candidates[MAX_PLAYERS];
int cand_count = 0;
double best_diff = 1e9;
for (int j = 0; j < pool_size; j++) {
if (j == i) continue;
Identity* id = pool[j];
// 保护:不能替换长老狼
if (id->id == elder_id) continue;
if (id->category != mother_cat) continue;
// 如果母身份是强神,则不能替换验人系或女巫系(固定身份)
if (mother_cat == CATEGORY_STRONG_CLERGY) {
if (id->original_category == ORIG_CAT_APPRAISAL ||
id->original_category == ORIG_CAT_WITCH) continue;
}
double score = calculate_score(id, game_players);
double diff = fabs(score - mother_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = j;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = j;
}
}
if (cand_count == 0) {
continue; // 无法找到合适替换,跳过本次
}
// 在候选者中按权重随机选一个
double total_weight = 0;
for (int k = 0; k < cand_count; k++) {
total_weight += pool[candidates[k]]->weight;
}
double rval = (double)rand() / RAND_MAX * total_weight;
double cum = 0;
int pick_idx = -1;
for (int k = 0; k < cand_count; k++) {
cum += pool[candidates[k]]->weight;
if (rval <= cum) {
pick_idx = candidates[k];
break;
}
}
if (pick_idx == -1) pick_idx = candidates[0];
// 执行替换
pool[pick_idx] = mother;
changed = 1;
break; // 一次只处理一个,重新循环
} else {
// 操作B:将当前子身份替换为同类别、同原始分类且与自身算分最接近的另一个身份(从全局未使用中找)
Category cat = child->category;
int orig = child->original_category;
double child_score = calculate_score(child, game_players);
// 构建候选身份ID列表(全局未使用且满足条件)
int candidates[MAX_IDENTITIES];
int cand_count = 0;
double best_diff = 1e9;
for (int id = 0; id < total_identities; id++) {
if (id == child->id) continue;
// 保护:不能替换成长老狼
if (id == elder_id) continue;
// 检查该身份是否已在池中
int in_pool = 0;
for (int j = 0; j < pool_size; j++) {
if (pool[j]->id == id) { in_pool = 1; break; }
}
if (in_pool) continue; // 已在池中,不可重复
if (identities[id].min_players > game_players) continue; // 人数过滤
if (identities[id].category != cat) continue;
if (identities[id].original_category != orig) continue;
double score = calculate_score(&identities[id], game_players);
double diff = fabs(score - child_score);
if (diff < best_diff - 1e-6) {
best_diff = diff;
cand_count = 0;
candidates[cand_count++] = id;
} else if (fabs(diff - best_diff) < 1e-6) {
candidates[cand_count++] = id;
}
}
if (cand_count == 0) {
continue; // 无合适替换,跳过
}
// 按权重随机选择
double total_weight = 0;
for (int k = 0; k < cand_count; k++) {
total_weight += identities[candidates[k]].weight;
}
double rval = (double)rand() / RAND_MAX * total_weight;
double cum = 0;
int pick_id = -1;
for (int k = 0; k < cand_count; k++) {
cum += identities[candidates[k]].weight;
if (rval <= cum) {
pick_id = candidates[k];
break;
}
}
if (pick_id == -1) pick_id = candidates[0];
// 将当前池中第 i 个身份替换为新的身份
pool[i] = &identities[pick_id];
changed = 1;
break; // 一次只处理一个
}
}
if (!changed) return 1; // 所有母身份关系满足
}
return 0; // 调整失败
}
// ========== 生成单个配置(综合模式) ==========
/**
* 综合模式:生成单个有效配置
* 尝试生成配置,并通过调整循环使倍率平衡、母身份关系正确、长老狼比例合适
* @param n 游戏人数
* @param result 输出参数:选择结果
* @param config_result 输出参数:配置信息
* @return 1表示成功,0表示失败
*/
int generate_single_configuration(int n, SelectionResult* result, ConfigResult* config_result) {
int max_attempts = MAX_CONFIG_ATTEMPTS;
for (int attempt = 0; attempt < max_attempts; attempt++) {
*config_result = generate_config(n);
*result = select_identities(config_result);
if (result->selected_count == 0) continue;
if (!validate_selection(result, *config_result)) continue;
int any_change = 1;
int loop = 0;
while (any_change && loop < MAX_ADJUST_LOOP) {
any_change = 0;
int mother_changed = adjust_mother_relationships(result, config_result, n, NULL, 0);
if (mother_changed) any_change = 1;
MagnificationCheck chk = calculate_magnification(*result, *config_result, n);
if (!chk.is_balanced) {
if (!adjust_magnification(result, config_result, n, NULL, 0)) {
break;
}
any_change = 1;
}
int elder_changed = adjust_elder_wolf(result, config_result, n, NULL, 0);
if (elder_changed) any_change = 1;
loop++;
}
if (!any_change && loop < MAX_ADJUST_LOOP) {
MagnificationCheck chk = calculate_magnification(*result, *config_result, n);
if (chk.is_balanced) {
return 1;
}
}
}
return 0;
}
// ========== 生成单个配置(限池模式) ==========
/**
* 限池模式:从给定身份池中生成单个有效配置
* @param n 游戏人数
* @param result 输出参数:选择结果
* @param config_result 输出参数:配置信息
* @param pool 身份池指针数组
* @param pool_size 池大小
* @return 1表示成功,0表示失败
*/
int generate_single_configuration_from_pool(int n, SelectionResult* result, ConfigResult* config_result,
Identity* pool[], int pool_size) {
int max_attempts = MAX_CONFIG_ATTEMPTS;
for (int attempt = 0; attempt < max_attempts; attempt++) {
*config_result = generate_config(n);
*result = select_identities_from_pool(config_result, pool, pool_size);
if (result->selected_count == 0) continue;
if (!validate_selection(result, *config_result)) continue;
int any_change = 1;
int loop = 0;
while (any_change && loop < MAX_ADJUST_LOOP) {
any_change = 0;
int mother_changed = adjust_mother_relationships(result, config_result, n, pool, pool_size);
if (mother_changed) any_change = 1;
MagnificationCheck chk = calculate_magnification(*result, *config_result, n);
if (!chk.is_balanced) {
if (!adjust_magnification(result, config_result, n, pool, pool_size)) {
break;
}
any_change = 1;
}
int elder_changed = adjust_elder_wolf(result, config_result, n, pool, pool_size);
if (elder_changed) any_change = 1;
loop++;
}
if (!any_change && loop < MAX_ADJUST_LOOP) {
MagnificationCheck chk = calculate_magnification(*result, *config_result, n);
if (chk.is_balanced) {
return 1;
}
}
}
return 0;
}
// ========== 排序比较函数(用于显示) ==========
/**
* 身份比较函数,用于显示时的排序
* 按类别顺序:强神、弱神、狼人、独立、不定
* 同一类别内按原始分类(验人系、女巫系、其他),再按算分降序,最后按名称
*/
int compare_identities_for_display(const void* a, const void* b) {
Identity* id_a = *(Identity**)a;
Identity* id_b = *(Identity**)b;
int cat_order[5] = {CATEGORY_STRONG_CLERGY, CATEGORY_WEAK_CLERGY,
CATEGORY_WEREWOLF, CATEGORY_INDEPENDENT, CATEGORY_INDEFINITE};
int order_a = -1, order_b = -1;
for (int i = 0; i < 5; i++) {
if (id_a->category == cat_order[i]) order_a = i;
if (id_b->category == cat_order[i]) order_b = i;
}
if (order_a != order_b) return order_a - order_b;
int sub_a = (id_a->original_category == ORIG_CAT_APPRAISAL || id_a->original_category == ORIG_CAT_WITCH) ?
id_a->original_category : 2;
int sub_b = (id_b->original_category == ORIG_CAT_APPRAISAL || id_b->original_category == ORIG_CAT_WITCH) ?
id_b->original_category : 2;
if (sub_a != sub_b) return sub_a - sub_b;
double score_a = calculate_score(id_a, game_players);
double score_b = calculate_score(id_b, game_players);
if (fabs(score_b - score_a) > 1e-6) return (score_b > score_a) ? 1 : -1;
return strcmp(id_a->name, id_b->name);
}
/**
* 统计项比较函数,用于测试结果输出
* 按类别顺序,同一类别内按出场率降序,再按名称
* @param a 指向 StatItem 的指针
* @param b 指向 StatItem 的指针
* @return 比较结果(负数、零、正数)
*/
int compare_stats_items(const void* a, const void* b) {
StatItem* ia = (StatItem*)a;
StatItem* ib = (StatItem*)b;
if (ia->cat != ib->cat) return ia->cat - ib->cat;
if (fabs(ib->rate - ia->rate) > 1e-6) return (ib->rate > ia->rate) ? 1 : -1;
return strcmp(ia->name, ib->name);
}
/**
* 打印身份池内容
* @param pool 身份池指针数组
* @param pool_size 池大小
*/
void print_identity_pool(Identity* pool[], int pool_size) {
printf("\n========== 构建的身份池 ==========\n");
// 复制一份指针并排序,使输出有序
Identity* sorted_pool[POOL_SIZE];
for (int i = 0; i < pool_size; i++) sorted_pool[i] = pool[i];
qsort(sorted_pool, pool_size, sizeof(Identity*), compare_identities_for_display);
int cur_cat = -1;
for (int i = 0; i < pool_size; i++) {
Identity* id = sorted_pool[i];
if (id->category == CATEGORY_INDEPENDENT || id->category == CATEGORY_INDEFINITE) {
if (cur_cat != -2) {
printf("\n其他:\n");
cur_cat = -2;
}
printf(" %s\n", id->name);
} else {
if (id->category != cur_cat) {
cur_cat = id->category;
printf("\n%s:\n", category_names[cur_cat]);
}
if (id->original_category == ORIG_CAT_APPRAISAL) {
printf(" %s (验人系)\n", id->name);
} else if (id->original_category == ORIG_CAT_WITCH) {
printf(" %s (女巫系)\n", id->name);
} else {
printf(" %s\n", id->name);
}
}
}
printf("===================================\n");
}
// ========== 格式化输出配置 ==========
/**
* 格式化输出一个配置
* @param sel 选择结果
* @param config 配置信息
* @param config_num 配置序号
* @param n 游戏人数
*/
void print_configuration_formatted(SelectionResult sel, ConfigResult config, int config_num, int n) {
printf("\n========== 配置 #%d ==========\n", config_num);
qsort(sel.selected_identities, sel.selected_count, sizeof(Identity*), compare_identities_for_display);
int cnt_wolf = 0, cnt_strong = 0, cnt_weak = 0, cnt_indep = 0, cnt_indef = 0;
for (int i = 0; i < sel.selected_count; i++) {
Category cat = sel.selected_identities[i]->category;
if (cat == CATEGORY_WEREWOLF) cnt_wolf++;
else if (cat == CATEGORY_STRONG_CLERGY) cnt_strong++;
else if (cat == CATEGORY_WEAK_CLERGY) cnt_weak++;
else if (cat == CATEGORY_INDEPENDENT) cnt_indep++;
else if (cat == CATEGORY_INDEFINITE) cnt_indef++;
}
int other_total = cnt_indep + cnt_indef;
printf("狼人: %d 强神: %d 弱神: %d 其他: %d\n", cnt_wolf, cnt_strong, cnt_weak, other_total);
printf("身份列表:\n");
int cur_cat = -1;
for (int i = 0; i < sel.selected_count; i++) {
Identity* id = sel.selected_identities[i];
if (id->category == CATEGORY_INDEPENDENT || id->category == CATEGORY_INDEFINITE) {
if (cur_cat != -2) {
printf("\n其他:\n");
cur_cat = -2;
}
printf(" %s [%.0f] (%s)\n", id->name, calculate_score(id, n), faction_names[id->faction]);
} else {
if (id->category != cur_cat) {
cur_cat = id->category;
printf("\n%s:\n", category_names[cur_cat]);
}
const char* sub = "";
if (id->original_category == ORIG_CAT_APPRAISAL) sub = " (验人系)";
else if (id->original_category == ORIG_CAT_WITCH) sub = " (女巫系)";
printf(" %s [%.0f]%s\n", id->name, calculate_score(id, n), sub);
}
}
MagnificationCheck chk = calculate_magnification(sel, config, n);
double minb, maxb;
get_balance_range(current_mode, n, &minb, &maxb);
printf("\n倍率: %.2f\n", chk.magnification, minb, maxb);
}
// ========== 限池模式运行函数 ==========
/**
* 运行限池模式
* 用户输入游戏人数,构建身份池,然后生成3个不重复的配置
*/
void run_limited_pool_mode() {
printf("\n========== 运行限池模式 ==========\n");
printf("目标配置数量: %d\n", TARGET_CONFIG_COUNT);
printf("请输入游戏人数(%d-%d人): ", MIN_PLAYERS, MAX_PLAYERS);
scanf("%d", &game_players);
if (game_players < MIN_PLAYERS || game_players > MAX_PLAYERS) {
printf("游戏人数必须在%d-%d人之间!\n", MIN_PLAYERS, MAX_PLAYERS);
return;
}
initialize_identities();
// 构建身份池
Identity* pool[POOL_SIZE];
int pool_size = build_identity_pool(pool);
print_identity_pool(pool, pool_size);
if (pool_size == 0) {
printf("身份池构建失败!\n");
return;
}
printf("身份池构建完成,共 %d 个身份。\n", pool_size);
double minb, maxb;
get_balance_range(current_mode, game_players, &minb, &maxb);
printf("当前平衡范围: [%.2f, %.2f]\n", minb, maxb);
printf("\n开始生成%d个不重复的配置...\n", TARGET_CONFIG_COUNT);
int success = 0, attempts = 0;
while (success < TARGET_CONFIG_COUNT && attempts < MAX_CONFIG_GENERATIONS) {
attempts++;
SelectionResult sel;
ConfigResult conf;
if (generate_single_configuration_from_pool(game_players, &sel, &conf, pool, pool_size)) {
success++;
print_configuration_formatted(sel, conf, success, game_players);
}
}
printf("\n========== 生成完成 ==========\n");
if (success >= TARGET_CONFIG_COUNT) printf("✓ 成功生成%d个配置\n", TARGET_CONFIG_COUNT);
else printf("警告: 未达到目标配置数量\n");
}
// ========== 综合模式运行函数 ==========
/**
* 运行综合模式(原标准模式)
* 用户输入游戏人数,直接生成3个不重复的配置
*/
void run_comprehensive_mode() {
printf("\n========== 运行综合模式 ==========\n");
printf("目标配置数量: %d\n", TARGET_CONFIG_COUNT);
printf("请输入游戏人数(%d-%d人): ", MIN_PLAYERS, MAX_PLAYERS);
scanf("%d", &game_players);
if (game_players < MIN_PLAYERS || game_players > MAX_PLAYERS) {
printf("游戏人数必须在%d-%d人之间!\n", MIN_PLAYERS, MAX_PLAYERS);
return;
}
initialize_identities();
double minb, maxb;
get_balance_range(current_mode, game_players, &minb, &maxb);
printf("当前平衡范围: [%.2f, %.2f]\n", minb, maxb);
printf("\n开始生成%d个不重复的配置...\n", TARGET_CONFIG_COUNT);
int success = 0, attempts = 0;
while (success < TARGET_CONFIG_COUNT && attempts < MAX_CONFIG_GENERATIONS) {
attempts++;
SelectionResult sel;
ConfigResult conf;
if (generate_single_configuration(game_players, &sel, &conf)) {
success++;
print_configuration_formatted(sel, conf, success, game_players);
}
}
printf("\n========== 生成完成 ==========\n");
if (success >= TARGET_CONFIG_COUNT) printf("✓ 成功生成%d个配置\n", TARGET_CONFIG_COUNT);
else printf("警告: 未达到目标配置数量\n");
}
// ========== 测试模式 ==========
/**
* 初始化测试模式统计
*/
void initialize_test_stats() {
memset(&test_stats, 0, sizeof(test_stats));
}
/**
* 更新测试模式统计
* @param sel 成功生成的选择结果
*/
void update_test_stats(SelectionResult sel) {
for (int i = 0; i < sel.selected_count; i++)
test_stats.identity_appearances[sel.selected_identities[i]->id]++;
}
/**
* 打印测试模式结果
*/
void print_test_results() {
printf("\n========== 测试模式结果 ==========\n");
printf("总模拟次数: %d\n", test_stats.total_simulations);
printf("成功生成配置: %d\n", test_stats.successful_generations);
printf("成功率: %.2f%%\n", (test_stats.successful_generations * 100.0) / test_stats.total_simulations);
StatItem items[MAX_IDENTITIES];
int item_cnt = 0;
for (int i = 0; i < total_identities; i++) {
double rate = test_stats.identity_appearances[i] * 100.0 / test_stats.successful_generations;
if (rate > 0.01) {
strcpy(items[item_cnt].name, identities[i].name);
if (identities[i].category == CATEGORY_STRONG_CLERGY) items[item_cnt].cat = 0;
else if (identities[i].category == CATEGORY_WEAK_CLERGY) items[item_cnt].cat = 1;
else if (identities[i].category == CATEGORY_WEREWOLF) items[item_cnt].cat = 2;
else items[item_cnt].cat = 3;
items[item_cnt].original_category = identities[i].original_category;
items[item_cnt].faction = identities[i].faction;
items[item_cnt].rate = rate;
item_cnt++;
}
}
qsort(items, item_cnt, sizeof(StatItem), compare_stats_items);
printf("\n身份出场率 (按类别及出场率排序):\n");
int cur_cat = -1;
for (int i = 0; i < item_cnt; i++) {
if (items[i].cat != cur_cat) {
cur_cat = items[i].cat;
if (cur_cat == 0) printf("\n【强神】\n");
else if (cur_cat == 1) printf("\n【弱神】\n");
else if (cur_cat == 2) printf("\n【狼人】\n");
else printf("\n【其他】\n");
}
const char* tag = "";
if (items[i].cat != 3) {
if (items[i].original_category == ORIG_CAT_APPRAISAL) tag = " (验人系)";
else if (items[i].original_category == ORIG_CAT_WITCH) tag = " (女巫系)";
} else {
tag = (items[i].faction == FACTION_INDEPENDENT) ? " (独立)" : " (不定)";
}
printf(" %-16s 出场率: %.2f%%%s\n", items[i].name, items[i].rate, tag);
}
}
/**
* 运行测试模式
* 对指定人数分别测试限池模式和综合模式,各10000次,并输出身份出场率和入池概率
*/
void run_test_mode() {
printf("\n========== 运行测试模式 ==========\n");
printf("请输入测试人数(9-18): ");
int test_players;
scanf("%d", &test_players);
if (test_players < 9 || test_players > 18) {
printf("人数必须在9-18之间!\n");
return;
}
game_players = test_players;
initialize_identities();
printf("将分别测试限池模式和综合模式,各 %d 局(%d人局)\n", TEST_COUNT, test_players);
// 统计结构
TestModeStats stats_pool = {0};
TestModeStats stats_comp = {0};
long long pool_appearances[MAX_IDENTITIES] = {0}; // 身份在池中出现的次数
int pool_build_success = 0; // 成功构建池的次数
// ---------- 限池模式测试 ----------
printf("\n--- 开始测试限池模式 ---\n");
for (int i = 0; i < TEST_COUNT; i++) {
if (i % 1000 == 0) printf("限池模式进度: %d / %d\n", i, TEST_COUNT);
Identity* pool[POOL_SIZE];
int pool_size = build_identity_pool(pool);
if (pool_size == 0) {
stats_pool.total_simulations++;
continue;
}
// 成功构建池
pool_build_success++;
for (int k = 0; k < pool_size; k++) {
pool_appearances[pool[k]->id]++;
}
SelectionResult sel;
ConfigResult conf;
if (generate_single_configuration_from_pool(test_players, &sel, &conf, pool, pool_size)) {
stats_pool.successful_generations++;
for (int j = 0; j < sel.selected_count; j++) {
stats_pool.identity_appearances[sel.selected_identities[j]->id]++;
}
}
stats_pool.total_simulations++;
}
// ---------- 综合模式测试 ----------
printf("\n--- 开始测试综合模式 ---\n");
for (int i = 0; i < TEST_COUNT; i++) {
if (i % 1000 == 0) printf("综合模式进度: %d / %d\n", i, TEST_COUNT);
SelectionResult sel;
ConfigResult conf;
if (generate_single_configuration(test_players, &sel, &conf)) {
stats_comp.successful_generations++;
for (int j = 0; j < sel.selected_count; j++) {
stats_comp.identity_appearances[sel.selected_identities[j]->id]++;
}
}
stats_comp.total_simulations++;
}
// ---------- 输出限池模式结果(出场率) ----------
printf("\n========== 限池模式测试结果(%d人局)==========\n", test_players);
printf("总模拟次数: %d\n", stats_pool.total_simulations);
printf("成功生成配置: %d\n", stats_pool.successful_generations);
if (stats_pool.total_simulations > 0) {
printf("成功率: %.2f%%\n", (stats_pool.successful_generations * 100.0) / stats_pool.total_simulations);
}
printf("\n身份出场率 (限池模式):\n");
StatItem items[MAX_IDENTITIES];
int item_cnt = 0;
for (int i = 0; i < total_identities; i++) {
double rate = stats_pool.identity_appearances[i] * 100.0 / stats_pool.successful_generations;
if (rate > 0.01) {
strcpy(items[item_cnt].name, identities[i].name);
if (identities[i].category == CATEGORY_STRONG_CLERGY) items[item_cnt].cat = 0;
else if (identities[i].category == CATEGORY_WEAK_CLERGY) items[item_cnt].cat = 1;
else if (identities[i].category == CATEGORY_WEREWOLF) items[item_cnt].cat = 2;
else items[item_cnt].cat = 3;
items[item_cnt].original_category = identities[i].original_category;
items[item_cnt].faction = identities[i].faction;
items[item_cnt].rate = rate;
item_cnt++;
}
}
qsort(items, item_cnt, sizeof(StatItem), compare_stats_items);
int cur_cat = -1;
for (int i = 0; i < item_cnt; i++) {
if (items[i].cat != cur_cat) {
cur_cat = items[i].cat;
if (cur_cat == 0) printf("\n【强神】\n");
else if (cur_cat == 1) printf("\n【弱神】\n");
else if (cur_cat == 2) printf("\n【狼人】\n");
else printf("\n【其他】\n");
}
const char* tag = "";
if (items[i].cat != 3) {
if (items[i].original_category == ORIG_CAT_APPRAISAL) tag = " (验人系)";
else if (items[i].original_category == ORIG_CAT_WITCH) tag = " (女巫系)";
} else {
tag = (items[i].faction == FACTION_INDEPENDENT) ? " (独立)" : " (不定)";
}
printf(" %-16s 出场率: %.2f%%%s\n", items[i].name, items[i].rate, tag);
}
// ---------- 输出限池模式结果(入池概率) ----------
printf("\n身份入池概率 (限池模式):\n");
item_cnt = 0;
for (int i = 0; i < total_identities; i++) {
double rate = pool_appearances[i] * 100.0 / pool_build_success;
if (rate > 0.01) {
strcpy(items[item_cnt].name, identities[i].name);
if (identities[i].category == CATEGORY_STRONG_CLERGY) items[item_cnt].cat = 0;
else if (identities[i].category == CATEGORY_WEAK_CLERGY) items[item_cnt].cat = 1;
else if (identities[i].category == CATEGORY_WEREWOLF) items[item_cnt].cat = 2;
else items[item_cnt].cat = 3;
items[item_cnt].original_category = identities[i].original_category;
items[item_cnt].faction = identities[i].faction;
items[item_cnt].rate = rate;
item_cnt++;
}
}
qsort(items, item_cnt, sizeof(StatItem), compare_stats_items);
cur_cat = -1;
for (int i = 0; i < item_cnt; i++) {
if (items[i].cat != cur_cat) {
cur_cat = items[i].cat;
if (cur_cat == 0) printf("\n【强神】\n");
else if (cur_cat == 1) printf("\n【弱神】\n");
else if (cur_cat == 2) printf("\n【狼人】\n");
else printf("\n【其他】\n");
}
const char* tag = "";
if (items[i].cat != 3) {
if (items[i].original_category == ORIG_CAT_APPRAISAL) tag = " (验人系)";
else if (items[i].original_category == ORIG_CAT_WITCH) tag = " (女巫系)";
} else {
tag = (items[i].faction == FACTION_INDEPENDENT) ? " (独立)" : " (不定)";
}
printf(" %-16s 入池概率: %.2f%%%s\n", items[i].name, items[i].rate, tag);
}
// ---------- 输出综合模式结果 ----------
printf("\n========== 综合模式测试结果(%d人局)==========\n", test_players);
printf("总模拟次数: %d\n", stats_comp.total_simulations);
printf("成功生成配置: %d\n", stats_comp.successful_generations);
if (stats_comp.total_simulations > 0) {
printf("成功率: %.2f%%\n", (stats_comp.successful_generations * 100.0) / stats_comp.total_simulations);
}
printf("\n身份出场率 (综合模式):\n");
item_cnt = 0;
for (int i = 0; i < total_identities; i++) {
double rate = stats_comp.identity_appearances[i] * 100.0 / stats_comp.successful_generations;
if (rate > 0.01) {
strcpy(items[item_cnt].name, identities[i].name);
if (identities[i].category == CATEGORY_STRONG_CLERGY) items[item_cnt].cat = 0;
else if (identities[i].category == CATEGORY_WEAK_CLERGY) items[item_cnt].cat = 1;
else if (identities[i].category == CATEGORY_WEREWOLF) items[item_cnt].cat = 2;
else items[item_cnt].cat = 3;
items[item_cnt].original_category = identities[i].original_category;
items[item_cnt].faction = identities[i].faction;
items[item_cnt].rate = rate;
item_cnt++;
}
}
qsort(items, item_cnt, sizeof(StatItem), compare_stats_items);
cur_cat = -1;
for (int i = 0; i < item_cnt; i++) {
if (items[i].cat != cur_cat) {
cur_cat = items[i].cat;
if (cur_cat == 0) printf("\n【强神】\n");
else if (cur_cat == 1) printf("\n【弱神】\n");
else if (cur_cat == 2) printf("\n【狼人】\n");
else printf("\n【其他】\n");
}
const char* tag = "";
if (items[i].cat != 3) {
if (items[i].original_category == ORIG_CAT_APPRAISAL) tag = " (验人系)";
else if (items[i].original_category == ORIG_CAT_WITCH) tag = " (女巫系)";
} else {
tag = (items[i].faction == FACTION_INDEPENDENT) ? " (独立)" : " (不定)";
}
printf(" %-16s 出场率: %.2f%%%s\n", items[i].name, items[i].rate, tag);
}
}
// ========== 主函数 ==========
int main() {
SetConsoleOutputCP(65001); // 设置控制台编码为UTF-8,支持中文显示
srand((unsigned)time(NULL));
printf("========== 狼人游戏 随机配置生成器 ==========\n");
printf("请选择模式 (1-限池模式, 2-综合模式, 3-测试模式): ");
int mode;
scanf("%d", &mode);
if (mode < 1 || mode > 3) mode = 2;
current_mode = mode - 1;
printf("已选择: %s\n", mode_names[current_mode]);
switch (current_mode) {
case MODE_LIMITED_POOL: run_limited_pool_mode(); break;
case MODE_COMPREHENSIVE: run_comprehensive_mode(); break;
case MODE_TEST: run_test_mode(); break;
}
system("pause");
return 0;
} |
|