七年后重做王者荣耀数据分析:这次数据是从游戏进程里直接拿的

目录

声明:本文只涉及个人设备与个人账号可见的数据,不涉及任何线上服务的越权访问,也不发布采集代码。文中所有数字都来自我自己那台机器上的库,初稿由 AI 整理。结论随时可能被下一轮数据推翻。

2019 年 4 月我写过一篇《抓取、分析王者荣耀高分段战绩》,那会儿走的是爬王者营地这条路,准备一堆账号轮着换 token,接口被封了就等十二个小时解封,前后花了两个月才攒到 6.5 万局对局和 34.6 万个玩家,然后写了篇《王者荣耀数据分析 1》。标题里那个「1」我当时是打算写成一个系列的,结果七年过去也没有第二篇。

这篇就是那个第二篇。

为什么这次不用爬虫了

上一篇《从抓包到改字段》讲的是怎么在游戏进程里挂 hook,收包和发包各拦一处,每条消息用 IL2CPP 反射递归读成 JSON。那套东西做完之后我才反应过来,它其实把七年前最麻烦的问题从根上绕开了。

爬营地的本质是模拟一个第三方客户端去调它的开放接口,所以你得处理它的登录态、版本校验和风控,而这几样东西每隔一段时间就会变一次,变一次你就得跟着改一次,这也是当年那个项目后来没有维护下去的直接原因。除此之外,营地能给你的字段也只是它愿意展示的那些,游戏结算里真正丰富的那部分它根本不透出,所以当年能做的分析很有限。

这次直接使用游戏客户端。游戏里点开某个人的战绩面板,客户端会发一条 1441,服务器回一条 1442。我已经能拦住收发口,也能构造一条 1441 塞进发送队列,于是采集器只需要控制查询节奏,再把响应落库。请求沿用客户端的长连接、登录态和加密,登录、鉴权、版本校验都交给游戏处理。

节奏当然得自己控。结果码 3 是「请求太频繁」,撞上了游戏里还会弹提示,所以我做了个自适应节流,连续若干条正常就把间隔乘 0.9,撞到 3 就乘 2 并且静默一分钟,两头都夹在设定的上下限里,跑一会儿就稳定在两秒一条左右。这里还有两个码需要单独对待,40007 是这个玩家不让查,实测慢到三秒半一条它照样返回,跟速率完全没关系,15001 是 uid 与大区对不上,属于数据问题。这两个如果不摘出来,节流会一直误判成撞了限流,间隔越退越大,最后慢得没法看。

查战绩还是查档案

真正决定效率的是选择查什么,这一点我一开始想岔了。玩家档案 2606 查一次只拿到一个人的资料,而战绩 1441 查一次回十局对局,每局十个人,一次就是一百条参战记录,里面出现的陌生 uid 还会自动滚进待查队列,两者的产出差着两个数量级。

所以我在采集器上加了个模式开关,「只查战绩」这一档纯粹是为了铺量。档案里那些 MMR、ELO、收藏值确实只有 2606 才有,但想看某个具体的人的时候单独补一条就够了,没必要每个人都查一遍。切过去之后,3.7 万局对局全部落在 7 月 27 日的 12 点到 19 点之间,七个小时。

2019 年那次这次
对局6.5 万3.7 万
参战记录65 万36.9 万
玩家34.6 万19.7 万(其中 6494 人拉到了完整档案)
覆盖大区未记录1299 个
采集耗时两个月七个小时

采集概览里显示了当前的玩家、对局和参战记录数量,以及每小时入库量

对局数还没赶上七年前,毕竟只跑了一个下午,但真正的差别在字段上,这次每条参战记录带六十多个字段,其中好几个是营地根本不会展示的,下面几件事全是从那些字段里翻出来的。

有个前提我得先讲清楚,这批样本严重偏向高分段。排位局里 86.6% 的人次是最强王者,12.3% 是星耀,剩下所有段位加起来才 1.1%,原因是队列从我自己的战绩滚出来,滚到的自然都是同分段的人。2019 年那次也是这个情况,当时我在文章里写的是「对局都是高段位(最低王者)的排位赛」,所以下面所有结论的适用范围,是王者和星耀这两档。

累计星数分布图用参考线标出了钻石、星耀、王者及王者星级区间

这里还踩到一个字段问题。档案里的 bGradeOfRank=1626 都表示最强王者,服务端为什么同时使用两种值还没查清。最直接的判断依据是星数:只有 16 的星数会超过 5,最高到 171;16 和 26 对应的历史段位分布也相同。页面最初按字段编号画柱状图,把 16 翻译成了永恒钻石Ⅴ,于是钻石位置冒出一根很夸张的柱子。

我把图改成了累计星数分布。青铜到星耀按各小段所需星数累加,王者门口是 92 星,之后直接加王者星数。16 和 26 都从 92 起算。这个换算依赖当前通行的升段星数,真正的永恒钻石Ⅴ又和王者共用了 16,所以这批数据无法准确拆出钻石Ⅴ;图上的参考线适合看大致分区。

为什么把库换成了 Postgres

