一张赛事公告背后要回答的六个问题

玩家晚上九点骑车经过港口城市的旧仓库区,路边的公告栏刷新出一条消息:“今晚十点,河堤球场,三对三街头篮球挑战,限时两小时,已有五名选手报名。”这条消息看起来很普通,但如果它是AI当场组织出来的,系统在它出现之前至少要回答六个问题:现在是什么时间、什么天气;这附近有没有能打篮球的场地,灯亮不亮;打什么规则;谁会来;玩家的水平适合什么对手;比赛打完以后,世界里什么东西要跟着变。

很多开放世界的“随机事件”只回答了其中一两个,于是就出现了下着暴雨的户外篮球赛、没有坡度的平地速降赛、离海岸两公里的冲浪比赛。在im体育里,我们把一场动态赛事的诞生拆成五个顺序步骤:读取世界状态、筛选设施与地点、拼装规则、邀请参赛NPC、把结果写回世界。下面用三场模拟赛事贯穿整个流程:城市夜间街头篮球挑战、山区限时自行车赛、海边冲浪赛。

第一步:读取世界状态,先决定“今天不该办什么”

生成器做的第一件事不是挑选好玩的比赛,而是排除不可能的比赛。它读取的世界状态包括:

  • 时间:一天中的时段、星期、季节。凌晨三点不适合拉满观众的街头赛,但适合一场小范围的夜骑挑战。
  • 天气:降水、风速风向、气温、能见度,以及过去几小时的趋势。暴雪天整个城市的户外球类赛事直接关闭;雨停不到一小时的沥青路面仍按湿滑处理。
  • 环境派生量:雪况、海况、路面状况。冲浪赛需要的是浪高、浪向、破浪点、风、潮汐和海流的组合,而不只是“今天有浪”。
  • 人群与NPC分布:哪些NPC此刻在这个城区,谁在训练,谁受伤,谁刚打完一场比赛体力未恢复。
  • 近期赛事记录:同一地点同一项目三天内已经办过两次,就降低它再被选中的权重。

以设计示例来说:周五晚上九点,港口城市晴,气温十四度,微风;山区下午有过阵雨,林道偏湿;海岸涌浪一米二、周期十秒,风从陆地吹向海面,晚上十一点前后是中潮。这一组状态会让三个区域各自得到一张“可办项目清单”,暴雨天或暴雪天这张清单可能只剩室内项目。

第二步:设施与地点筛选,场地必须真的存在

体育赛事和一般的开放世界任务最大的区别,是它离不开设施。篮球要篮筐和硬质地面,夜间还要照明;速降要足够的坡度和可封闭的路段;冲浪要在破浪点附近有能下水的海岸;滑板要有台阶、扶手或道具。我们给地图上的每个地点打上设施标签,并记录它的当前可用性。

赛事类型 必需设施 会导致排除的状态
夜间街头篮球篮筐、硬地、照明、足够的观众站位 降水、地面积水、照明维修中
山区限时自行车赛 连续坡道、可封闭路段、起终点空地 路面结冰、落石、能见度过低
海边冲浪赛稳定破浪点、下水通道、岸边裁判位 浪高不足或过大、强向岸风、离岸流警告
街头滑板赛 一组可串联的Spot、平整地面 地面潮湿、施工围挡、人流高峰

回到三场示例。河堤球场有两个篮筐、灯光正常,符合条件;另一个旧小区球场灯坏了,被排除。山区有两条候选路线,一条是下午阵雨后仍偏泥泞的林道,一条是铺装盘山路,生成器选了后者,并把林道放进“明天再评估”的列表。海岸三个破浪点中,礁石底的那个在中潮时浪型最好,就选它。

这一步看起来繁琐,却是玩家判断“这个世界讲不讲道理”的关键。一场设施不对的比赛只要出现一次,玩家就会开始怀疑后面所有的赛事都是随手摆出来的。

第三步:规则拼装,比赛形式跟着地点和人走

确定了地点,下一步是决定怎么比。我们的做法不是从一个巨大的赛事库里整条抽取,而是从规则部件拼装:赛制(淘汰、积分、计时、对抗)、人数、时长、胜负条件、特殊限制。部件之间有兼容规则,拼出来之后还要跑一遍可行性检查。

夜间篮球:河堤球场只有半场,所以用三对三半场;晚上十点到十二点的时间窗,采用先到十一分者胜的短局、打三轮淘汰;附加规则是“每队至少一名本地俱乐部球员”,因为这座城市的篮球圈有几个街区俱乐部,这条规则能把它们拉进来。

山区自行车赛:盘山路全长约四公里,海拔落差三百米左右,做成个人计时赛;因为是晚上,限定必须开车灯,并把最险的两个发夹弯设为减速检查点。检查点不是为了难为玩家,而是可行性检查发现,在夜间能见度下,这两个弯的入弯速度上限低于路线其他部分。