实时报文台那边用的是 SQLite,那边写进去的是流水,主要为了回看和检索,进程内嵌一个库最省事,多一个外部依赖反而麻烦。采集这边换成了 Postgres,理由是这些查询里有大量的自连接(同一局里的人两两配对生成关系图的边)、窗口函数(追一个玩家的昵称什么时候变的)和 corr() 这类统计聚合,还要给昵称建 trigram 索引做模糊搜索,这些东西 SQLite 要么没有要么写起来非常别扭。代价是多一个 docker compose,我觉得挺划算。

开黑到底有没有用

结算数据里每个人身上有个 bTeamAcntNum,记的是这个人排队的时候几个人一起,1 就是单排,5 就是五排。这个字段一出来我第一个想问的问题就很俗,开黑能不能提高胜率。

按人数分组一看,四档胜率全挤在 50% 附近,最高的单排 50.56%,最低的五排 50.24%,差不到半个百分点;死亡数倒是很规律地从单排的 4.32 一路降到五排的 3.17。

一起排几个人次胜率平均死亡
1(单排)137,51350.56%4.32
263,99350.33%3.50
319,26550.39%3.36
529,65050.24%3.17

看到这里我差点写下「开黑让你死得少但赢不了更多」。这张胜率表少了对手构成,单独看它无法回答开黑效果,于是我又去查了同局另一边的 bTeamAcntNum

查法很简单,把每支队伍五个人的 bTeamAcntNum 降序拼成一个串,2+2+1+1+1 就是一对双排加三个散人,5+5+5+5+5 就是整队五排,然后拿它跟同一局对面那队的串做字符串比较。

只留双方各五条记录完整、没有人机、时长超过五分钟的排位,再按对局去重,一共是 23,861 局。双方的开黑人数构成逐位相同。

队里最大的开黑规模对局数对面构成相同
全是单排5,489全部
有 2 人一起排12,306全部
有 3 人一起排3,115全部
有 5 人一起排2,951全部

数据分析页按 bTeamAcntNum 对照两边的开黑规模,四档的构成都完全一致

五排对五排本来就在预期内,混编队伍的逐位对应更值得看。你这边是 3+3+3+1+1,对面也是 3+3+3+1+1;一对双排加三个散人,对面仍是同一套人数配置。这个结果只覆盖开黑人数,玩家水平、分路和隐藏分仍可能有差别。单凭这批对局也算不出「开黑本身提高了多少胜率」,因为系统已经在匹配阶段控制了对照条件。

最常见的几种构成是这样:

构成队数
2+2+1+1+119,420
1+1+1+1+111,177
5+5+5+5+55,930
3+3+3+1+15,393
2+2+2+2+15,364

五排的助攻参与度和时长

这批完整排位里的五排局都是五排对五排。我把整队五排、混编队伍和五个散人的汇总数据放在一起看,口径是全队助攻数除以全队击杀数。这个数记录每个人头平均有多少队友参与。这里只是观察性比较,英雄阵容、玩家实力和团战频率都会影响结果。

队伍类型队数每个人头带几个助攻全队人头全队死亡
整队五排5,9302.1015.9115.85
混编31,0621.8818.8218.74
五个散人11,1771.7322.9122.70

控制台把整队五排、混编和五个散人的助攻与击杀放在一张表里

五排每个人头挂 2.10 个助攻,五个散人的队伍是 1.73,高出 21%。这个比值记录一颗人头平均有多少队友参与,也会受到英雄阵容和团战频率影响,所以我把它当作配合方式的一个侧面。

我原先看到五排人头少,直觉上以为比赛会拖得更久,结果把时长算出来正好相反。这里按对局去重,只留双方五人数据完整、没有 AI、时长超过五分钟的排位:

对局构成对局数平均时长中位数12 分钟内20 分钟以上
整队五排2,95113:5113:0634.29%7.79%
混编15,42114:4914:1122.26%10.70%
五个散人5,48915:5415:1813.35%16.12%

五排、混编和五个散人对局的时长分布,五排曲线更早达到峰值

整队五排比五个散人平均早 2 分 03 秒结束,中位数差 2 分 12 秒。五排局有三分之一在 12 分钟内打完,散人局只有一成多;20 分钟以上的占比则是 7.79% 对 16.12%,差了一倍。

再看推塔,五排获胜方平均推掉 4.72 座,五个散人的获胜方是 4.71 座;五排败方平均推掉 1.17 座,散人败方是 1.87 座。全场击杀为 31.72 对 45.77。五排局击杀更少、结束更早,双方推塔数的差距也更大。库里没有投降字段,快速推进和提前投降分别贡献了多少,目前算不出来。

有一个字段直接把人机认出来了

战绩里每个人带一个 bIsAI。我一开始把它当作简单的人机标记,扫过全库才发现底下分成两拨。

一拨是人机槽位,大区号为 0,uid 只有 11 到 25 这十一个,名字每局重新抽一个,「蔡文姬[电脑]」「峡谷训练师」「泥石流怪兽」轮着来,这批一眼就是假的,没什么好讨论的。另一拨就有意思了,它们有正常的大区号、正常的 uid、正常的昵称,一共 5,526 个身份,单看任何一条记录都跟真人没有区别。我最初的判断是掉线之后被系统接管的真人,毕竟王者里断线确实会由 AI 托管,这个解释听上去也很合理。

然后我扫到了 bHeroProficiencyLv,英雄熟练度。

熟练度 = 0熟练度 > 0
真人记录361,4790
带 AI 标记的记录25,545

人机分析页里,英雄熟练度字段把真人记录和带 AI 标记的记录分成了两组

36 万条真人记录里的这个字段全是 0,带 AI 标记的记录则有 99.96% 是非零的。非零值识别出了 5,545 条 AI 记录,没有真人被误标;另有 2 条 AI 记录的值也是 0。我猜服务端生成结算数据时走了两条代码路径,人机路径写入英雄熟练度,真人路径留了空值。这个字段比战斗表现稳定得多。

其他字段也能对上。bTeamAcntNum 在这批记录里恒等于 1,5,545 条一个例外都没有,真人里有 34.7% 是两人以上一起排的。5,526 个身份里有 5,505 个只出现过一局,21 个出现过两局,之后就不再露面。掉线托管的活人还会在其他对局中以正常身份出现,这批记录没有这种复用。

段位字段的平均值是 22,落在星耀档;星数平均只有 4.36,93% 集中在 0 到 5 星。真人平均 62.26 星,73% 在 6 星以上。真人数据里的段位和星数紧密相关,这批记录断开了这层关系。它们的挂机和被踢记录也都是零,真人分别有 1,914 条和 413 条。战斗指标的差距较小:平均死亡 4.64 对 3.76,助攻 5.14 对 7.06,对英雄伤害 6.17 万对 7.52 万。

它们在排位里怎么出现

我再按对局去重,只看 game_type=4,并把大区号正常、bIsAI=1 的记录算作这批人机。25,527 局排位中有 1,664 局出现过,比例是 6.52%。

排位人机的分段出现率和单局数量分布,低分段以及一局两个人机的柱子最明显

数量分布里有两处很整齐。1,176 局恰好出现两个人机,而且全部是一边一个。另有 484 局出现完整的五人人机队,其中 37 局在另一边还多放了一个人机。这支五人人机队只赢 12 局,胜率 2.48%;这些对局的中位时长是 12:16,正常排位是 14:17。至于那 12 局,碰上样本胜率 2.48% 的队伍还能输,所谓的福利局都能打输,确实没什么好解释的。

人机出现率随分段迅速下降。每局真人的平均段位低于王者时,33.85% 的对局有人机;王者 0~24 星是 8.97%,25~49 星是 1.24%,50~99 星只剩 0.02%,100 星以上一局都没有。当前数据里能看到两种安排:一边一个的对称填充,以及一整队胜率极低的人机对手。完整人机队在结果上给真人提供了一场高胜率对局,具体触发条件和系统目的仍然未知。

碰到五人人机之前,上一条已采集记录打成什么样

战绩接口一次只返回最近十局,所以这个问题只能查到一部分人。五人人机队对面共有 2,383 条真人参战记录,涉及 2,012 名玩家,其中 625 条能在库里找到更早的一条对局记录。按这 625 条记录统计,上一条记录输了 519 条,败率 83.04%。

同一个人可能多次碰到五人人机。为了做普通排位对照,我先给每名玩家只留最早一次遭遇,2,012 人中还剩 254 人能回溯上一条已采集记录,覆盖率 12.62%。这 254 人的上一条记录为 33 胜、221 负,胜率 12.99%。这个去重口径只用于分层对照,后面的多条记录窗口会把每次遭遇都算进去。

低分段玩家遇到人机的频率本来就高,对照也要管住段位和日期。我按北京时间自然月和当局累计星数 5 星一档,把这些玩家与同期普通排位匹配,同时排除所有进入过五人人机组的玩家。254 人中有 249 人所在分层能找到对照:

上一条记录表现五人人机局对手普通排位对照
胜率11.65%65.53%
平均评分7.5388.465
平均 K/D/A4.201 / 5.410 / 5.6874.428 / 3.858 / 7.866
平均 KDA2.5365.076

完整五人人机队的胜负,以及对手上一条已采集记录与同期同分段普通排位的胜负和表现对照

分月、分段以后,上一条记录的胜率仍差 53.88 个百分点。目标组的死亡更多,助攻和 KDA 也低很多,击杀数则很接近。数据库里能查到的上一条记录表现,与随后碰到完整人机队有很强的关联。这个对照只覆盖 249 名玩家,触发条件仍然未知;历史战绩缺失的玩家也可能改变总体结果。

单条记录只能看到最后一个点。我又以每次遭遇为单位,回溯最近 1、3、5、8、10 条已采集排位记录。为了让五个窗口可以直接比较,下面只用能回溯满 10 条的固定样本:402 条遭遇记录,涉及 167 名玩家和 372 场五人人机局,覆盖全部 2,383 条遭遇记录的 16.87%。

回溯窗口窗口胜率窗口内全败多数对局告负
前 1 条15.92%84.08%84.08%
前 3 条23.22%52.24%83.08%
前 5 条32.64%6.47%81.34%
前 8 条41.14%0%64.93%
前 10 条43.53%0%62.44%