冲浪赛:中潮窗口大约九十分钟,于是设为两轮、每轮二十分钟、每人取两道最高分;有优先权规则,避免多人抢同一道浪。潮位继续上涨后破浪点会移动,所以比赛必须在窗口内结束,不能随意延长。

规则拼装还要参考玩家水平。同样是冲浪赛,面对刚能稳定起乘的玩家,生成器会把它做成社区练习赛,允许长板、放宽计分;面对已经常在中大浪里做回切的玩家,才会拼出职业邀请赛的规则。这里调的是赛制和对手阵容,而不是偷偷改浪。

第四步:邀请参赛NPC,谁来不是抽签决定的

一场比赛好不好玩,很大程度取决于对手。我们不从NPC池里随机抽人,而是向附近的NPC“发邀请”,由每个NPC按自己的目标、日程和状态决定是否参加。一个正在备战下周正式联赛的篮球NPC,可能拒绝今晚的街头赛,免得受伤;一个排名刚被玩家超过的NPC,则很可能主动报名。NPC的运动目标怎么影响这类决定,可以参考NPC的运动目标这篇文章。

在示例里,街头篮球赛收到五个NPC报名,其中两位是同一俱乐部的搭档,一位是上个月在另一个球场输给玩家的后卫,他的记忆里写着“玩家习惯往左突破”。山区自行车赛只有三个NPC报名,因为下午的雨让不少骑手推迟了夜骑计划。冲浪赛则有六人参加,包括一位刚从雪山搬到海边、冲浪还在进步中的单板滑雪选手。

这些NPC在比赛中变强的方式也有约束:更好的路线、更合理的判断、针对玩家习惯调整防守、适应当晚的风和光线、更少失误。他们不能读取玩家的手柄输入,不能在落后时获得隐藏加速,也不能无视体力。一个前一晚刚打完比赛的NPC,今晚第三轮的冲刺速度就应该下降。

第五步:结果写回世界,比赛才算真正发生过

如果比赛结束后什么都没改变,它就只是一次一次性的小游戏。我们要求每场动态赛事至少写回以下几类信息:

  1. 排名与声望:参赛者的项目排名变化,本地圈子里的名气变化。
  2. NPC记忆:谁赢了谁、比分、关键回合、对玩家风格的新判断;如果两人连续交手且互有胜负,可能形成宿敌关系。
  3. NPC状态:体力消耗、轻伤、信心变化,这些会影响他们接下来几天的训练和报名决定。
  4. 地点记录:这个球场、这段山路、这个破浪点办过什么比赛,降低短期内重复举办的概率,也可能让某个地点逐渐成为固定赛点。
  5. 玩家成长:项目技术经验、解锁的邀请渠道、结识的俱乐部。

示例里,玩家在篮球赛第二轮输给了那位记得他左突习惯的后卫,这次失利被写进双方记忆;后卫所在俱乐部的名气上升,一周后城市里生成了一场俱乐部对抗赛,而玩家因为参加过那场街头赛,收到了另一家俱乐部的补员邀请。一场夜里临时组织的比赛,就这样变成了后续事件的起点。玩家在im体育App里查看赛事历史时,能看到这条前因后果链。

生成器最常见的四种失败

我们在原型里反复遇到的问题,大多不是“生成不出来”,而是“生成出了不该有的东西”:

  • 天气变化后没有撤赛:赛事生成时晴天,开赛前半小时开始下雨,比赛却照常进行。解决办法是在开赛前重新校验一次世界状态,必要时延期或改为室内。
  • 地点饱和:某个设施条件特别好的球场被反复选中,整座城市的篮球赛都挤在一个地方。需要地点冷却和分散权重。
  • NPC分身:同一个NPC同一时段出现在两场比赛的报名表上。报名必须占用NPC的日程时间。
  • 难度跳变:玩家赢了一场社区赛,下一场直接面对职业选手。难度的提升应来自对手阵容的逐步变化,而不是一次跳级。

这些失败提醒我们,动态赛事和动态体育赛事里讨论的写死赛事并不对立:手写的规则部件和约束表提供骨架,生成器只负责在骨架内组合。完全随机的比赛不是动态,而是噪声。

一场你没见过的比赛,前提是它讲得出来历

回到标题的问题:AI体育开放世界能不能自己组织一场玩家从来没见过的比赛?在im体育大模型的设计里,答案是可以,但“没见过”只是结果,“讲得出来历”才是要求。玩家可能从没见过“中潮窗口下的两轮冲浪赛,参赛者包括一位刚转项的滑雪选手”,但当他看到这场比赛时,应该能理解它为什么是今晚、为什么在这片海岸、为什么是这些人。体育事件持续地、有原因地发生,世界才像一个一直有人在运动的地方。