每次碰到完整五人人机队前,最近十条已采集排位记录的逐局胜率和不同回溯窗口分布

逐条统计时,目标局前第 1、2、3 条排位记录的胜率分别是 15.92%、24.38%、29.35%;第 4 条升到 49.25%,第 5~10 条落在 44.28%~57.71%。前十条的整体胜率为 43.53%,最接近目标局的三条降到 23.22%,输局集中在临近目标局的短窗口里。

重复玩家需要单独检查。161 名玩家碰到过不止一次,相关参战记录占 22.32%,最多的一人碰到 23 次。改成每名玩家等权后,前十条胜率是 42.43%,前三条是 20.00%,短窗口下降仍然存在。

库里没有保存每次战绩查询返回的完整十局批次,两条记录之间可能夹着没有采集到的对局。这里的「前三条全败」只描述已采集排位记录,暂时不能写成三连败。当前数据能确认短期输局与五人人机局同时出现,系统是否读取近期战绩、具体看几局,还要靠连续采集继续查。

一个 77.1% 胜率样本,拆开以后是什么样

磊哥相关内容里的「牢玩家」,指每局认真打、常拿高评分,随后被匹配机制安排去承担困难对局、长期被控制胜率的玩家。这个词和账号年限没有关系。社区流传的应对玩法包括梦游流:少拿人头、压低评分,把胜负交给队友,期望后续碰到容易赢的对局。相关说法可以在梦游流庄周教学视频知乎上的「牢玩家定律」讨论一份 2024 年的玩法整理里看到。

库里有一个很醒目的样本。该玩家最新档案为 65 星、ELO 1683、MMR 835,采集到的 48 局 PVP 却赢了 37 局,胜率 77.08%。档案里的排位记录覆盖 2,004 局,1,023 胜,胜率 51.05%。两个口径差了 26.03 个百分点。

先拆对手。这 48 局里有 23 局面对完整五人人机,22 胜;5 局对面有部分 AI 槽位,4 胜;剩下 20 局是纯真人,11 胜。纯真人局胜率为 55%,和档案排位胜率接近。完整人机局占了将近一半样本,并贡献了 22 个胜场。

这名玩家在完整人机局的平均评分是 10.02,平均 5.48 杀、3.39 死、8.91 助攻,队内评分平均排第 2.70,输出占本队 24.33%。23 局里只有 2 局零击杀。采集记录里没有出现持续压低击杀和评分的表现。

再沿时间看,23 局完整人机对手可以拆出 7 个连段起点。每个起点往前取一条已采集 PVP 记录,其中 5 条排位、2 条娱乐,共 3 负 4 胜;4 条评分低于 6,2 条零击杀。数量太少,单靠这个玩家还看不出触发规律。

纯真人五排还能看到固定队。队友 A 最新档案为 95 星、ELO 2463、MMR 1658,同队 11 局里有 10 局评分高于目标玩家,平均评分 9.25 对 7.06。队友 B、C、E 分别为 74、74、113 星,ELO 在 2047~2750 之间。队友 D 的档案数值也高,这几局平均评分只有 5.38,低于目标玩家的 7.18。固定队里有几位表现稳定的大腿,也有一名档案强、当前几局表现较低的队友。

一名玩家的 48 局会同时混入组队和对手构成的影响。我又把完整人机连段起点放到全库里比较:目标组有 553 条记录,普通排位原始对照有 8,003 条;对照按本局开局月份和累计星数 5 星一档加权。全库对照按上一条已采集排位记录计算,目标组的败率为 86.44%,普通排位为 33.87%。

上一条记录的胜负和评分、击杀本来就紧密相关。固定胜负后再比,同为败局时,完整人机起点与普通排位的平均评分为 7.29 和 7.13;低于 6 分的比例为 29.35% 和 34.68%;零击杀比例为 12.79% 和 14.46%。同为胜局时,两组零击杀比例为 4.00% 和 4.16%。

77.1% 胜率和高比例 AI 对手、固定队中的高评分队友同时出现。全库里最稳定的关系是上一条已采集排位告负,低评分与零击杀没有显示出额外升高。梦游流能否改变后续匹配,当前数据还回答不了;下一轮可以提前定义低击杀、低评分组,连续记录随后遇到的对手。

匿名高采集胜率玩家的 AI 对手构成、真人固定队和全库上一条已采集排位记录的控制结果

五个人机站在同一边时,比赛有多快

我把双方十条记录完整的排位分成三组:一方五个人机、双方各一个人机、全场没有人机。先看全部样本:

对局类型对局数平均时长中位数10 分钟内12 分钟内20 分钟以上
一方五个人机48412:5212:1610.12%44.01%3.51%
双方各一个人机1,17616:3116:002.89%9.27%18.71%
全场没有人机23,86114:5714:176.19%21.70%11.59%

一方五个人机、双方各一个人机和正常排位按一分钟分档的时长分布

一方五个人机的 484 局里有 49 局不到 10 分钟,最短一局是 6:53。正常排位里同样有短局,23,861 局中有 1,476 局不到 10 分钟,最短是 5:22。两组在 8 分钟内的占比分别是 0.83% 和 1.52%,差距主要集中在 8~14 分钟:完整人机队有 63.43% 在这六分钟里结束。低于 12 分钟的 213 局,获胜方全部是完整人机队的对面一方。

这三组的段位构成差得很大。每边一个人机的样本有 91.84% 低于王者,正常排位只有 11.18%,直接拿原始中位数比较会混入段位影响。我沿用页面上的分段口径,只留每局真人平均累计星低于 92 的对局:

对局类型对局数中位数10 分钟内12 分钟内20 分钟以上
一方五个人机28312:0610.60%46.64%2.12%
双方各一个人机1,08016:002.69%9.07%18.06%
全场没有人机2,66815:571.91%8.85%19.53%

控制分段后,双方各一个人机与正常排位的分布几乎重合:中位数相差 3 秒,P10 都在 12:05 左右,P90 都是 21:57。完整人机队仍然早 3 分 51 秒结束,10 分钟内的占比是同分段正常排位的 5.54 倍。

我也按北京时间拆了开局小时。完整人机队在 23 点最多,21~23 点占 26.86%;正常排位在同一时段占 20.27%。双方各一个人机在 21 点最多,18~23 点合计占 49.66%,正常排位是 33.49%。

两种人机安排与正常排位在 24 小时内的开局分布

按每个小时的全部完整排位校正后,双方各一个人机在 19 点的出现率最高,为 8.22%。完整人机队的当小时出现率峰值落在 8 点,只有 13 局;把日期限制到数据较密集的 7 月 10~27 日,峰值会移到 17 点。当前库里的历史日期高度集中在 2026 年 7 月,采集又是在六个小时里集中完成的,这张小时图适合描述当前样本,固定投放时段还看不出来。

我又按北京时间的自然日拆了一次。图里列出库内有完整排位记录的 37 个日期,没有记录的日期不补成 0。7 月 28 日只覆盖到 02:14,共 299 局,摘要和峰值都把这一天排除了。

两种人机安排按北京时间自然日统计的每日场次数,以及占当天全部完整排位的比例

原始场次数在 7 月末快速增加。完整人机队的峰值是 7 月 26 日 90 局,双方各一个人机的峰值是 7 月 25 日 184 局。7 月 23~27 日承载了库内 75.72% 的完整排位,也承载了 68.18% 的完整人机队和 58.25% 的双方各一个人机局。战绩接口每人只返回最近十局,日期越早,留在窗口里的记录通常越少;查询到的玩家越多,同一天能拼出的对局也越多。场次数峰值主要描述这次采样的日期构成,系统当天是否增加投放仍然未知。

每日比例的分母是当天库内全部完整排位。我把 1,000 局设为摘要门槛,得到 7 月 21~27 日七个连续日期。完整人机队在 7 月 23 日达到 2.52%,7 月 27 日降到 0.92%;双方各一个人机从 7 月 21 日的 7.34% 降到 1.39%,中间只有 7 月 24 日出现一次小幅回升。两条线在这七天里都往下走。每天进入样本的玩家和分段构成还在变化,系统是否主动减少这两种安排,需要更长时间的持续采集才能回答。

它们选什么英雄、走哪一路

把两种安排分开后,分路差异很大。双方各一个人机的 2,352 条记录里,打野占 63.61%,对抗路占 23.04%,游走 7.61%,发育路 5.36%,中路只有 9 条。同一批排位的真人记录在五路上各占两成左右。

单个人机主要走打野,完整五人人机队的五路分布接近常规阵容

完整五人人机队按五路配人。484 支队伍里有 483 支五路齐全;每支队伍都用了五个不同英雄。把队内英雄 ID 排序后再比较,484 套组合一次也没有重复。只取这 2,420 条完整队记录,它们用过 92 个英雄,前十名合计占 26.57%。

双方各一个人机时,英雄选择集中得多:73 个英雄,前五名占 35.29%,前十名占 52.64%。这前五名全是打野,依次为宫本武藏、典韦、铠、诸葛亮和兰陵王。正常排位真人用过 131 个英雄,前十名合计占 19.67%。

双方各一个人机时,各分路最常选择的最多十个英雄,并与正常真人和同场真人对照

分路构成会放大这组差异,所以我又在每条分路内部重算了一遍,并加上同场真人作第二条基线。每边一个人机的打野里,宫本武藏占 12.37%,正常排位真人为 4.50%,同场真人为 8.05%;典韦分别是 12.17%、2.98% 和 7.12%。曜只排打野第七,5.82% 的选用率仍远高于两条真人基线的 0.68% 和 0.47%。对抗路的夏洛特是 9.41%,两条真人基线为 1.59% 和 1.44%。中路只有 9 条人机记录,这一列不作解读。

完整人机队也有自己的选择表。发育路孙尚香占 16.56%,正常真人和同场真人分别为 3.09% 和 3.92%;对抗路钟无艳是 9.86%,两条基线为 1.22% 和 0.64%;游走孙膑是 11.16%,两条基线为 2.60% 和 1.68%。

完整五人人机队各分路最常选择的十个英雄,并与两组真人基线对照

两种安排的英雄选择差得很大。双方各一个时,63.61% 的人机被分到打野,前十个英雄占了过半;凑成完整队伍时,五路基本齐全,前十名只占 26.57%。把分路和同场真人纳入对照后,夏洛特、曜、钟无艳、孙尚香和孙膑仍然出现得明显更多。这里统计的是选择频率,英雄强度和胜率需要另外计算。

它们会固定在数组最后一格吗

1442 的原始数组里,蓝方固定占 0~4,红方固定占 5~9。完整五人人机队会占满阵营内的每个槽位,所以下面只看单个人机那 2,390 个阵营。

单个人机会出现在十个绝对下标中的任何一个,阵营内最后一格占比最高

单个人机在阵营内五个槽位的占比分别是 17.07%、18.33%、20.38%、20.42%、23.81%。五个位置都会出现,最后一格数量最多,比均匀分布的 20% 高 3.81 个百分点。所有排位人机记录的蓝红方占比是 49.28% 和 50.72%,两边接近。

原始记录里还有一个看着很像位置的 dwPosOfTeam,这批人机的值全部为 0。它记录开黑队伍内部的序位;人机的 bTeamAcntNum 恒为 1,所以这里只会是 0。

反证也得说清楚。有 3 个这样的 uid,我发查档案请求之后拿到了完整档案,对战场次分别是 1888、2565、3385,MMR 一千五上下,其中一个在我库里从没以真人身份出现过。所以要么这批 uid 里混着真账号,要么人机直接借用了真人的身份信息。剩下的 5,499 个已经排进采集队列了,档案查询会给出答案,如果是凭空造的,服务器应该返回 15001

六度分隔在这里成不成立

19.7 万个玩家,同一局打过就连一条边,一共 152 万条边,这个规模跑 BFS 已经有点吃力,所以六度那部分是采样做的,连通性那部分是精确算的。

  • 99.9447% 的人两两之间连得上
  • 平均要经过 4.52 个中间人
  • 86.7% 的组合在六个中间人以内
  • 最远的一对隔了 8 个人

六度分隔说的是任意两人之间最多隔六个人,这里有 86.7% 的组合满足,剩下一成多要绕七到八个人,所以只能说勉强成立。

比这个数本身更有意思的是它在往上走。图只有 5 万人的时候,平均中间人是 3.93,六度以内的比例 99.7%,涨到 19 万人之后就变成 4.52 和 86.7% 了。采得越多路反而越长,原因是新采到的人大多只有一两条边,还挂在图的外围,跟核心区域之间只有很少的通路,等这些人也被反复采到,路径应该会重新缩短。

「任意两人能连上的比例」这个数不能拿采样估,这是我中途才意识到的。我一开始的做法是均匀取 40 个起点做 BFS,统计能到达多少人,估出来 99.9723%,四舍五入之后页面上显示成 100.0%,然后我随手挑两个人一试却连不上,看着自相矛盾。问题在于采样起点均匀取的话几乎必然全落在最大连通块里,小块里的人根本不会被选中当起点。改成按连通块大小精确算,sum(size choose 2) / (N choose 2),得到 99.9447%。最大块占 191,489 人,外面只剩 53 个,分在 28 人、17 人、3 人、3 人、2 人五个小块上,这些人打过的那几局里同局的其他人也都只被采到过一次,所以整块跟外面没有交集。

严格口径(同一方一起打过至少两次才算认识)下这张图非常稀疏,只有 518 个人有边。这个数字反映的其实是我的采样方式,按对局广度铺开的话同一批人很难被采到第二次,跟玩家真实的社交密度没什么关系。不过现在有了 bTeamAcntNum,开黑关系可以直接读出来,不用再从重复同场里推,这块还没重做。

不用告诉它谁是坦克,数据自己认得出来

这一条是我做的时候顺着别的问题撞出来的,做完自己还挺得意。我没有给任何英雄标过职业,只算了每个人的承伤、治疗、输出各占本队总量的百分比,然后按英雄取平均,三个维度各自排一遍,结果是这样:

承伤占比最高出场承伤治疗输出
苏烈2,09131.5%41.0%11.6%
刘禅2,12830.8%18.0%10.8%
程咬金1,61930.6%61.0%18.5%
夏侯惇2,58530.0%25.9%18.4%
治疗占比最高出场承伤治疗输出
程咬金1,61930.6%61.0%18.5%
蔡文姬3,63925.7%57.3%7.7%
元流之子(辅助)2,78927.2%52.7%11.8%
桑启2,25923.1%51.1%11.9%
输出占比最高出场承伤治疗输出
沈梦溪3,98614.3%6.7%29.1%
海诺2,04727.7%33.1%28.0%
元流之子(射手)5,02617.0%15.7%27.9%
戈娅2,36518.9%11.8%27.7%

承伤榜前四位都是前排英雄,输出榜前四位都有持续输出能力。程咬金同时排进承伤和治疗两张表的前列,符合他的回血机制。元流之子的辅助、射手形态在数据里是两个英雄,一个进了治疗榜,另一个进了输出榜。

英雄胜率只是这批样本的快照

排位里出场最多的六个英雄,胜率全部挤在 50% 附近:

出场最多出场胜率
后羿6,70851.46%
5,86151.63%
甄姬5,73149.99%
朵莉亚5,08448.84%
妲己4,47749.85%
赵云4,46650.94%

而胜率最高的那批(出场 800 场以上),没有一个出现在上面的名单里:

胜率最高出场胜率
沈梦溪2,38261.42%
盾山1,28459.11%
戈娅1,41258.85%
马超2,17156.98%
关羽2,08856.85%
1,87156.55%

控制台的全模式英雄视图把出场次数和胜率画成散点,绝大多数英雄都挤在五成胜率附近

另一头的样本胜率也拉得很开:不知火舞 45.27%、吕布 45.48%、澜 45.89%、马可波罗 45.92%,沈梦溪和不知火舞之间相差 16 个百分点。沈梦溪的输出占比也排在第一,平均打出本队 29.1% 的英雄伤害。

这组数字没有控制玩家熟练度、阵容、禁选、分段和采样时间,胜率高低只能描述我采到的这些对局。它不能直接充当版本强度榜。出场榜与胜率榜缺少重叠也是样本现象,玩家为什么选某个英雄,结算数据回答不了。

账号年限与相关性

每个玩家取最新档案,一共 6,494 人。按 365 天折一年,玩了 9 年以上的有 2,599 人,占 40.02%;10 年以上有 900 人,占 13.86%。对战超过一万场的有 3,277 人,刚好过半,超过三万场的还有 207 人。

账号年限分布和各年限玩家的平均累计场次,账号越老平均场次越高

9 年以上玩家平均打了 16,181 场、上过 21.8 次王者,其余玩家是 8,439 场和 12.8 次。全库最高为 58,959 场,这个账号有 3,796 个游戏日,长期平均每天 15.53 场。

这些数字很容易让人把「玩得久」和「打得强」连在一起,所以我把档案里的主要数值做了一张完整的皮尔逊相关系数矩阵。每个人只取最新快照,共 6,494 个样本。

玩家档案各项数值的完整相关性矩阵,颜色和数字同时表示线性相关方向与强度

最强的几组大多来自口径重叠:累计星数与 MMR 是 0.997,累计星数与 ELO 是 0.992,MMR 与 ELO 是 0.994,皮肤收藏值与总收藏值是 0.992。对战场次与被赞为 0.902,与排位场次为 0.901,与王者次数为 0.834。新增的累计 MVP 也一样,它与总场次的相关系数是 0.862,与累计被赞是 0.792。这些累计量都会随游戏总量增长,正文里逐项解释没有多少价值。

胜率有两种口径。档案排位胜率要求排位超过 20 局,覆盖 6,490 人;采集 PVP 胜率用库里实际见到的所有多人 PVP 对局,排除明确的人机模式和 AI 参战者,同样要求超过 20 局,覆盖 1,835 人。

胜率与档案排位胜率 Pearson采集 PVP 胜率 Pearson采集 PVP 胜率 Spearman
累计星数0.1080.1150.329
ELO0.0950.1270.377
MMR0.1110.1130.330

这些系数都是正数。Pearson 落在 0.10 左右,线性关系很弱;Spearman 为 0.33~0.38,按排名看会清楚一些,离紧密对应仍有很大距离。采集 PVP 胜率与档案排位胜率的 Pearson 是 0.366,Spearman 是 0.320。

离群点两端都很明显。上面那名 65 星玩家采集 48 局,胜率 77.1%,ELO 1683、MMR 835,档案排位胜率为 51.0%。另一端有一名匿名玩家采集 42 局,胜率 33.3%,档案却是 238 星、ELO 4000、MMR 3944,排位胜率 61.7%。二十到五十局的窗口足以和长期档案拉开很大差距。

星数与 ELO、MMR 的关系接近完全正相关,样本里仍有少数错位。两个匿名档案当前累计星数都是 0,ELO/MMR 分别为 2813/2095 和 2668/1761;另一些玩家为 97 星、ELO 2458~2468、MMR 1600。赛季重置、字段更新时间差和真实的评分差异都可能造成这种记录,当前快照无法区分具体原因。

游戏天数与对战场次的相关系数是 0.563,与王者次数是 0.602;到了 MMR 和累计星数,只剩 0.259 和 0.256。游戏天数与排位胜率为 -0.233。账号年限与场次有中等相关,与当前实力指标的线性相关较弱。相关系数只衡量线性关系,也不提供因果方向,采样偏向高分段这一点同样会影响结果。

累计值除以对应场次后,关系变了很多。6,494 名玩家平均被队友点赞 5,916.7 次,中位数 5,136 次;换成每场以后,均值是 0.565 次,中位数是 0.529 次。累计 MVP 平均 1,052.5 次,中位数 884 次;MVP 率的均值是 13.44%,中位数是 11.61%。

玩家累计被赞、场均被赞、累计 MVP 与 MVP 率的汇总,以及场均被赞和 MVP 率分布

MVP 率的分母需要单独说明。档案里的 dwMvpdwCount 属于同一组统计,dwCount 只覆盖总对战场次的一部分,中位覆盖率为 75.55%。直接除以总场次会把 MVP 率中位数从 11.61% 压到 8.82%,所以图里使用 dwMvp / dwCount。比例分布收录分母大于 0 的玩家,相关性矩阵要求对应分母大于 20。

场均被赞与排位胜率的相关系数是 0.463,与游戏天数是 -0.473,与总场次是 -0.394。最后一项共享了总场次这个分母,比例指标可能由此产生额外的数学相关。数据库里也没有点赞功能的启用时间和历史模式范围,这组负相关暂时只记作样本现象。

MVP 率与巅峰赛积分的相关系数是 0.474,与最强分路战力是 0.403,与排位胜率是 0.399,与 MMR 是 0.374;它和总场次只剩 0.076。场均被赞和 MVP 率之间则是 -0.012,两种比例之间几乎没有线性相关。英雄、分路、组队关系和局内行为还没有纳入这张矩阵,点赞具体受什么影响,现有档案拆不出来。

档案里还有几项可以单独记一下。人均被对手点赞 569 次,队友点赞约是它的 10.4 倍。巅峰赛有场次记录的玩家是 4,095 人,占 63%,平均 1,646 分,最高 2,435 分。

苹果区和安卓区在这批样本里也有差异:

渠道系统人数平均 ELO平均场次
手Q苹果7453,56012,577
手Q安卓2,1743,34712,328
微信苹果1,3493,35411,828
微信安卓2,2263,10810,339

两个渠道的苹果样本平均 ELO 都高两百多分。队列从我自己的历史战绩向外展开,各区人数差异很大,这张表只描述当前样本,无法外推到全服。安卓和苹果大区是我从游戏内存里的 tdir 区服树分出来的:1xxx、3xxx 是安卓,2xxx、4xxx 是苹果。

几个零散观察

用单项 KDA 排序时,25,526 局排位里有 11.72% 的全场最高 KDA 出现在败方。KDA 只覆盖击杀、死亡和助攻,这个比例适合描述单项数据,承担不了「谁打得最好」的判断。

排位里最高的一次连续击杀是 31。五连以上占 14.35% 的人次,十连以上占 1.49%。

按北京时间拆开开局时段,21 点最多,共 1,857 局;凌晨 0 点有 1,598 局,中午 12 点有 870 局,早上 7 点最低,共 361 局。图里的时间来自玩家的历史战绩,覆盖很多天,和采集发生的七个小时无关。

控制台按北京时间画出的开局时段分布,21 点和 22 点的参战人次最高

另有 419 个人的昵称被系统改成「违规昵称」,占名册的 0.21%。昵称同时存在于每条战绩和档案快照里,按时间排序就能得到改名记录;19.7 万人中有 1,022 人能看到至少一次改名。

dwControlTime 这个字段没有文档,我最初按字面理解成被控时间,结果赢方的值反而更高。按英雄取平均值排序后,前面是墨子、盘古、项羽、武则天、张良和盾山,末尾是明世隐、马可波罗、影。这个顺序说明它记录的是自己控住别人的累计时间。协议里有不少语义不明的字段,用已知英雄特征校验分布,比看字段名猜含义可靠。

榜单,以及一条差点误导我的记录

榜单这种东西最好看,但不同模式的数值不能直接比较。

我第一次把伤害榜拉出来,头名是 91 万对英雄伤害,点进去一看是 game_type=6,两个人的 1v1 单挑,打了 36 分钟。而且两个人的伤害和承伤正好互为镜像,一个打出 91 万受了 34 万,另一个反过来,全场就他俩,不镜像才不正常。

还有一条 25.8 万经济的记录,第一眼看着像开挂。查下来是 game_type=5 配一张特殊地图,输的一方整队是人机槽位,赢的五个人经济全部落在 25.6 到 25.8 万之间。再看分项经济,野怪 902、打野 1080、上路兵线 2560、中路 621,加起来只有五千多,总额字段却是 25.8 万。这一局的 ullMatchTypeBits 是 0,普通排位是 1,全库也只有这一局的经济超过 10 万。这个模式显然采用了另一套总额口径。

所以我给榜单每一行都带上了模式,也支持按模式筛选。只看排位的话:

项目记录
单局控制别人最久197 秒
单局治疗最多51.6 万
单局对英雄伤害最高58.8 万
单局承伤最高50.3 万
最长一局34 分 24 秒

后面想做的

结算数据里有个 stMvpScoreDetail,展开是五个分项得分,而每个人的最终评分 iMvpScoreTTH 也在同一条记录里,这个字段存的是放大 100 倍的整数,818 就是游戏里显示的 8.18 分。三十六万条样本、五个自变量一个因变量,逆出结算评分的公式应该是够用的。这件事我觉得最有意思,游戏从来没公开过评分到底怎么算,而玩家为这个分数已经吵了很多年,每次拿了 MVP 或者被判低分都要争论一番。

stHighLightInfo 是高光时刻,astSkillStatisticInfo 是每个技能的使用统计,经济还按上中下三路和打野分开存着。这些都还躺在原始 JSON 里没动过,等于说该拿的数据早就拿到了,只是还没来得及分析。

还有那 5,499 个待验证的人机 uid,设备回来跑一轮就知道了。

评论区加载中…